Include errno.h, string.h, unistd.h. Don't declare errno, strerror.
[emacs.git] / src / xfns.c
blob8edbd66b160df0e0fd8abeb7c7fb586e5d29a60d
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
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 "fontset.h"
43 #include "systime.h"
44 #include "termhooks.h"
45 #include "atimer.h"
47 #ifdef HAVE_X_WINDOWS
49 #include <ctype.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
53 #ifndef VMS
54 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
55 #include "bitmaps/gray.xbm"
56 #else
57 #include <X11/bitmaps/gray>
58 #endif
59 #else
60 #include "[.bitmaps]gray.xbm"
61 #endif
63 #ifdef USE_X_TOOLKIT
64 #include <X11/Shell.h>
66 #ifndef USE_MOTIF
67 #include <X11/Xaw/Paned.h>
68 #include <X11/Xaw/Label.h>
69 #endif /* USE_MOTIF */
71 #ifdef USG
72 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
73 #include <X11/Xos.h>
74 #define USG
75 #else
76 #include <X11/Xos.h>
77 #endif
79 #include "widget.h"
81 #include "../lwlib/lwlib.h"
83 #ifdef USE_MOTIF
84 #include <Xm/Xm.h>
85 #include <Xm/DialogS.h>
86 #include <Xm/FileSB.h>
87 #endif
89 /* Do the EDITRES protocol if running X11R5
90 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
92 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
93 #define HACK_EDITRES
94 extern void _XEditResCheckMessages ();
95 #endif /* R5 + Athena */
97 /* Unique id counter for widgets created by the Lucid Widget Library. */
99 extern LWLIB_ID widget_id_tick;
101 #ifdef USE_LUCID
102 /* This is part of a kludge--see lwlib/xlwmenu.c. */
103 extern XFontStruct *xlwmenu_default_font;
104 #endif
106 extern void free_frame_menubar ();
107 extern double atof ();
109 #endif /* USE_X_TOOLKIT */
111 #define min(a,b) ((a) < (b) ? (a) : (b))
112 #define max(a,b) ((a) > (b) ? (a) : (b))
114 #ifdef HAVE_X11R4
115 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
116 #else
117 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
118 #endif
120 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
121 it, and including `bitmaps/gray' more than once is a problem when
122 config.h defines `static' as an empty replacement string. */
124 int gray_bitmap_width = gray_width;
125 int gray_bitmap_height = gray_height;
126 unsigned char *gray_bitmap_bits = gray_bits;
128 /* The name we're using in resource queries. Most often "emacs". */
130 Lisp_Object Vx_resource_name;
132 /* The application class we're using in resource queries.
133 Normally "Emacs". */
135 Lisp_Object Vx_resource_class;
137 /* Non-zero means we're allowed to display a busy cursor. */
139 int display_busy_cursor_p;
141 /* The background and shape of the mouse pointer, and shape when not
142 over text or in the modeline. */
144 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
145 Lisp_Object Vx_busy_pointer_shape;
147 /* The shape when over mouse-sensitive text. */
149 Lisp_Object Vx_sensitive_text_pointer_shape;
151 /* Color of chars displayed in cursor box. */
153 Lisp_Object Vx_cursor_fore_pixel;
155 /* Nonzero if using X. */
157 static int x_in_use;
159 /* Non nil if no window manager is in use. */
161 Lisp_Object Vx_no_window_manager;
163 /* Search path for bitmap files. */
165 Lisp_Object Vx_bitmap_file_path;
167 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
169 Lisp_Object Vx_pixel_size_width_font_regexp;
171 /* Evaluate this expression to rebuild the section of syms_of_xfns
172 that initializes and staticpros the symbols declared below. Note
173 that Emacs 18 has a bug that keeps C-x C-e from being able to
174 evaluate this expression.
176 (progn
177 ;; Accumulate a list of the symbols we want to initialize from the
178 ;; declarations at the top of the file.
179 (goto-char (point-min))
180 (search-forward "/\*&&& symbols declared here &&&*\/\n")
181 (let (symbol-list)
182 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
183 (setq symbol-list
184 (cons (buffer-substring (match-beginning 1) (match-end 1))
185 symbol-list))
186 (forward-line 1))
187 (setq symbol-list (nreverse symbol-list))
188 ;; Delete the section of syms_of_... where we initialize the symbols.
189 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
190 (let ((start (point)))
191 (while (looking-at "^ Q")
192 (forward-line 2))
193 (kill-region start (point)))
194 ;; Write a new symbol initialization section.
195 (while symbol-list
196 (insert (format " %s = intern (\"" (car symbol-list)))
197 (let ((start (point)))
198 (insert (substring (car symbol-list) 1))
199 (subst-char-in-region start (point) ?_ ?-))
200 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
201 (setq symbol-list (cdr symbol-list)))))
205 /*&&& symbols declared here &&&*/
206 Lisp_Object Qauto_raise;
207 Lisp_Object Qauto_lower;
208 Lisp_Object Qbar;
209 Lisp_Object Qborder_color;
210 Lisp_Object Qborder_width;
211 Lisp_Object Qbox;
212 Lisp_Object Qcursor_color;
213 Lisp_Object Qcursor_type;
214 Lisp_Object Qgeometry;
215 Lisp_Object Qicon_left;
216 Lisp_Object Qicon_top;
217 Lisp_Object Qicon_type;
218 Lisp_Object Qicon_name;
219 Lisp_Object Qinternal_border_width;
220 Lisp_Object Qleft;
221 Lisp_Object Qright;
222 Lisp_Object Qmouse_color;
223 Lisp_Object Qnone;
224 Lisp_Object Qouter_window_id;
225 Lisp_Object Qparent_id;
226 Lisp_Object Qscroll_bar_width;
227 Lisp_Object Qsuppress_icon;
228 extern Lisp_Object Qtop;
229 Lisp_Object Qundefined_color;
230 Lisp_Object Qvertical_scroll_bars;
231 Lisp_Object Qvisibility;
232 Lisp_Object Qwindow_id;
233 Lisp_Object Qx_frame_parameter;
234 Lisp_Object Qx_resource_name;
235 Lisp_Object Quser_position;
236 Lisp_Object Quser_size;
237 extern Lisp_Object Qdisplay;
238 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
239 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
241 /* The below are defined in frame.c. */
243 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
244 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
245 extern Lisp_Object Qtool_bar_lines;
247 extern Lisp_Object Vwindow_system_version;
249 Lisp_Object Qface_set_after_frame_default;
252 /* Error if we are not connected to X. */
254 void
255 check_x ()
257 if (! x_in_use)
258 error ("X windows are not in use or not initialized");
261 /* Nonzero if we can use mouse menus.
262 You should not call this unless HAVE_MENUS is defined. */
265 have_menus_p ()
267 return x_in_use;
270 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
271 and checking validity for X. */
273 FRAME_PTR
274 check_x_frame (frame)
275 Lisp_Object frame;
277 FRAME_PTR f;
279 if (NILP (frame))
280 frame = selected_frame;
281 CHECK_LIVE_FRAME (frame, 0);
282 f = XFRAME (frame);
283 if (! FRAME_X_P (f))
284 error ("Non-X frame used");
285 return f;
288 /* Let the user specify an X display with a frame.
289 nil stands for the selected frame--or, if that is not an X frame,
290 the first X display on the list. */
292 static struct x_display_info *
293 check_x_display_info (frame)
294 Lisp_Object frame;
296 if (NILP (frame))
298 struct frame *sf = XFRAME (selected_frame);
300 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
301 return FRAME_X_DISPLAY_INFO (sf);
302 else if (x_display_list != 0)
303 return x_display_list;
304 else
305 error ("X windows are not in use or not initialized");
307 else if (STRINGP (frame))
308 return x_display_info_for_name (frame);
309 else
311 FRAME_PTR f;
313 CHECK_LIVE_FRAME (frame, 0);
314 f = XFRAME (frame);
315 if (! FRAME_X_P (f))
316 error ("Non-X frame used");
317 return FRAME_X_DISPLAY_INFO (f);
322 /* Return the Emacs frame-object corresponding to an X window.
323 It could be the frame's main window or an icon window. */
325 /* This function can be called during GC, so use GC_xxx type test macros. */
327 struct frame *
328 x_window_to_frame (dpyinfo, wdesc)
329 struct x_display_info *dpyinfo;
330 int wdesc;
332 Lisp_Object tail, frame;
333 struct frame *f;
335 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
337 frame = XCAR (tail);
338 if (!GC_FRAMEP (frame))
339 continue;
340 f = XFRAME (frame);
341 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
342 continue;
343 if (f->output_data.x->busy_window == wdesc)
344 return f;
345 #ifdef USE_X_TOOLKIT
346 if ((f->output_data.x->edit_widget
347 && XtWindow (f->output_data.x->edit_widget) == wdesc)
348 /* A tooltip frame? */
349 || (!f->output_data.x->edit_widget
350 && FRAME_X_WINDOW (f) == wdesc)
351 || f->output_data.x->icon_desc == wdesc)
352 return f;
353 #else /* not USE_X_TOOLKIT */
354 if (FRAME_X_WINDOW (f) == wdesc
355 || f->output_data.x->icon_desc == wdesc)
356 return f;
357 #endif /* not USE_X_TOOLKIT */
359 return 0;
362 #ifdef USE_X_TOOLKIT
363 /* Like x_window_to_frame but also compares the window with the widget's
364 windows. */
366 struct frame *
367 x_any_window_to_frame (dpyinfo, wdesc)
368 struct x_display_info *dpyinfo;
369 int wdesc;
371 Lisp_Object tail, frame;
372 struct frame *f, *found;
373 struct x_output *x;
375 found = NULL;
376 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
378 frame = XCAR (tail);
379 if (!GC_FRAMEP (frame))
380 continue;
382 f = XFRAME (frame);
383 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
385 /* This frame matches if the window is any of its widgets. */
386 x = f->output_data.x;
387 if (x->busy_window == wdesc)
388 found = f;
389 else if (x->widget)
391 if (wdesc == XtWindow (x->widget)
392 || wdesc == XtWindow (x->column_widget)
393 || wdesc == XtWindow (x->edit_widget))
394 found = f;
395 /* Match if the window is this frame's menubar. */
396 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
397 found = f;
399 else if (FRAME_X_WINDOW (f) == wdesc)
400 /* A tooltip frame. */
401 found = f;
405 return found;
408 /* Likewise, but exclude the menu bar widget. */
410 struct frame *
411 x_non_menubar_window_to_frame (dpyinfo, wdesc)
412 struct x_display_info *dpyinfo;
413 int wdesc;
415 Lisp_Object tail, frame;
416 struct frame *f;
417 struct x_output *x;
419 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
421 frame = XCAR (tail);
422 if (!GC_FRAMEP (frame))
423 continue;
424 f = XFRAME (frame);
425 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
426 continue;
427 x = f->output_data.x;
428 /* This frame matches if the window is any of its widgets. */
429 if (x->busy_window == wdesc)
430 return f;
431 else if (x->widget)
433 if (wdesc == XtWindow (x->widget)
434 || wdesc == XtWindow (x->column_widget)
435 || wdesc == XtWindow (x->edit_widget))
436 return f;
438 else if (FRAME_X_WINDOW (f) == wdesc)
439 /* A tooltip frame. */
440 return f;
442 return 0;
445 /* Likewise, but consider only the menu bar widget. */
447 struct frame *
448 x_menubar_window_to_frame (dpyinfo, wdesc)
449 struct x_display_info *dpyinfo;
450 int wdesc;
452 Lisp_Object tail, frame;
453 struct frame *f;
454 struct x_output *x;
456 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
458 frame = XCAR (tail);
459 if (!GC_FRAMEP (frame))
460 continue;
461 f = XFRAME (frame);
462 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
463 continue;
464 x = f->output_data.x;
465 /* Match if the window is this frame's menubar. */
466 if (x->menubar_widget
467 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
468 return f;
470 return 0;
473 /* Return the frame whose principal (outermost) window is WDESC.
474 If WDESC is some other (smaller) window, we return 0. */
476 struct frame *
477 x_top_window_to_frame (dpyinfo, wdesc)
478 struct x_display_info *dpyinfo;
479 int wdesc;
481 Lisp_Object tail, frame;
482 struct frame *f;
483 struct x_output *x;
485 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
487 frame = XCAR (tail);
488 if (!GC_FRAMEP (frame))
489 continue;
490 f = XFRAME (frame);
491 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
492 continue;
493 x = f->output_data.x;
495 if (x->widget)
497 /* This frame matches if the window is its topmost widget. */
498 if (wdesc == XtWindow (x->widget))
499 return f;
500 #if 0 /* I don't know why it did this,
501 but it seems logically wrong,
502 and it causes trouble for MapNotify events. */
503 /* Match if the window is this frame's menubar. */
504 if (x->menubar_widget
505 && wdesc == XtWindow (x->menubar_widget))
506 return f;
507 #endif
509 else if (FRAME_X_WINDOW (f) == wdesc)
510 /* Tooltip frame. */
511 return f;
513 return 0;
515 #endif /* USE_X_TOOLKIT */
519 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
520 id, which is just an int that this section returns. Bitmaps are
521 reference counted so they can be shared among frames.
523 Bitmap indices are guaranteed to be > 0, so a negative number can
524 be used to indicate no bitmap.
526 If you use x_create_bitmap_from_data, then you must keep track of
527 the bitmaps yourself. That is, creating a bitmap from the same
528 data more than once will not be caught. */
531 /* Functions to access the contents of a bitmap, given an id. */
534 x_bitmap_height (f, id)
535 FRAME_PTR f;
536 int id;
538 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
542 x_bitmap_width (f, id)
543 FRAME_PTR f;
544 int id;
546 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
550 x_bitmap_pixmap (f, id)
551 FRAME_PTR f;
552 int id;
554 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
558 /* Allocate a new bitmap record. Returns index of new record. */
560 static int
561 x_allocate_bitmap_record (f)
562 FRAME_PTR f;
564 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
565 int i;
567 if (dpyinfo->bitmaps == NULL)
569 dpyinfo->bitmaps_size = 10;
570 dpyinfo->bitmaps
571 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
572 dpyinfo->bitmaps_last = 1;
573 return 1;
576 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
577 return ++dpyinfo->bitmaps_last;
579 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
580 if (dpyinfo->bitmaps[i].refcount == 0)
581 return i + 1;
583 dpyinfo->bitmaps_size *= 2;
584 dpyinfo->bitmaps
585 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
586 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
587 return ++dpyinfo->bitmaps_last;
590 /* Add one reference to the reference count of the bitmap with id ID. */
592 void
593 x_reference_bitmap (f, id)
594 FRAME_PTR f;
595 int id;
597 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
600 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
603 x_create_bitmap_from_data (f, bits, width, height)
604 struct frame *f;
605 char *bits;
606 unsigned int width, height;
608 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
609 Pixmap bitmap;
610 int id;
612 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
613 bits, width, height);
615 if (! bitmap)
616 return -1;
618 id = x_allocate_bitmap_record (f);
619 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
620 dpyinfo->bitmaps[id - 1].file = NULL;
621 dpyinfo->bitmaps[id - 1].refcount = 1;
622 dpyinfo->bitmaps[id - 1].depth = 1;
623 dpyinfo->bitmaps[id - 1].height = height;
624 dpyinfo->bitmaps[id - 1].width = width;
626 return id;
629 /* Create bitmap from file FILE for frame F. */
632 x_create_bitmap_from_file (f, file)
633 struct frame *f;
634 Lisp_Object file;
636 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
637 unsigned int width, height;
638 Pixmap bitmap;
639 int xhot, yhot, result, id;
640 Lisp_Object found;
641 int fd;
642 char *filename;
644 /* Look for an existing bitmap with the same name. */
645 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
647 if (dpyinfo->bitmaps[id].refcount
648 && dpyinfo->bitmaps[id].file
649 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
651 ++dpyinfo->bitmaps[id].refcount;
652 return id + 1;
656 /* Search bitmap-file-path for the file, if appropriate. */
657 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
658 if (fd < 0)
659 return -1;
660 /* XReadBitmapFile won't handle magic file names. */
661 if (fd == 0)
662 return -1;
663 emacs_close (fd);
665 filename = (char *) XSTRING (found)->data;
667 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
668 filename, &width, &height, &bitmap, &xhot, &yhot);
669 if (result != BitmapSuccess)
670 return -1;
672 id = x_allocate_bitmap_record (f);
673 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
674 dpyinfo->bitmaps[id - 1].refcount = 1;
675 dpyinfo->bitmaps[id - 1].file
676 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
677 dpyinfo->bitmaps[id - 1].depth = 1;
678 dpyinfo->bitmaps[id - 1].height = height;
679 dpyinfo->bitmaps[id - 1].width = width;
680 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
682 return id;
685 /* Remove reference to bitmap with id number ID. */
687 void
688 x_destroy_bitmap (f, id)
689 FRAME_PTR f;
690 int id;
692 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
694 if (id > 0)
696 --dpyinfo->bitmaps[id - 1].refcount;
697 if (dpyinfo->bitmaps[id - 1].refcount == 0)
699 BLOCK_INPUT;
700 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
701 if (dpyinfo->bitmaps[id - 1].file)
703 xfree (dpyinfo->bitmaps[id - 1].file);
704 dpyinfo->bitmaps[id - 1].file = NULL;
706 UNBLOCK_INPUT;
711 /* Free all the bitmaps for the display specified by DPYINFO. */
713 static void
714 x_destroy_all_bitmaps (dpyinfo)
715 struct x_display_info *dpyinfo;
717 int i;
718 for (i = 0; i < dpyinfo->bitmaps_last; i++)
719 if (dpyinfo->bitmaps[i].refcount > 0)
721 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
722 if (dpyinfo->bitmaps[i].file)
723 xfree (dpyinfo->bitmaps[i].file);
725 dpyinfo->bitmaps_last = 0;
728 /* Connect the frame-parameter names for X frames
729 to the ways of passing the parameter values to the window system.
731 The name of a parameter, as a Lisp symbol,
732 has an `x-frame-parameter' property which is an integer in Lisp
733 that is an index in this table. */
735 struct x_frame_parm_table
737 char *name;
738 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 static void x_create_im P_ ((struct frame *));
742 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
744 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
745 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
746 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
749 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
750 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
751 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
752 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
754 Lisp_Object));
755 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
757 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
758 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
759 Lisp_Object));
760 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
761 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
762 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
763 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
764 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
765 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
766 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
767 Lisp_Object));
768 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
769 Lisp_Object));
770 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
771 Lisp_Object,
772 Lisp_Object,
773 char *, char *,
774 int));
775 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
777 static struct x_frame_parm_table x_frame_parms[] =
779 "auto-raise", x_set_autoraise,
780 "auto-lower", x_set_autolower,
781 "background-color", x_set_background_color,
782 "border-color", x_set_border_color,
783 "border-width", x_set_border_width,
784 "cursor-color", x_set_cursor_color,
785 "cursor-type", x_set_cursor_type,
786 "font", x_set_font,
787 "foreground-color", x_set_foreground_color,
788 "icon-name", x_set_icon_name,
789 "icon-type", x_set_icon_type,
790 "internal-border-width", x_set_internal_border_width,
791 "menu-bar-lines", x_set_menu_bar_lines,
792 "mouse-color", x_set_mouse_color,
793 "name", x_explicitly_set_name,
794 "scroll-bar-width", x_set_scroll_bar_width,
795 "title", x_set_title,
796 "unsplittable", x_set_unsplittable,
797 "vertical-scroll-bars", x_set_vertical_scroll_bars,
798 "visibility", x_set_visibility,
799 "tool-bar-lines", x_set_tool_bar_lines,
800 "scroll-bar-foreground", x_set_scroll_bar_foreground,
801 "scroll-bar-background", x_set_scroll_bar_background,
802 "screen-gamma", x_set_screen_gamma,
803 "line-spacing", x_set_line_spacing
806 /* Attach the `x-frame-parameter' properties to
807 the Lisp symbol names of parameters relevant to X. */
809 void
810 init_x_parm_symbols ()
812 int i;
814 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
815 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
816 make_number (i));
819 /* Change the parameters of frame F as specified by ALIST.
820 If a parameter is not specially recognized, do nothing special;
821 otherwise call the `x_set_...' function for that parameter.
822 Except for certain geometry properties, always call store_frame_param
823 to store the new value in the parameter alist. */
825 void
826 x_set_frame_parameters (f, alist)
827 FRAME_PTR f;
828 Lisp_Object alist;
830 Lisp_Object tail;
832 /* If both of these parameters are present, it's more efficient to
833 set them both at once. So we wait until we've looked at the
834 entire list before we set them. */
835 int width, height;
837 /* Same here. */
838 Lisp_Object left, top;
840 /* Same with these. */
841 Lisp_Object icon_left, icon_top;
843 /* Record in these vectors all the parms specified. */
844 Lisp_Object *parms;
845 Lisp_Object *values;
846 int i, p;
847 int left_no_change = 0, top_no_change = 0;
848 int icon_left_no_change = 0, icon_top_no_change = 0;
850 struct gcpro gcpro1, gcpro2;
852 i = 0;
853 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
854 i++;
856 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
857 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
859 /* Extract parm names and values into those vectors. */
861 i = 0;
862 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
864 Lisp_Object elt;
866 elt = Fcar (tail);
867 parms[i] = Fcar (elt);
868 values[i] = Fcdr (elt);
869 i++;
871 /* TAIL and ALIST are not used again below here. */
872 alist = tail = Qnil;
874 GCPRO2 (*parms, *values);
875 gcpro1.nvars = i;
876 gcpro2.nvars = i;
878 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
879 because their values appear in VALUES and strings are not valid. */
880 top = left = Qunbound;
881 icon_left = icon_top = Qunbound;
883 /* Provide default values for HEIGHT and WIDTH. */
884 if (FRAME_NEW_WIDTH (f))
885 width = FRAME_NEW_WIDTH (f);
886 else
887 width = FRAME_WIDTH (f);
889 if (FRAME_NEW_HEIGHT (f))
890 height = FRAME_NEW_HEIGHT (f);
891 else
892 height = FRAME_HEIGHT (f);
894 /* Process foreground_color and background_color before anything else.
895 They are independent of other properties, but other properties (e.g.,
896 cursor_color) are dependent upon them. */
897 for (p = 0; p < i; p++)
899 Lisp_Object prop, val;
901 prop = parms[p];
902 val = values[p];
903 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
905 register Lisp_Object param_index, old_value;
907 param_index = Fget (prop, Qx_frame_parameter);
908 old_value = get_frame_param (f, prop);
909 store_frame_param (f, prop, val);
910 if (NATNUMP (param_index)
911 && (XFASTINT (param_index)
912 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
913 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
917 /* Now process them in reverse of specified order. */
918 for (i--; i >= 0; i--)
920 Lisp_Object prop, val;
922 prop = parms[i];
923 val = values[i];
925 if (EQ (prop, Qwidth) && NUMBERP (val))
926 width = XFASTINT (val);
927 else if (EQ (prop, Qheight) && NUMBERP (val))
928 height = XFASTINT (val);
929 else if (EQ (prop, Qtop))
930 top = val;
931 else if (EQ (prop, Qleft))
932 left = val;
933 else if (EQ (prop, Qicon_top))
934 icon_top = val;
935 else if (EQ (prop, Qicon_left))
936 icon_left = val;
937 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
938 /* Processed above. */
939 continue;
940 else
942 register Lisp_Object param_index, old_value;
944 param_index = Fget (prop, Qx_frame_parameter);
945 old_value = get_frame_param (f, prop);
946 store_frame_param (f, prop, val);
947 if (NATNUMP (param_index)
948 && (XFASTINT (param_index)
949 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
950 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
954 /* Don't die if just one of these was set. */
955 if (EQ (left, Qunbound))
957 left_no_change = 1;
958 if (f->output_data.x->left_pos < 0)
959 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
960 else
961 XSETINT (left, f->output_data.x->left_pos);
963 if (EQ (top, Qunbound))
965 top_no_change = 1;
966 if (f->output_data.x->top_pos < 0)
967 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
968 else
969 XSETINT (top, f->output_data.x->top_pos);
972 /* If one of the icon positions was not set, preserve or default it. */
973 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
975 icon_left_no_change = 1;
976 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
977 if (NILP (icon_left))
978 XSETINT (icon_left, 0);
980 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
982 icon_top_no_change = 1;
983 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
984 if (NILP (icon_top))
985 XSETINT (icon_top, 0);
988 /* Don't set these parameters unless they've been explicitly
989 specified. The window might be mapped or resized while we're in
990 this function, and we don't want to override that unless the lisp
991 code has asked for it.
993 Don't set these parameters unless they actually differ from the
994 window's current parameters; the window may not actually exist
995 yet. */
997 Lisp_Object frame;
999 check_frame_size (f, &height, &width);
1001 XSETFRAME (frame, f);
1003 if (width != FRAME_WIDTH (f)
1004 || height != FRAME_HEIGHT (f)
1005 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1006 Fset_frame_size (frame, make_number (width), make_number (height));
1008 if ((!NILP (left) || !NILP (top))
1009 && ! (left_no_change && top_no_change)
1010 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1011 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1013 int leftpos = 0;
1014 int toppos = 0;
1016 /* Record the signs. */
1017 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1018 if (EQ (left, Qminus))
1019 f->output_data.x->size_hint_flags |= XNegative;
1020 else if (INTEGERP (left))
1022 leftpos = XINT (left);
1023 if (leftpos < 0)
1024 f->output_data.x->size_hint_flags |= XNegative;
1026 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1027 && CONSP (XCDR (left))
1028 && INTEGERP (XCAR (XCDR (left))))
1030 leftpos = - XINT (XCAR (XCDR (left)));
1031 f->output_data.x->size_hint_flags |= XNegative;
1033 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1034 && CONSP (XCDR (left))
1035 && INTEGERP (XCAR (XCDR (left))))
1037 leftpos = XINT (XCAR (XCDR (left)));
1040 if (EQ (top, Qminus))
1041 f->output_data.x->size_hint_flags |= YNegative;
1042 else if (INTEGERP (top))
1044 toppos = XINT (top);
1045 if (toppos < 0)
1046 f->output_data.x->size_hint_flags |= YNegative;
1048 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1049 && CONSP (XCDR (top))
1050 && INTEGERP (XCAR (XCDR (top))))
1052 toppos = - XINT (XCAR (XCDR (top)));
1053 f->output_data.x->size_hint_flags |= YNegative;
1055 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1056 && CONSP (XCDR (top))
1057 && INTEGERP (XCAR (XCDR (top))))
1059 toppos = XINT (XCAR (XCDR (top)));
1063 /* Store the numeric value of the position. */
1064 f->output_data.x->top_pos = toppos;
1065 f->output_data.x->left_pos = leftpos;
1067 f->output_data.x->win_gravity = NorthWestGravity;
1069 /* Actually set that position, and convert to absolute. */
1070 x_set_offset (f, leftpos, toppos, -1);
1073 if ((!NILP (icon_left) || !NILP (icon_top))
1074 && ! (icon_left_no_change && icon_top_no_change))
1075 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1078 UNGCPRO;
1081 /* Store the screen positions of frame F into XPTR and YPTR.
1082 These are the positions of the containing window manager window,
1083 not Emacs's own window. */
1085 void
1086 x_real_positions (f, xptr, yptr)
1087 FRAME_PTR f;
1088 int *xptr, *yptr;
1090 int win_x, win_y;
1091 Window child;
1093 /* This is pretty gross, but seems to be the easiest way out of
1094 the problem that arises when restarting window-managers. */
1096 #ifdef USE_X_TOOLKIT
1097 Window outer = (f->output_data.x->widget
1098 ? XtWindow (f->output_data.x->widget)
1099 : FRAME_X_WINDOW (f));
1100 #else
1101 Window outer = f->output_data.x->window_desc;
1102 #endif
1103 Window tmp_root_window;
1104 Window *tmp_children;
1105 unsigned int tmp_nchildren;
1107 while (1)
1109 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1110 Window outer_window;
1112 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1113 &f->output_data.x->parent_desc,
1114 &tmp_children, &tmp_nchildren);
1115 XFree ((char *) tmp_children);
1117 win_x = win_y = 0;
1119 /* Find the position of the outside upper-left corner of
1120 the inner window, with respect to the outer window. */
1121 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1122 outer_window = f->output_data.x->parent_desc;
1123 else
1124 outer_window = outer;
1126 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1128 /* From-window, to-window. */
1129 outer_window,
1130 FRAME_X_DISPLAY_INFO (f)->root_window,
1132 /* From-position, to-position. */
1133 0, 0, &win_x, &win_y,
1135 /* Child of win. */
1136 &child);
1138 /* It is possible for the window returned by the XQueryNotify
1139 to become invalid by the time we call XTranslateCoordinates.
1140 That can happen when you restart some window managers.
1141 If so, we get an error in XTranslateCoordinates.
1142 Detect that and try the whole thing over. */
1143 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1145 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1146 break;
1149 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1152 *xptr = win_x;
1153 *yptr = win_y;
1156 /* Insert a description of internally-recorded parameters of frame X
1157 into the parameter alist *ALISTPTR that is to be given to the user.
1158 Only parameters that are specific to the X window system
1159 and whose values are not correctly recorded in the frame's
1160 param_alist need to be considered here. */
1162 void
1163 x_report_frame_params (f, alistptr)
1164 struct frame *f;
1165 Lisp_Object *alistptr;
1167 char buf[16];
1168 Lisp_Object tem;
1170 /* Represent negative positions (off the top or left screen edge)
1171 in a way that Fmodify_frame_parameters will understand correctly. */
1172 XSETINT (tem, f->output_data.x->left_pos);
1173 if (f->output_data.x->left_pos >= 0)
1174 store_in_alist (alistptr, Qleft, tem);
1175 else
1176 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1178 XSETINT (tem, f->output_data.x->top_pos);
1179 if (f->output_data.x->top_pos >= 0)
1180 store_in_alist (alistptr, Qtop, tem);
1181 else
1182 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1184 store_in_alist (alistptr, Qborder_width,
1185 make_number (f->output_data.x->border_width));
1186 store_in_alist (alistptr, Qinternal_border_width,
1187 make_number (f->output_data.x->internal_border_width));
1188 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1189 store_in_alist (alistptr, Qwindow_id,
1190 build_string (buf));
1191 #ifdef USE_X_TOOLKIT
1192 /* Tooltip frame may not have this widget. */
1193 if (f->output_data.x->widget)
1194 #endif
1195 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1196 store_in_alist (alistptr, Qouter_window_id,
1197 build_string (buf));
1198 store_in_alist (alistptr, Qicon_name, f->icon_name);
1199 FRAME_SAMPLE_VISIBILITY (f);
1200 store_in_alist (alistptr, Qvisibility,
1201 (FRAME_VISIBLE_P (f) ? Qt
1202 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1203 store_in_alist (alistptr, Qdisplay,
1204 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1206 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1207 tem = Qnil;
1208 else
1209 XSETFASTINT (tem, f->output_data.x->parent_desc);
1210 store_in_alist (alistptr, Qparent_id, tem);
1215 /* Gamma-correct COLOR on frame F. */
1217 void
1218 gamma_correct (f, color)
1219 struct frame *f;
1220 XColor *color;
1222 if (f->gamma)
1224 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1225 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1226 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1231 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1232 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1233 allocate the color. Value is zero if COLOR_NAME is invalid, or
1234 no color could be allocated. */
1237 x_defined_color (f, color_name, color, alloc_p)
1238 struct frame *f;
1239 char *color_name;
1240 XColor *color;
1241 int alloc_p;
1243 int success_p;
1244 Display *dpy = FRAME_X_DISPLAY (f);
1245 Colormap cmap = FRAME_X_COLORMAP (f);
1247 BLOCK_INPUT;
1248 success_p = XParseColor (dpy, cmap, color_name, color);
1249 if (success_p && alloc_p)
1250 success_p = x_alloc_nearest_color (f, cmap, color);
1251 UNBLOCK_INPUT;
1253 return success_p;
1257 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1258 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1259 Signal an error if color can't be allocated. */
1262 x_decode_color (f, color_name, mono_color)
1263 FRAME_PTR f;
1264 Lisp_Object color_name;
1265 int mono_color;
1267 XColor cdef;
1269 CHECK_STRING (color_name, 0);
1271 #if 0 /* Don't do this. It's wrong when we're not using the default
1272 colormap, it makes freeing difficult, and it's probably not
1273 an important optimization. */
1274 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1275 return BLACK_PIX_DEFAULT (f);
1276 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1277 return WHITE_PIX_DEFAULT (f);
1278 #endif
1280 /* Return MONO_COLOR for monochrome frames. */
1281 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1282 return mono_color;
1284 /* x_defined_color is responsible for coping with failures
1285 by looking for a near-miss. */
1286 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1287 return cdef.pixel;
1289 Fsignal (Qerror, Fcons (build_string ("undefined color"),
1290 Fcons (color_name, Qnil)));
1295 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1296 the previous value of that parameter, NEW_VALUE is the new value. */
1298 static void
1299 x_set_line_spacing (f, new_value, old_value)
1300 struct frame *f;
1301 Lisp_Object new_value, old_value;
1303 if (NILP (new_value))
1304 f->extra_line_spacing = 0;
1305 else if (NATNUMP (new_value))
1306 f->extra_line_spacing = XFASTINT (new_value);
1307 else
1308 Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
1309 Fcons (new_value, Qnil)));
1310 if (FRAME_VISIBLE_P (f))
1311 redraw_frame (f);
1315 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1316 the previous value of that parameter, NEW_VALUE is the new value. */
1318 static void
1319 x_set_screen_gamma (f, new_value, old_value)
1320 struct frame *f;
1321 Lisp_Object new_value, old_value;
1323 if (NILP (new_value))
1324 f->gamma = 0;
1325 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1326 /* The value 0.4545 is the normal viewing gamma. */
1327 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1328 else
1329 Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
1330 Fcons (new_value, Qnil)));
1332 clear_face_cache (0);
1336 /* Functions called only from `x_set_frame_param'
1337 to set individual parameters.
1339 If FRAME_X_WINDOW (f) is 0,
1340 the frame is being created and its X-window does not exist yet.
1341 In that case, just record the parameter's new value
1342 in the standard place; do not attempt to change the window. */
1344 void
1345 x_set_foreground_color (f, arg, oldval)
1346 struct frame *f;
1347 Lisp_Object arg, oldval;
1349 unsigned long pixel
1350 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1352 unload_color (f, f->output_data.x->foreground_pixel);
1353 f->output_data.x->foreground_pixel = pixel;
1355 if (FRAME_X_WINDOW (f) != 0)
1357 BLOCK_INPUT;
1358 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1359 f->output_data.x->foreground_pixel);
1360 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1361 f->output_data.x->foreground_pixel);
1362 UNBLOCK_INPUT;
1363 update_face_from_frame_parameter (f, Qforeground_color, arg);
1364 if (FRAME_VISIBLE_P (f))
1365 redraw_frame (f);
1369 void
1370 x_set_background_color (f, arg, oldval)
1371 struct frame *f;
1372 Lisp_Object arg, oldval;
1374 unsigned long pixel
1375 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1377 unload_color (f, f->output_data.x->background_pixel);
1378 f->output_data.x->background_pixel = pixel;
1380 if (FRAME_X_WINDOW (f) != 0)
1382 BLOCK_INPUT;
1383 /* The main frame area. */
1384 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1385 f->output_data.x->background_pixel);
1386 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1387 f->output_data.x->background_pixel);
1388 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1389 f->output_data.x->background_pixel);
1390 XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1391 f->output_data.x->background_pixel);
1393 Lisp_Object bar;
1394 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
1395 bar = XSCROLL_BAR (bar)->next)
1396 XSetWindowBackground (FRAME_X_DISPLAY (f),
1397 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
1398 f->output_data.x->background_pixel);
1400 UNBLOCK_INPUT;
1402 update_face_from_frame_parameter (f, Qbackground_color, arg);
1404 if (FRAME_VISIBLE_P (f))
1405 redraw_frame (f);
1409 void
1410 x_set_mouse_color (f, arg, oldval)
1411 struct frame *f;
1412 Lisp_Object arg, oldval;
1414 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1415 Cursor busy_cursor;
1416 int count;
1417 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1418 unsigned long mask_color = f->output_data.x->background_pixel;
1420 /* Don't let pointers be invisible. */
1421 if (mask_color == pixel
1422 && mask_color == f->output_data.x->background_pixel)
1423 pixel = f->output_data.x->foreground_pixel;
1425 unload_color (f, f->output_data.x->mouse_pixel);
1426 f->output_data.x->mouse_pixel = pixel;
1428 BLOCK_INPUT;
1430 /* It's not okay to crash if the user selects a screwy cursor. */
1431 count = x_catch_errors (FRAME_X_DISPLAY (f));
1433 if (!EQ (Qnil, Vx_pointer_shape))
1435 CHECK_NUMBER (Vx_pointer_shape, 0);
1436 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
1438 else
1439 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1440 x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
1442 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1444 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1445 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1446 XINT (Vx_nontext_pointer_shape));
1448 else
1449 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
1450 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1452 if (!EQ (Qnil, Vx_busy_pointer_shape))
1454 CHECK_NUMBER (Vx_busy_pointer_shape, 0);
1455 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1456 XINT (Vx_busy_pointer_shape));
1458 else
1459 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
1460 x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s");
1462 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1463 if (!EQ (Qnil, Vx_mode_pointer_shape))
1465 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1466 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1467 XINT (Vx_mode_pointer_shape));
1469 else
1470 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1471 x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
1473 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1475 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1476 cross_cursor
1477 = XCreateFontCursor (FRAME_X_DISPLAY (f),
1478 XINT (Vx_sensitive_text_pointer_shape));
1480 else
1481 cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
1483 /* Check and report errors with the above calls. */
1484 x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
1485 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1488 XColor fore_color, back_color;
1490 fore_color.pixel = f->output_data.x->mouse_pixel;
1491 back_color.pixel = mask_color;
1492 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
1493 &fore_color);
1494 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
1495 &back_color);
1496 XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
1497 &fore_color, &back_color);
1498 XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
1499 &fore_color, &back_color);
1500 XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
1501 &fore_color, &back_color);
1502 XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
1503 &fore_color, &back_color);
1504 XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
1505 &fore_color, &back_color);
1508 if (FRAME_X_WINDOW (f) != 0)
1509 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
1511 if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
1512 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
1513 f->output_data.x->text_cursor = cursor;
1515 if (nontext_cursor != f->output_data.x->nontext_cursor
1516 && f->output_data.x->nontext_cursor != 0)
1517 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
1518 f->output_data.x->nontext_cursor = nontext_cursor;
1520 if (busy_cursor != f->output_data.x->busy_cursor
1521 && f->output_data.x->busy_cursor != 0)
1522 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
1523 f->output_data.x->busy_cursor = busy_cursor;
1525 if (mode_cursor != f->output_data.x->modeline_cursor
1526 && f->output_data.x->modeline_cursor != 0)
1527 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
1528 f->output_data.x->modeline_cursor = mode_cursor;
1530 if (cross_cursor != f->output_data.x->cross_cursor
1531 && f->output_data.x->cross_cursor != 0)
1532 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
1533 f->output_data.x->cross_cursor = cross_cursor;
1535 XFlush (FRAME_X_DISPLAY (f));
1536 UNBLOCK_INPUT;
1538 update_face_from_frame_parameter (f, Qmouse_color, arg);
1541 void
1542 x_set_cursor_color (f, arg, oldval)
1543 struct frame *f;
1544 Lisp_Object arg, oldval;
1546 unsigned long fore_pixel, pixel;
1547 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1549 if (!NILP (Vx_cursor_fore_pixel))
1551 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1552 WHITE_PIX_DEFAULT (f));
1553 fore_pixel_allocated_p = 1;
1555 else
1556 fore_pixel = f->output_data.x->background_pixel;
1558 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1559 pixel_allocated_p = 1;
1561 /* Make sure that the cursor color differs from the background color. */
1562 if (pixel == f->output_data.x->background_pixel)
1564 if (pixel_allocated_p)
1566 x_free_colors (f, &pixel, 1);
1567 pixel_allocated_p = 0;
1570 pixel = f->output_data.x->mouse_pixel;
1571 if (pixel == fore_pixel)
1573 if (fore_pixel_allocated_p)
1575 x_free_colors (f, &fore_pixel, 1);
1576 fore_pixel_allocated_p = 0;
1578 fore_pixel = f->output_data.x->background_pixel;
1582 unload_color (f, f->output_data.x->cursor_foreground_pixel);
1583 if (!fore_pixel_allocated_p)
1584 fore_pixel = x_copy_color (f, fore_pixel);
1585 f->output_data.x->cursor_foreground_pixel = fore_pixel;
1587 unload_color (f, f->output_data.x->cursor_pixel);
1588 if (!pixel_allocated_p)
1589 pixel = x_copy_color (f, pixel);
1590 f->output_data.x->cursor_pixel = pixel;
1592 if (FRAME_X_WINDOW (f) != 0)
1594 BLOCK_INPUT;
1595 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1596 f->output_data.x->cursor_pixel);
1597 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1598 fore_pixel);
1599 UNBLOCK_INPUT;
1601 if (FRAME_VISIBLE_P (f))
1603 x_update_cursor (f, 0);
1604 x_update_cursor (f, 1);
1608 update_face_from_frame_parameter (f, Qcursor_color, arg);
1611 /* Set the border-color of frame F to value described by ARG.
1612 ARG can be a string naming a color.
1613 The border-color is used for the border that is drawn by the X server.
1614 Note that this does not fully take effect if done before
1615 F has an x-window; it must be redone when the window is created.
1617 Note: this is done in two routines because of the way X10 works.
1619 Note: under X11, this is normally the province of the window manager,
1620 and so emacs' border colors may be overridden. */
1622 void
1623 x_set_border_color (f, arg, oldval)
1624 struct frame *f;
1625 Lisp_Object arg, oldval;
1627 int pix;
1629 CHECK_STRING (arg, 0);
1630 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1631 x_set_border_pixel (f, pix);
1632 update_face_from_frame_parameter (f, Qborder_color, arg);
1635 /* Set the border-color of frame F to pixel value PIX.
1636 Note that this does not fully take effect if done before
1637 F has an x-window. */
1639 void
1640 x_set_border_pixel (f, pix)
1641 struct frame *f;
1642 int pix;
1644 unload_color (f, f->output_data.x->border_pixel);
1645 f->output_data.x->border_pixel = pix;
1647 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1649 BLOCK_INPUT;
1650 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1651 (unsigned long)pix);
1652 UNBLOCK_INPUT;
1654 if (FRAME_VISIBLE_P (f))
1655 redraw_frame (f);
1660 /* Value is the internal representation of the specified cursor type
1661 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1662 of the bar cursor. */
1664 enum text_cursor_kinds
1665 x_specified_cursor_type (arg, width)
1666 Lisp_Object arg;
1667 int *width;
1669 enum text_cursor_kinds type;
1671 if (EQ (arg, Qbar))
1673 type = BAR_CURSOR;
1674 *width = 2;
1676 else if (CONSP (arg)
1677 && EQ (XCAR (arg), Qbar)
1678 && INTEGERP (XCDR (arg))
1679 && XINT (XCDR (arg)) >= 0)
1681 type = BAR_CURSOR;
1682 *width = XINT (XCDR (arg));
1684 else if (NILP (arg))
1685 type = NO_CURSOR;
1686 else
1687 /* Treat anything unknown as "box cursor".
1688 It was bad to signal an error; people have trouble fixing
1689 .Xdefaults with Emacs, when it has something bad in it. */
1690 type = FILLED_BOX_CURSOR;
1692 return type;
1695 void
1696 x_set_cursor_type (f, arg, oldval)
1697 FRAME_PTR f;
1698 Lisp_Object arg, oldval;
1700 int width;
1702 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1703 f->output_data.x->cursor_width = width;
1705 /* Make sure the cursor gets redrawn. This is overkill, but how
1706 often do people change cursor types? */
1707 update_mode_lines++;
1710 void
1711 x_set_icon_type (f, arg, oldval)
1712 struct frame *f;
1713 Lisp_Object arg, oldval;
1715 int result;
1717 if (STRINGP (arg))
1719 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1720 return;
1722 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1723 return;
1725 BLOCK_INPUT;
1726 if (NILP (arg))
1727 result = x_text_icon (f,
1728 (char *) XSTRING ((!NILP (f->icon_name)
1729 ? f->icon_name
1730 : f->name))->data);
1731 else
1732 result = x_bitmap_icon (f, arg);
1734 if (result)
1736 UNBLOCK_INPUT;
1737 error ("No icon window available");
1740 XFlush (FRAME_X_DISPLAY (f));
1741 UNBLOCK_INPUT;
1744 /* Return non-nil if frame F wants a bitmap icon. */
1746 Lisp_Object
1747 x_icon_type (f)
1748 FRAME_PTR f;
1750 Lisp_Object tem;
1752 tem = assq_no_quit (Qicon_type, f->param_alist);
1753 if (CONSP (tem))
1754 return XCDR (tem);
1755 else
1756 return Qnil;
1759 void
1760 x_set_icon_name (f, arg, oldval)
1761 struct frame *f;
1762 Lisp_Object arg, oldval;
1764 int result;
1766 if (STRINGP (arg))
1768 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1769 return;
1771 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1772 return;
1774 f->icon_name = arg;
1776 if (f->output_data.x->icon_bitmap != 0)
1777 return;
1779 BLOCK_INPUT;
1781 result = x_text_icon (f,
1782 (char *) XSTRING ((!NILP (f->icon_name)
1783 ? f->icon_name
1784 : !NILP (f->title)
1785 ? f->title
1786 : f->name))->data);
1788 if (result)
1790 UNBLOCK_INPUT;
1791 error ("No icon window available");
1794 XFlush (FRAME_X_DISPLAY (f));
1795 UNBLOCK_INPUT;
1798 void
1799 x_set_font (f, arg, oldval)
1800 struct frame *f;
1801 Lisp_Object arg, oldval;
1803 Lisp_Object result;
1804 Lisp_Object fontset_name;
1805 Lisp_Object frame;
1807 CHECK_STRING (arg, 1);
1809 fontset_name = Fquery_fontset (arg, Qnil);
1811 BLOCK_INPUT;
1812 result = (STRINGP (fontset_name)
1813 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1814 : x_new_font (f, XSTRING (arg)->data));
1815 UNBLOCK_INPUT;
1817 if (EQ (result, Qnil))
1818 error ("Font `%s' is not defined", XSTRING (arg)->data);
1819 else if (EQ (result, Qt))
1820 error ("The characters of the given font have varying widths");
1821 else if (STRINGP (result))
1823 store_frame_param (f, Qfont, result);
1824 recompute_basic_faces (f);
1826 else
1827 abort ();
1829 do_pending_window_change (0);
1831 /* Don't call `face-set-after-frame-default' when faces haven't been
1832 initialized yet. This is the case when called from
1833 Fx_create_frame. In that case, the X widget or window doesn't
1834 exist either, and we can end up in x_report_frame_params with a
1835 null widget which gives a segfault. */
1836 if (FRAME_FACE_CACHE (f))
1838 XSETFRAME (frame, f);
1839 call1 (Qface_set_after_frame_default, frame);
1843 void
1844 x_set_border_width (f, arg, oldval)
1845 struct frame *f;
1846 Lisp_Object arg, oldval;
1848 CHECK_NUMBER (arg, 0);
1850 if (XINT (arg) == f->output_data.x->border_width)
1851 return;
1853 if (FRAME_X_WINDOW (f) != 0)
1854 error ("Cannot change the border width of a window");
1856 f->output_data.x->border_width = XINT (arg);
1859 void
1860 x_set_internal_border_width (f, arg, oldval)
1861 struct frame *f;
1862 Lisp_Object arg, oldval;
1864 int old = f->output_data.x->internal_border_width;
1866 CHECK_NUMBER (arg, 0);
1867 f->output_data.x->internal_border_width = XINT (arg);
1868 if (f->output_data.x->internal_border_width < 0)
1869 f->output_data.x->internal_border_width = 0;
1871 #ifdef USE_X_TOOLKIT
1872 if (f->output_data.x->edit_widget)
1873 widget_store_internal_border (f->output_data.x->edit_widget);
1874 #endif
1876 if (f->output_data.x->internal_border_width == old)
1877 return;
1879 if (FRAME_X_WINDOW (f) != 0)
1881 x_set_window_size (f, 0, f->width, f->height);
1882 SET_FRAME_GARBAGED (f);
1883 do_pending_window_change (0);
1887 void
1888 x_set_visibility (f, value, oldval)
1889 struct frame *f;
1890 Lisp_Object value, oldval;
1892 Lisp_Object frame;
1893 XSETFRAME (frame, f);
1895 if (NILP (value))
1896 Fmake_frame_invisible (frame, Qt);
1897 else if (EQ (value, Qicon))
1898 Ficonify_frame (frame);
1899 else
1900 Fmake_frame_visible (frame);
1903 static void
1904 x_set_menu_bar_lines_1 (window, n)
1905 Lisp_Object window;
1906 int n;
1908 struct window *w = XWINDOW (window);
1910 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1911 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1913 if (INTEGERP (w->orig_top))
1914 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
1915 if (INTEGERP (w->orig_height))
1916 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
1918 /* Handle just the top child in a vertical split. */
1919 if (!NILP (w->vchild))
1920 x_set_menu_bar_lines_1 (w->vchild, n);
1922 /* Adjust all children in a horizontal split. */
1923 for (window = w->hchild; !NILP (window); window = w->next)
1925 w = XWINDOW (window);
1926 x_set_menu_bar_lines_1 (window, n);
1930 void
1931 x_set_menu_bar_lines (f, value, oldval)
1932 struct frame *f;
1933 Lisp_Object value, oldval;
1935 int nlines;
1936 #ifndef USE_X_TOOLKIT
1937 int olines = FRAME_MENU_BAR_LINES (f);
1938 #endif
1940 /* Right now, menu bars don't work properly in minibuf-only frames;
1941 most of the commands try to apply themselves to the minibuffer
1942 frame itself, and get an error because you can't switch buffers
1943 in or split the minibuffer window. */
1944 if (FRAME_MINIBUF_ONLY_P (f))
1945 return;
1947 if (INTEGERP (value))
1948 nlines = XINT (value);
1949 else
1950 nlines = 0;
1952 /* Make sure we redisplay all windows in this frame. */
1953 windows_or_buffers_changed++;
1955 #ifdef USE_X_TOOLKIT
1956 FRAME_MENU_BAR_LINES (f) = 0;
1957 if (nlines)
1959 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1960 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1961 /* Make sure next redisplay shows the menu bar. */
1962 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1964 else
1966 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1967 free_frame_menubar (f);
1968 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1969 if (FRAME_X_P (f))
1970 f->output_data.x->menubar_widget = 0;
1972 #else /* not USE_X_TOOLKIT */
1973 FRAME_MENU_BAR_LINES (f) = nlines;
1974 x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
1975 #endif /* not USE_X_TOOLKIT */
1976 adjust_glyphs (f);
1980 /* Set the number of lines used for the tool bar of frame F to VALUE.
1981 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1982 is the old number of tool bar lines. This function changes the
1983 height of all windows on frame F to match the new tool bar height.
1984 The frame's height doesn't change. */
1986 void
1987 x_set_tool_bar_lines (f, value, oldval)
1988 struct frame *f;
1989 Lisp_Object value, oldval;
1991 int delta, nlines;
1993 /* Use VALUE only if an integer >= 0. */
1994 if (INTEGERP (value) && XINT (value) >= 0)
1995 nlines = XFASTINT (value);
1996 else
1997 nlines = 0;
1999 /* Make sure we redisplay all windows in this frame. */
2000 ++windows_or_buffers_changed;
2002 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2003 FRAME_TOOL_BAR_LINES (f) = nlines;
2004 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
2005 adjust_glyphs (f);
2009 /* Set the foreground color for scroll bars on frame F to VALUE.
2010 VALUE should be a string, a color name. If it isn't a string or
2011 isn't a valid color name, do nothing. OLDVAL is the old value of
2012 the frame parameter. */
2014 void
2015 x_set_scroll_bar_foreground (f, value, oldval)
2016 struct frame *f;
2017 Lisp_Object value, oldval;
2019 unsigned long pixel;
2021 if (STRINGP (value))
2022 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2023 else
2024 pixel = -1;
2026 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2027 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2029 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2030 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2032 /* Remove all scroll bars because they have wrong colors. */
2033 if (condemn_scroll_bars_hook)
2034 (*condemn_scroll_bars_hook) (f);
2035 if (judge_scroll_bars_hook)
2036 (*judge_scroll_bars_hook) (f);
2038 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2039 redraw_frame (f);
2044 /* Set the background color for scroll bars on frame F to VALUE VALUE
2045 should be a string, a color name. If it isn't a string or isn't a
2046 valid color name, do nothing. OLDVAL is the old value of the frame
2047 parameter. */
2049 void
2050 x_set_scroll_bar_background (f, value, oldval)
2051 struct frame *f;
2052 Lisp_Object value, oldval;
2054 unsigned long pixel;
2056 if (STRINGP (value))
2057 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2058 else
2059 pixel = -1;
2061 if (f->output_data.x->scroll_bar_background_pixel != -1)
2062 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2064 f->output_data.x->scroll_bar_background_pixel = pixel;
2065 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2067 /* Remove all scroll bars because they have wrong colors. */
2068 if (condemn_scroll_bars_hook)
2069 (*condemn_scroll_bars_hook) (f);
2070 if (judge_scroll_bars_hook)
2071 (*judge_scroll_bars_hook) (f);
2073 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2074 redraw_frame (f);
2079 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2080 x_id_name.
2082 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2083 name; if NAME is a string, set F's name to NAME and set
2084 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2086 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2087 suggesting a new name, which lisp code should override; if
2088 F->explicit_name is set, ignore the new name; otherwise, set it. */
2090 void
2091 x_set_name (f, name, explicit)
2092 struct frame *f;
2093 Lisp_Object name;
2094 int explicit;
2096 /* Make sure that requests from lisp code override requests from
2097 Emacs redisplay code. */
2098 if (explicit)
2100 /* If we're switching from explicit to implicit, we had better
2101 update the mode lines and thereby update the title. */
2102 if (f->explicit_name && NILP (name))
2103 update_mode_lines = 1;
2105 f->explicit_name = ! NILP (name);
2107 else if (f->explicit_name)
2108 return;
2110 /* If NAME is nil, set the name to the x_id_name. */
2111 if (NILP (name))
2113 /* Check for no change needed in this very common case
2114 before we do any consing. */
2115 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2116 XSTRING (f->name)->data))
2117 return;
2118 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2120 else
2121 CHECK_STRING (name, 0);
2123 /* Don't change the name if it's already NAME. */
2124 if (! NILP (Fstring_equal (name, f->name)))
2125 return;
2127 f->name = name;
2129 /* For setting the frame title, the title parameter should override
2130 the name parameter. */
2131 if (! NILP (f->title))
2132 name = f->title;
2134 if (FRAME_X_WINDOW (f))
2136 BLOCK_INPUT;
2137 #ifdef HAVE_X11R4
2139 XTextProperty text, icon;
2140 Lisp_Object icon_name;
2142 text.value = XSTRING (name)->data;
2143 text.encoding = XA_STRING;
2144 text.format = 8;
2145 text.nitems = STRING_BYTES (XSTRING (name));
2147 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
2149 icon.value = XSTRING (icon_name)->data;
2150 icon.encoding = XA_STRING;
2151 icon.format = 8;
2152 icon.nitems = STRING_BYTES (XSTRING (icon_name));
2153 #ifdef USE_X_TOOLKIT
2154 XSetWMName (FRAME_X_DISPLAY (f),
2155 XtWindow (f->output_data.x->widget), &text);
2156 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2157 &icon);
2158 #else /* not USE_X_TOOLKIT */
2159 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2160 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2161 #endif /* not USE_X_TOOLKIT */
2163 #else /* not HAVE_X11R4 */
2164 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2165 XSTRING (name)->data);
2166 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2167 XSTRING (name)->data);
2168 #endif /* not HAVE_X11R4 */
2169 UNBLOCK_INPUT;
2173 /* This function should be called when the user's lisp code has
2174 specified a name for the frame; the name will override any set by the
2175 redisplay code. */
2176 void
2177 x_explicitly_set_name (f, arg, oldval)
2178 FRAME_PTR f;
2179 Lisp_Object arg, oldval;
2181 x_set_name (f, arg, 1);
2184 /* This function should be called by Emacs redisplay code to set the
2185 name; names set this way will never override names set by the user's
2186 lisp code. */
2187 void
2188 x_implicitly_set_name (f, arg, oldval)
2189 FRAME_PTR f;
2190 Lisp_Object arg, oldval;
2192 x_set_name (f, arg, 0);
2195 /* Change the title of frame F to NAME.
2196 If NAME is nil, use the frame name as the title.
2198 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2199 name; if NAME is a string, set F's name to NAME and set
2200 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2202 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2203 suggesting a new name, which lisp code should override; if
2204 F->explicit_name is set, ignore the new name; otherwise, set it. */
2206 void
2207 x_set_title (f, name, old_name)
2208 struct frame *f;
2209 Lisp_Object name, old_name;
2211 /* Don't change the title if it's already NAME. */
2212 if (EQ (name, f->title))
2213 return;
2215 update_mode_lines = 1;
2217 f->title = name;
2219 if (NILP (name))
2220 name = f->name;
2221 else
2222 CHECK_STRING (name, 0);
2224 if (FRAME_X_WINDOW (f))
2226 BLOCK_INPUT;
2227 #ifdef HAVE_X11R4
2229 XTextProperty text, icon;
2230 Lisp_Object icon_name;
2232 text.value = XSTRING (name)->data;
2233 text.encoding = XA_STRING;
2234 text.format = 8;
2235 text.nitems = STRING_BYTES (XSTRING (name));
2237 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
2239 icon.value = XSTRING (icon_name)->data;
2240 icon.encoding = XA_STRING;
2241 icon.format = 8;
2242 icon.nitems = STRING_BYTES (XSTRING (icon_name));
2243 #ifdef USE_X_TOOLKIT
2244 XSetWMName (FRAME_X_DISPLAY (f),
2245 XtWindow (f->output_data.x->widget), &text);
2246 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2247 &icon);
2248 #else /* not USE_X_TOOLKIT */
2249 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2250 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2251 #endif /* not USE_X_TOOLKIT */
2253 #else /* not HAVE_X11R4 */
2254 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2255 XSTRING (name)->data);
2256 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2257 XSTRING (name)->data);
2258 #endif /* not HAVE_X11R4 */
2259 UNBLOCK_INPUT;
2263 void
2264 x_set_autoraise (f, arg, oldval)
2265 struct frame *f;
2266 Lisp_Object arg, oldval;
2268 f->auto_raise = !EQ (Qnil, arg);
2271 void
2272 x_set_autolower (f, arg, oldval)
2273 struct frame *f;
2274 Lisp_Object arg, oldval;
2276 f->auto_lower = !EQ (Qnil, arg);
2279 void
2280 x_set_unsplittable (f, arg, oldval)
2281 struct frame *f;
2282 Lisp_Object arg, oldval;
2284 f->no_split = !NILP (arg);
2287 void
2288 x_set_vertical_scroll_bars (f, arg, oldval)
2289 struct frame *f;
2290 Lisp_Object arg, oldval;
2292 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2293 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2294 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2295 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2297 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2298 = (NILP (arg)
2299 ? vertical_scroll_bar_none
2300 : EQ (Qright, arg)
2301 ? vertical_scroll_bar_right
2302 : vertical_scroll_bar_left);
2304 /* We set this parameter before creating the X window for the
2305 frame, so we can get the geometry right from the start.
2306 However, if the window hasn't been created yet, we shouldn't
2307 call x_set_window_size. */
2308 if (FRAME_X_WINDOW (f))
2309 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2310 do_pending_window_change (0);
2314 void
2315 x_set_scroll_bar_width (f, arg, oldval)
2316 struct frame *f;
2317 Lisp_Object arg, oldval;
2319 int wid = FONT_WIDTH (f->output_data.x->font);
2321 if (NILP (arg))
2323 #ifdef USE_TOOLKIT_SCROLL_BARS
2324 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2325 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2326 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2327 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2328 #else
2329 /* Make the actual width at least 14 pixels and a multiple of a
2330 character width. */
2331 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2333 /* Use all of that space (aside from required margins) for the
2334 scroll bar. */
2335 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2336 #endif
2338 if (FRAME_X_WINDOW (f))
2339 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2340 do_pending_window_change (0);
2342 else if (INTEGERP (arg) && XINT (arg) > 0
2343 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2345 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2346 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2348 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2349 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2350 if (FRAME_X_WINDOW (f))
2351 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2354 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2355 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2356 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2361 /* Subroutines of creating an X frame. */
2363 /* Make sure that Vx_resource_name is set to a reasonable value.
2364 Fix it up, or set it to `emacs' if it is too hopeless. */
2366 static void
2367 validate_x_resource_name ()
2369 int len = 0;
2370 /* Number of valid characters in the resource name. */
2371 int good_count = 0;
2372 /* Number of invalid characters in the resource name. */
2373 int bad_count = 0;
2374 Lisp_Object new;
2375 int i;
2377 if (!STRINGP (Vx_resource_class))
2378 Vx_resource_class = build_string (EMACS_CLASS);
2380 if (STRINGP (Vx_resource_name))
2382 unsigned char *p = XSTRING (Vx_resource_name)->data;
2383 int i;
2385 len = STRING_BYTES (XSTRING (Vx_resource_name));
2387 /* Only letters, digits, - and _ are valid in resource names.
2388 Count the valid characters and count the invalid ones. */
2389 for (i = 0; i < len; i++)
2391 int c = p[i];
2392 if (! ((c >= 'a' && c <= 'z')
2393 || (c >= 'A' && c <= 'Z')
2394 || (c >= '0' && c <= '9')
2395 || c == '-' || c == '_'))
2396 bad_count++;
2397 else
2398 good_count++;
2401 else
2402 /* Not a string => completely invalid. */
2403 bad_count = 5, good_count = 0;
2405 /* If name is valid already, return. */
2406 if (bad_count == 0)
2407 return;
2409 /* If name is entirely invalid, or nearly so, use `emacs'. */
2410 if (good_count == 0
2411 || (good_count == 1 && bad_count > 0))
2413 Vx_resource_name = build_string ("emacs");
2414 return;
2417 /* Name is partly valid. Copy it and replace the invalid characters
2418 with underscores. */
2420 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2422 for (i = 0; i < len; i++)
2424 int c = XSTRING (new)->data[i];
2425 if (! ((c >= 'a' && c <= 'z')
2426 || (c >= 'A' && c <= 'Z')
2427 || (c >= '0' && c <= '9')
2428 || c == '-' || c == '_'))
2429 XSTRING (new)->data[i] = '_';
2434 extern char *x_get_string_resource ();
2436 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2437 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2438 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2439 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2440 the name specified by the `-name' or `-rn' command-line arguments.\n\
2442 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2443 class, respectively. You must specify both of them or neither.\n\
2444 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2445 and the class is `Emacs.CLASS.SUBCLASS'.")
2446 (attribute, class, component, subclass)
2447 Lisp_Object attribute, class, component, subclass;
2449 register char *value;
2450 char *name_key;
2451 char *class_key;
2453 check_x ();
2455 CHECK_STRING (attribute, 0);
2456 CHECK_STRING (class, 0);
2458 if (!NILP (component))
2459 CHECK_STRING (component, 1);
2460 if (!NILP (subclass))
2461 CHECK_STRING (subclass, 2);
2462 if (NILP (component) != NILP (subclass))
2463 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2465 validate_x_resource_name ();
2467 /* Allocate space for the components, the dots which separate them,
2468 and the final '\0'. Make them big enough for the worst case. */
2469 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2470 + (STRINGP (component)
2471 ? STRING_BYTES (XSTRING (component)) : 0)
2472 + STRING_BYTES (XSTRING (attribute))
2473 + 3);
2475 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2476 + STRING_BYTES (XSTRING (class))
2477 + (STRINGP (subclass)
2478 ? STRING_BYTES (XSTRING (subclass)) : 0)
2479 + 3);
2481 /* Start with emacs.FRAMENAME for the name (the specific one)
2482 and with `Emacs' for the class key (the general one). */
2483 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2484 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2486 strcat (class_key, ".");
2487 strcat (class_key, XSTRING (class)->data);
2489 if (!NILP (component))
2491 strcat (class_key, ".");
2492 strcat (class_key, XSTRING (subclass)->data);
2494 strcat (name_key, ".");
2495 strcat (name_key, XSTRING (component)->data);
2498 strcat (name_key, ".");
2499 strcat (name_key, XSTRING (attribute)->data);
2501 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2502 name_key, class_key);
2504 if (value != (char *) 0)
2505 return build_string (value);
2506 else
2507 return Qnil;
2510 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2512 Lisp_Object
2513 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2514 struct x_display_info *dpyinfo;
2515 Lisp_Object attribute, class, component, subclass;
2517 register char *value;
2518 char *name_key;
2519 char *class_key;
2521 CHECK_STRING (attribute, 0);
2522 CHECK_STRING (class, 0);
2524 if (!NILP (component))
2525 CHECK_STRING (component, 1);
2526 if (!NILP (subclass))
2527 CHECK_STRING (subclass, 2);
2528 if (NILP (component) != NILP (subclass))
2529 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2531 validate_x_resource_name ();
2533 /* Allocate space for the components, the dots which separate them,
2534 and the final '\0'. Make them big enough for the worst case. */
2535 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2536 + (STRINGP (component)
2537 ? STRING_BYTES (XSTRING (component)) : 0)
2538 + STRING_BYTES (XSTRING (attribute))
2539 + 3);
2541 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2542 + STRING_BYTES (XSTRING (class))
2543 + (STRINGP (subclass)
2544 ? STRING_BYTES (XSTRING (subclass)) : 0)
2545 + 3);
2547 /* Start with emacs.FRAMENAME for the name (the specific one)
2548 and with `Emacs' for the class key (the general one). */
2549 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2550 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2552 strcat (class_key, ".");
2553 strcat (class_key, XSTRING (class)->data);
2555 if (!NILP (component))
2557 strcat (class_key, ".");
2558 strcat (class_key, XSTRING (subclass)->data);
2560 strcat (name_key, ".");
2561 strcat (name_key, XSTRING (component)->data);
2564 strcat (name_key, ".");
2565 strcat (name_key, XSTRING (attribute)->data);
2567 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2569 if (value != (char *) 0)
2570 return build_string (value);
2571 else
2572 return Qnil;
2575 /* Used when C code wants a resource value. */
2577 char *
2578 x_get_resource_string (attribute, class)
2579 char *attribute, *class;
2581 char *name_key;
2582 char *class_key;
2583 struct frame *sf = SELECTED_FRAME ();
2585 /* Allocate space for the components, the dots which separate them,
2586 and the final '\0'. */
2587 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2588 + strlen (attribute) + 2);
2589 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2590 + strlen (class) + 2);
2592 sprintf (name_key, "%s.%s",
2593 XSTRING (Vinvocation_name)->data,
2594 attribute);
2595 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2597 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2598 name_key, class_key);
2601 /* Types we might convert a resource string into. */
2602 enum resource_types
2604 RES_TYPE_NUMBER,
2605 RES_TYPE_FLOAT,
2606 RES_TYPE_BOOLEAN,
2607 RES_TYPE_STRING,
2608 RES_TYPE_SYMBOL
2611 /* Return the value of parameter PARAM.
2613 First search ALIST, then Vdefault_frame_alist, then the X defaults
2614 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2616 Convert the resource to the type specified by desired_type.
2618 If no default is specified, return Qunbound. If you call
2619 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2620 and don't let it get stored in any Lisp-visible variables! */
2622 static Lisp_Object
2623 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2624 struct x_display_info *dpyinfo;
2625 Lisp_Object alist, param;
2626 char *attribute;
2627 char *class;
2628 enum resource_types type;
2630 register Lisp_Object tem;
2632 tem = Fassq (param, alist);
2633 if (EQ (tem, Qnil))
2634 tem = Fassq (param, Vdefault_frame_alist);
2635 if (EQ (tem, Qnil))
2638 if (attribute)
2640 tem = display_x_get_resource (dpyinfo,
2641 build_string (attribute),
2642 build_string (class),
2643 Qnil, Qnil);
2645 if (NILP (tem))
2646 return Qunbound;
2648 switch (type)
2650 case RES_TYPE_NUMBER:
2651 return make_number (atoi (XSTRING (tem)->data));
2653 case RES_TYPE_FLOAT:
2654 return make_float (atof (XSTRING (tem)->data));
2656 case RES_TYPE_BOOLEAN:
2657 tem = Fdowncase (tem);
2658 if (!strcmp (XSTRING (tem)->data, "on")
2659 || !strcmp (XSTRING (tem)->data, "true"))
2660 return Qt;
2661 else
2662 return Qnil;
2664 case RES_TYPE_STRING:
2665 return tem;
2667 case RES_TYPE_SYMBOL:
2668 /* As a special case, we map the values `true' and `on'
2669 to Qt, and `false' and `off' to Qnil. */
2671 Lisp_Object lower;
2672 lower = Fdowncase (tem);
2673 if (!strcmp (XSTRING (lower)->data, "on")
2674 || !strcmp (XSTRING (lower)->data, "true"))
2675 return Qt;
2676 else if (!strcmp (XSTRING (lower)->data, "off")
2677 || !strcmp (XSTRING (lower)->data, "false"))
2678 return Qnil;
2679 else
2680 return Fintern (tem, Qnil);
2683 default:
2684 abort ();
2687 else
2688 return Qunbound;
2690 return Fcdr (tem);
2693 /* Like x_get_arg, but also record the value in f->param_alist. */
2695 static Lisp_Object
2696 x_get_and_record_arg (f, alist, param, attribute, class, type)
2697 struct frame *f;
2698 Lisp_Object alist, param;
2699 char *attribute;
2700 char *class;
2701 enum resource_types type;
2703 Lisp_Object value;
2705 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2706 attribute, class, type);
2707 if (! NILP (value))
2708 store_frame_param (f, param, value);
2710 return value;
2713 /* Record in frame F the specified or default value according to ALIST
2714 of the parameter named PROP (a Lisp symbol).
2715 If no value is specified for PROP, look for an X default for XPROP
2716 on the frame named NAME.
2717 If that is not found either, use the value DEFLT. */
2719 static Lisp_Object
2720 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2721 struct frame *f;
2722 Lisp_Object alist;
2723 Lisp_Object prop;
2724 Lisp_Object deflt;
2725 char *xprop;
2726 char *xclass;
2727 enum resource_types type;
2729 Lisp_Object tem;
2731 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2732 if (EQ (tem, Qunbound))
2733 tem = deflt;
2734 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2735 return tem;
2739 /* Record in frame F the specified or default value according to ALIST
2740 of the parameter named PROP (a Lisp symbol). If no value is
2741 specified for PROP, look for an X default for XPROP on the frame
2742 named NAME. If that is not found either, use the value DEFLT. */
2744 static Lisp_Object
2745 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2746 foreground_p)
2747 struct frame *f;
2748 Lisp_Object alist;
2749 Lisp_Object prop;
2750 char *xprop;
2751 char *xclass;
2752 int foreground_p;
2754 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2755 Lisp_Object tem;
2757 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2758 if (EQ (tem, Qunbound))
2760 #ifdef USE_TOOLKIT_SCROLL_BARS
2762 /* See if an X resource for the scroll bar color has been
2763 specified. */
2764 tem = display_x_get_resource (dpyinfo,
2765 build_string (foreground_p
2766 ? "foreground"
2767 : "background"),
2768 build_string (""),
2769 build_string ("verticalScrollBar"),
2770 build_string (""));
2771 if (!STRINGP (tem))
2773 /* If nothing has been specified, scroll bars will use a
2774 toolkit-dependent default. Because these defaults are
2775 difficult to get at without actually creating a scroll
2776 bar, use nil to indicate that no color has been
2777 specified. */
2778 tem = Qnil;
2781 #else /* not USE_TOOLKIT_SCROLL_BARS */
2783 tem = Qnil;
2785 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2788 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2789 return tem;
2794 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2795 "Parse an X-style geometry string STRING.\n\
2796 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2797 The properties returned may include `top', `left', `height', and `width'.\n\
2798 The value of `left' or `top' may be an integer,\n\
2799 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2800 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2801 (string)
2802 Lisp_Object string;
2804 int geometry, x, y;
2805 unsigned int width, height;
2806 Lisp_Object result;
2808 CHECK_STRING (string, 0);
2810 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2811 &x, &y, &width, &height);
2813 #if 0
2814 if (!!(geometry & XValue) != !!(geometry & YValue))
2815 error ("Must specify both x and y position, or neither");
2816 #endif
2818 result = Qnil;
2819 if (geometry & XValue)
2821 Lisp_Object element;
2823 if (x >= 0 && (geometry & XNegative))
2824 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2825 else if (x < 0 && ! (geometry & XNegative))
2826 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2827 else
2828 element = Fcons (Qleft, make_number (x));
2829 result = Fcons (element, result);
2832 if (geometry & YValue)
2834 Lisp_Object element;
2836 if (y >= 0 && (geometry & YNegative))
2837 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2838 else if (y < 0 && ! (geometry & YNegative))
2839 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2840 else
2841 element = Fcons (Qtop, make_number (y));
2842 result = Fcons (element, result);
2845 if (geometry & WidthValue)
2846 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2847 if (geometry & HeightValue)
2848 result = Fcons (Fcons (Qheight, make_number (height)), result);
2850 return result;
2853 /* Calculate the desired size and position of this window,
2854 and return the flags saying which aspects were specified.
2856 This function does not make the coordinates positive. */
2858 #define DEFAULT_ROWS 40
2859 #define DEFAULT_COLS 80
2861 static int
2862 x_figure_window_size (f, parms)
2863 struct frame *f;
2864 Lisp_Object parms;
2866 register Lisp_Object tem0, tem1, tem2;
2867 long window_prompting = 0;
2868 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2870 /* Default values if we fall through.
2871 Actually, if that happens we should get
2872 window manager prompting. */
2873 SET_FRAME_WIDTH (f, DEFAULT_COLS);
2874 f->height = DEFAULT_ROWS;
2875 /* Window managers expect that if program-specified
2876 positions are not (0,0), they're intentional, not defaults. */
2877 f->output_data.x->top_pos = 0;
2878 f->output_data.x->left_pos = 0;
2880 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
2881 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
2882 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
2883 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2885 if (!EQ (tem0, Qunbound))
2887 CHECK_NUMBER (tem0, 0);
2888 f->height = XINT (tem0);
2890 if (!EQ (tem1, Qunbound))
2892 CHECK_NUMBER (tem1, 0);
2893 SET_FRAME_WIDTH (f, XINT (tem1));
2895 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2896 window_prompting |= USSize;
2897 else
2898 window_prompting |= PSize;
2901 f->output_data.x->vertical_scroll_bar_extra
2902 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2904 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2905 f->output_data.x->flags_areas_extra
2906 = FRAME_FLAGS_AREA_WIDTH (f);
2907 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2908 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2910 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
2911 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
2912 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
2913 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2915 if (EQ (tem0, Qminus))
2917 f->output_data.x->top_pos = 0;
2918 window_prompting |= YNegative;
2920 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
2921 && CONSP (XCDR (tem0))
2922 && INTEGERP (XCAR (XCDR (tem0))))
2924 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
2925 window_prompting |= YNegative;
2927 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
2928 && CONSP (XCDR (tem0))
2929 && INTEGERP (XCAR (XCDR (tem0))))
2931 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
2933 else if (EQ (tem0, Qunbound))
2934 f->output_data.x->top_pos = 0;
2935 else
2937 CHECK_NUMBER (tem0, 0);
2938 f->output_data.x->top_pos = XINT (tem0);
2939 if (f->output_data.x->top_pos < 0)
2940 window_prompting |= YNegative;
2943 if (EQ (tem1, Qminus))
2945 f->output_data.x->left_pos = 0;
2946 window_prompting |= XNegative;
2948 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
2949 && CONSP (XCDR (tem1))
2950 && INTEGERP (XCAR (XCDR (tem1))))
2952 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
2953 window_prompting |= XNegative;
2955 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
2956 && CONSP (XCDR (tem1))
2957 && INTEGERP (XCAR (XCDR (tem1))))
2959 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
2961 else if (EQ (tem1, Qunbound))
2962 f->output_data.x->left_pos = 0;
2963 else
2965 CHECK_NUMBER (tem1, 0);
2966 f->output_data.x->left_pos = XINT (tem1);
2967 if (f->output_data.x->left_pos < 0)
2968 window_prompting |= XNegative;
2971 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2972 window_prompting |= USPosition;
2973 else
2974 window_prompting |= PPosition;
2977 return window_prompting;
2980 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2982 Status
2983 XSetWMProtocols (dpy, w, protocols, count)
2984 Display *dpy;
2985 Window w;
2986 Atom *protocols;
2987 int count;
2989 Atom prop;
2990 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2991 if (prop == None) return False;
2992 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2993 (unsigned char *) protocols, count);
2994 return True;
2996 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2998 #ifdef USE_X_TOOLKIT
3000 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3001 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3002 already be present because of the toolkit (Motif adds some of them,
3003 for example, but Xt doesn't). */
3005 static void
3006 hack_wm_protocols (f, widget)
3007 FRAME_PTR f;
3008 Widget widget;
3010 Display *dpy = XtDisplay (widget);
3011 Window w = XtWindow (widget);
3012 int need_delete = 1;
3013 int need_focus = 1;
3014 int need_save = 1;
3016 BLOCK_INPUT;
3018 Atom type, *atoms = 0;
3019 int format = 0;
3020 unsigned long nitems = 0;
3021 unsigned long bytes_after;
3023 if ((XGetWindowProperty (dpy, w,
3024 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3025 (long)0, (long)100, False, XA_ATOM,
3026 &type, &format, &nitems, &bytes_after,
3027 (unsigned char **) &atoms)
3028 == Success)
3029 && format == 32 && type == XA_ATOM)
3030 while (nitems > 0)
3032 nitems--;
3033 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3034 need_delete = 0;
3035 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3036 need_focus = 0;
3037 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3038 need_save = 0;
3040 if (atoms) XFree ((char *) atoms);
3043 Atom props [10];
3044 int count = 0;
3045 if (need_delete)
3046 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3047 if (need_focus)
3048 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3049 if (need_save)
3050 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3051 if (count)
3052 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3053 XA_ATOM, 32, PropModeAppend,
3054 (unsigned char *) props, count);
3056 UNBLOCK_INPUT;
3058 #endif
3062 /* Support routines for XIC (X Input Context). */
3064 #ifdef HAVE_X_I18N
3066 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3067 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3070 /* Supported XIM styles, ordered by preferenc. */
3072 static XIMStyle supported_xim_styles[] =
3074 XIMPreeditPosition | XIMStatusArea,
3075 XIMPreeditPosition | XIMStatusNothing,
3076 XIMPreeditPosition | XIMStatusNone,
3077 XIMPreeditNothing | XIMStatusArea,
3078 XIMPreeditNothing | XIMStatusNothing,
3079 XIMPreeditNothing | XIMStatusNone,
3080 XIMPreeditNone | XIMStatusArea,
3081 XIMPreeditNone | XIMStatusNothing,
3082 XIMPreeditNone | XIMStatusNone,
3087 /* Create an X fontset on frame F with base font name
3088 BASE_FONTNAME.. */
3090 static XFontSet
3091 xic_create_xfontset (f, base_fontname)
3092 struct frame *f;
3093 char *base_fontname;
3095 XFontSet xfs;
3096 char **missing_list;
3097 int missing_count;
3098 char *def_string;
3100 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3101 base_fontname, &missing_list,
3102 &missing_count, &def_string);
3103 if (missing_list)
3104 XFreeStringList (missing_list);
3106 /* No need to free def_string. */
3107 return xfs;
3111 /* Value is the best input style, given user preferences USER (already
3112 checked to be supported by Emacs), and styles supported by the
3113 input method XIM. */
3115 static XIMStyle
3116 best_xim_style (user, xim)
3117 XIMStyles *user;
3118 XIMStyles *xim;
3120 int i, j;
3122 for (i = 0; i < user->count_styles; ++i)
3123 for (j = 0; j < xim->count_styles; ++j)
3124 if (user->supported_styles[i] == xim->supported_styles[j])
3125 return user->supported_styles[i];
3127 /* Return the default style. */
3128 return XIMPreeditNothing | XIMStatusNothing;
3131 /* Create XIC for frame F. */
3133 void
3134 create_frame_xic (f)
3135 struct frame *f;
3137 XIM xim;
3138 XIC xic = NULL;
3139 XFontSet xfs = NULL;
3140 static XIMStyle xic_style;
3142 if (FRAME_XIC (f))
3143 return;
3145 xim = FRAME_X_XIM (f);
3146 if (xim)
3148 XRectangle s_area;
3149 XPoint spot;
3150 XVaNestedList preedit_attr;
3151 XVaNestedList status_attr;
3152 char *base_fontname;
3153 int fontset;
3155 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3156 spot.x = 0; spot.y = 1;
3157 /* Create X fontset. */
3158 fontset = FRAME_FONTSET (f);
3159 if (fontset < 0)
3160 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3161 else
3163 /* Determine the base fontname from the ASCII font name of
3164 FONTSET. */
3165 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3166 char *p = ascii_font;
3167 int i;
3169 for (i = 0; *p; p++)
3170 if (*p == '-') i++;
3171 if (i != 14)
3172 /* As the font name doesn't conform to XLFD, we can't
3173 modify it to get a suitable base fontname for the
3174 frame. */
3175 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3176 else
3178 int len = strlen (ascii_font) + 1;
3179 char *p1;
3181 for (i = 0, p = ascii_font; i < 8; p++)
3183 if (*p == '-')
3185 i++;
3186 if (i == 3)
3187 p1 = p + 1;
3190 base_fontname = (char *) alloca (len);
3191 bzero (base_fontname, len);
3192 strcpy (base_fontname, "-*-*-");
3193 bcopy (p1, base_fontname + 5, p - p1);
3194 strcat (base_fontname, "*-*-*-*-*-*-*");
3197 xfs = xic_create_xfontset (f, base_fontname);
3199 /* Determine XIC style. */
3200 if (xic_style == 0)
3202 XIMStyles supported_list;
3203 supported_list.count_styles = (sizeof supported_xim_styles
3204 / sizeof supported_xim_styles[0]);
3205 supported_list.supported_styles = supported_xim_styles;
3206 xic_style = best_xim_style (&supported_list,
3207 FRAME_X_XIM_STYLES (f));
3210 preedit_attr = XVaCreateNestedList (0,
3211 XNFontSet, xfs,
3212 XNForeground,
3213 FRAME_FOREGROUND_PIXEL (f),
3214 XNBackground,
3215 FRAME_BACKGROUND_PIXEL (f),
3216 (xic_style & XIMPreeditPosition
3217 ? XNSpotLocation
3218 : NULL),
3219 &spot,
3220 NULL);
3221 status_attr = XVaCreateNestedList (0,
3222 XNArea,
3223 &s_area,
3224 XNFontSet,
3225 xfs,
3226 XNForeground,
3227 FRAME_FOREGROUND_PIXEL (f),
3228 XNBackground,
3229 FRAME_BACKGROUND_PIXEL (f),
3230 NULL);
3232 xic = XCreateIC (xim,
3233 XNInputStyle, xic_style,
3234 XNClientWindow, FRAME_X_WINDOW(f),
3235 XNFocusWindow, FRAME_X_WINDOW(f),
3236 XNStatusAttributes, status_attr,
3237 XNPreeditAttributes, preedit_attr,
3238 NULL);
3239 XFree (preedit_attr);
3240 XFree (status_attr);
3243 FRAME_XIC (f) = xic;
3244 FRAME_XIC_STYLE (f) = xic_style;
3245 FRAME_XIC_FONTSET (f) = xfs;
3249 /* Destroy XIC and free XIC fontset of frame F, if any. */
3251 void
3252 free_frame_xic (f)
3253 struct frame *f;
3255 if (FRAME_XIC (f) == NULL)
3256 return;
3258 XDestroyIC (FRAME_XIC (f));
3259 if (FRAME_XIC_FONTSET (f))
3260 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3262 FRAME_XIC (f) = NULL;
3263 FRAME_XIC_FONTSET (f) = NULL;
3267 /* Place preedit area for XIC of window W's frame to specified
3268 pixel position X/Y. X and Y are relative to window W. */
3270 void
3271 xic_set_preeditarea (w, x, y)
3272 struct window *w;
3273 int x, y;
3275 struct frame *f = XFRAME (w->frame);
3276 XVaNestedList attr;
3277 XPoint spot;
3279 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3280 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3281 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3282 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3283 XFree (attr);
3287 /* Place status area for XIC in bottom right corner of frame F.. */
3289 void
3290 xic_set_statusarea (f)
3291 struct frame *f;
3293 XIC xic = FRAME_XIC (f);
3294 XVaNestedList attr;
3295 XRectangle area;
3296 XRectangle *needed;
3298 /* Negotiate geometry of status area. If input method has existing
3299 status area, use its current size. */
3300 area.x = area.y = area.width = area.height = 0;
3301 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3302 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3303 XFree (attr);
3305 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3306 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3307 XFree (attr);
3309 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3311 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3312 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3313 XFree (attr);
3316 area.width = needed->width;
3317 area.height = needed->height;
3318 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3319 area.y = (PIXEL_HEIGHT (f) - area.height
3320 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3321 XFree (needed);
3323 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3324 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3325 XFree (attr);
3329 /* Set X fontset for XIC of frame F, using base font name
3330 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3332 void
3333 xic_set_xfontset (f, base_fontname)
3334 struct frame *f;
3335 char *base_fontname;
3337 XVaNestedList attr;
3338 XFontSet xfs;
3340 xfs = xic_create_xfontset (f, base_fontname);
3342 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3343 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3344 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3345 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3346 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3347 XFree (attr);
3349 if (FRAME_XIC_FONTSET (f))
3350 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3351 FRAME_XIC_FONTSET (f) = xfs;
3354 #endif /* HAVE_X_I18N */
3358 #ifdef USE_X_TOOLKIT
3360 /* Create and set up the X widget for frame F. */
3362 static void
3363 x_window (f, window_prompting, minibuffer_only)
3364 struct frame *f;
3365 long window_prompting;
3366 int minibuffer_only;
3368 XClassHint class_hints;
3369 XSetWindowAttributes attributes;
3370 unsigned long attribute_mask;
3371 Widget shell_widget;
3372 Widget pane_widget;
3373 Widget frame_widget;
3374 Arg al [25];
3375 int ac;
3377 BLOCK_INPUT;
3379 /* Use the resource name as the top-level widget name
3380 for looking up resources. Make a non-Lisp copy
3381 for the window manager, so GC relocation won't bother it.
3383 Elsewhere we specify the window name for the window manager. */
3386 char *str = (char *) XSTRING (Vx_resource_name)->data;
3387 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3388 strcpy (f->namebuf, str);
3391 ac = 0;
3392 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3393 XtSetArg (al[ac], XtNinput, 1); ac++;
3394 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3395 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3396 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3397 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3398 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3399 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3400 applicationShellWidgetClass,
3401 FRAME_X_DISPLAY (f), al, ac);
3403 f->output_data.x->widget = shell_widget;
3404 /* maybe_set_screen_title_format (shell_widget); */
3406 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3407 (widget_value *) NULL,
3408 shell_widget, False,
3409 (lw_callback) NULL,
3410 (lw_callback) NULL,
3411 (lw_callback) NULL,
3412 (lw_callback) NULL);
3414 ac = 0;
3415 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3416 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3417 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3418 XtSetValues (pane_widget, al, ac);
3419 f->output_data.x->column_widget = pane_widget;
3421 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3422 the emacs screen when changing menubar. This reduces flickering. */
3424 ac = 0;
3425 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3426 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3427 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3428 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3429 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3430 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3431 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3432 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3433 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3434 al, ac);
3436 f->output_data.x->edit_widget = frame_widget;
3438 XtManageChild (frame_widget);
3440 /* Do some needed geometry management. */
3442 int len;
3443 char *tem, shell_position[32];
3444 Arg al[2];
3445 int ac = 0;
3446 int extra_borders = 0;
3447 int menubar_size
3448 = (f->output_data.x->menubar_widget
3449 ? (f->output_data.x->menubar_widget->core.height
3450 + f->output_data.x->menubar_widget->core.border_width)
3451 : 0);
3453 #if 0 /* Experimentally, we now get the right results
3454 for -geometry -0-0 without this. 24 Aug 96, rms. */
3455 if (FRAME_EXTERNAL_MENU_BAR (f))
3457 Dimension ibw = 0;
3458 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3459 menubar_size += ibw;
3461 #endif
3463 f->output_data.x->menubar_height = menubar_size;
3465 #ifndef USE_LUCID
3466 /* Motif seems to need this amount added to the sizes
3467 specified for the shell widget. The Athena/Lucid widgets don't.
3468 Both conclusions reached experimentally. -- rms. */
3469 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3470 &extra_borders, NULL);
3471 extra_borders *= 2;
3472 #endif
3474 /* Convert our geometry parameters into a geometry string
3475 and specify it.
3476 Note that we do not specify here whether the position
3477 is a user-specified or program-specified one.
3478 We pass that information later, in x_wm_set_size_hints. */
3480 int left = f->output_data.x->left_pos;
3481 int xneg = window_prompting & XNegative;
3482 int top = f->output_data.x->top_pos;
3483 int yneg = window_prompting & YNegative;
3484 if (xneg)
3485 left = -left;
3486 if (yneg)
3487 top = -top;
3489 if (window_prompting & USPosition)
3490 sprintf (shell_position, "=%dx%d%c%d%c%d",
3491 PIXEL_WIDTH (f) + extra_borders,
3492 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3493 (xneg ? '-' : '+'), left,
3494 (yneg ? '-' : '+'), top);
3495 else
3496 sprintf (shell_position, "=%dx%d",
3497 PIXEL_WIDTH (f) + extra_borders,
3498 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3501 len = strlen (shell_position) + 1;
3502 /* We don't free this because we don't know whether
3503 it is safe to free it while the frame exists.
3504 It isn't worth the trouble of arranging to free it
3505 when the frame is deleted. */
3506 tem = (char *) xmalloc (len);
3507 strncpy (tem, shell_position, len);
3508 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3509 XtSetValues (shell_widget, al, ac);
3512 XtManageChild (pane_widget);
3513 XtRealizeWidget (shell_widget);
3515 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3517 validate_x_resource_name ();
3519 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3520 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3521 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3523 #ifdef HAVE_X_I18N
3524 FRAME_XIC (f) = NULL;
3525 create_frame_xic (f);
3526 #endif
3528 f->output_data.x->wm_hints.input = True;
3529 f->output_data.x->wm_hints.flags |= InputHint;
3530 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3531 &f->output_data.x->wm_hints);
3533 hack_wm_protocols (f, shell_widget);
3535 #ifdef HACK_EDITRES
3536 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3537 #endif
3539 /* Do a stupid property change to force the server to generate a
3540 PropertyNotify event so that the event_stream server timestamp will
3541 be initialized to something relevant to the time we created the window.
3543 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3544 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3545 XA_ATOM, 32, PropModeAppend,
3546 (unsigned char*) NULL, 0);
3548 /* Make all the standard events reach the Emacs frame. */
3549 attributes.event_mask = STANDARD_EVENT_SET;
3551 #ifdef HAVE_X_I18N
3552 if (FRAME_XIC (f))
3554 /* XIM server might require some X events. */
3555 unsigned long fevent = NoEventMask;
3556 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3557 attributes.event_mask |= fevent;
3559 #endif /* HAVE_X_I18N */
3561 attribute_mask = CWEventMask;
3562 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3563 attribute_mask, &attributes);
3565 XtMapWidget (frame_widget);
3567 /* x_set_name normally ignores requests to set the name if the
3568 requested name is the same as the current name. This is the one
3569 place where that assumption isn't correct; f->name is set, but
3570 the X server hasn't been told. */
3572 Lisp_Object name;
3573 int explicit = f->explicit_name;
3575 f->explicit_name = 0;
3576 name = f->name;
3577 f->name = Qnil;
3578 x_set_name (f, name, explicit);
3581 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3582 f->output_data.x->text_cursor);
3584 UNBLOCK_INPUT;
3586 /* This is a no-op, except under Motif. Make sure main areas are
3587 set to something reasonable, in case we get an error later. */
3588 lw_set_main_areas (pane_widget, 0, frame_widget);
3591 #else /* not USE_X_TOOLKIT */
3593 /* Create and set up the X window for frame F. */
3595 void
3596 x_window (f)
3597 struct frame *f;
3600 XClassHint class_hints;
3601 XSetWindowAttributes attributes;
3602 unsigned long attribute_mask;
3604 attributes.background_pixel = f->output_data.x->background_pixel;
3605 attributes.border_pixel = f->output_data.x->border_pixel;
3606 attributes.bit_gravity = StaticGravity;
3607 attributes.backing_store = NotUseful;
3608 attributes.save_under = True;
3609 attributes.event_mask = STANDARD_EVENT_SET;
3610 attributes.colormap = FRAME_X_COLORMAP (f);
3611 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3612 | CWColormap);
3614 BLOCK_INPUT;
3615 FRAME_X_WINDOW (f)
3616 = XCreateWindow (FRAME_X_DISPLAY (f),
3617 f->output_data.x->parent_desc,
3618 f->output_data.x->left_pos,
3619 f->output_data.x->top_pos,
3620 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3621 f->output_data.x->border_width,
3622 CopyFromParent, /* depth */
3623 InputOutput, /* class */
3624 FRAME_X_VISUAL (f),
3625 attribute_mask, &attributes);
3627 #ifdef HAVE_X_I18N
3628 create_frame_xic (f);
3629 if (FRAME_XIC (f))
3631 /* XIM server might require some X events. */
3632 unsigned long fevent = NoEventMask;
3633 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3634 attributes.event_mask |= fevent;
3635 attribute_mask = CWEventMask;
3636 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3637 attribute_mask, &attributes);
3639 #endif /* HAVE_X_I18N */
3641 validate_x_resource_name ();
3643 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3644 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3645 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3647 /* The menubar is part of the ordinary display;
3648 it does not count in addition to the height of the window. */
3649 f->output_data.x->menubar_height = 0;
3651 /* This indicates that we use the "Passive Input" input model.
3652 Unless we do this, we don't get the Focus{In,Out} events that we
3653 need to draw the cursor correctly. Accursed bureaucrats.
3654 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3656 f->output_data.x->wm_hints.input = True;
3657 f->output_data.x->wm_hints.flags |= InputHint;
3658 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3659 &f->output_data.x->wm_hints);
3660 f->output_data.x->wm_hints.icon_pixmap = None;
3662 /* Request "save yourself" and "delete window" commands from wm. */
3664 Atom protocols[2];
3665 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3666 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3667 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3670 /* x_set_name normally ignores requests to set the name if the
3671 requested name is the same as the current name. This is the one
3672 place where that assumption isn't correct; f->name is set, but
3673 the X server hasn't been told. */
3675 Lisp_Object name;
3676 int explicit = f->explicit_name;
3678 f->explicit_name = 0;
3679 name = f->name;
3680 f->name = Qnil;
3681 x_set_name (f, name, explicit);
3684 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3685 f->output_data.x->text_cursor);
3687 UNBLOCK_INPUT;
3689 if (FRAME_X_WINDOW (f) == 0)
3690 error ("Unable to create window");
3693 #endif /* not USE_X_TOOLKIT */
3695 /* Handle the icon stuff for this window. Perhaps later we might
3696 want an x_set_icon_position which can be called interactively as
3697 well. */
3699 static void
3700 x_icon (f, parms)
3701 struct frame *f;
3702 Lisp_Object parms;
3704 Lisp_Object icon_x, icon_y;
3705 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3707 /* Set the position of the icon. Note that twm groups all
3708 icons in an icon window. */
3709 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3710 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3711 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3713 CHECK_NUMBER (icon_x, 0);
3714 CHECK_NUMBER (icon_y, 0);
3716 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3717 error ("Both left and top icon corners of icon must be specified");
3719 BLOCK_INPUT;
3721 if (! EQ (icon_x, Qunbound))
3722 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3724 /* Start up iconic or window? */
3725 x_wm_set_window_state
3726 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3727 Qicon)
3728 ? IconicState
3729 : NormalState));
3731 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3732 ? f->icon_name
3733 : f->name))->data);
3735 UNBLOCK_INPUT;
3738 /* Make the GC's needed for this window, setting the
3739 background, border and mouse colors; also create the
3740 mouse cursor and the gray border tile. */
3742 static char cursor_bits[] =
3744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3750 static void
3751 x_make_gc (f)
3752 struct frame *f;
3754 XGCValues gc_values;
3756 BLOCK_INPUT;
3758 /* Create the GC's of this frame.
3759 Note that many default values are used. */
3761 /* Normal video */
3762 gc_values.font = f->output_data.x->font->fid;
3763 gc_values.foreground = f->output_data.x->foreground_pixel;
3764 gc_values.background = f->output_data.x->background_pixel;
3765 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3766 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
3767 FRAME_X_WINDOW (f),
3768 GCLineWidth | GCFont
3769 | GCForeground | GCBackground,
3770 &gc_values);
3772 /* Reverse video style. */
3773 gc_values.foreground = f->output_data.x->background_pixel;
3774 gc_values.background = f->output_data.x->foreground_pixel;
3775 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
3776 FRAME_X_WINDOW (f),
3777 GCFont | GCForeground | GCBackground
3778 | GCLineWidth,
3779 &gc_values);
3781 /* Cursor has cursor-color background, background-color foreground. */
3782 gc_values.foreground = f->output_data.x->background_pixel;
3783 gc_values.background = f->output_data.x->cursor_pixel;
3784 gc_values.fill_style = FillOpaqueStippled;
3785 gc_values.stipple
3786 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3787 FRAME_X_DISPLAY_INFO (f)->root_window,
3788 cursor_bits, 16, 16);
3789 f->output_data.x->cursor_gc
3790 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3791 (GCFont | GCForeground | GCBackground
3792 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3793 &gc_values);
3795 /* Reliefs. */
3796 f->output_data.x->white_relief.gc = 0;
3797 f->output_data.x->black_relief.gc = 0;
3799 /* Create the gray border tile used when the pointer is not in
3800 the frame. Since this depends on the frame's pixel values,
3801 this must be done on a per-frame basis. */
3802 f->output_data.x->border_tile
3803 = (XCreatePixmapFromBitmapData
3804 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3805 gray_bits, gray_width, gray_height,
3806 f->output_data.x->foreground_pixel,
3807 f->output_data.x->background_pixel,
3808 DefaultDepth (FRAME_X_DISPLAY (f),
3809 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3811 UNBLOCK_INPUT;
3814 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3815 1, 1, 0,
3816 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3817 Returns an Emacs frame object.\n\
3818 ALIST is an alist of frame parameters.\n\
3819 If the parameters specify that the frame should not have a minibuffer,\n\
3820 and do not specify a specific minibuffer window to use,\n\
3821 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3822 be shared by the new frame.\n\
3824 This function is an internal primitive--use `make-frame' instead.")
3825 (parms)
3826 Lisp_Object parms;
3828 struct frame *f;
3829 Lisp_Object frame, tem;
3830 Lisp_Object name;
3831 int minibuffer_only = 0;
3832 long window_prompting = 0;
3833 int width, height;
3834 int count = specpdl_ptr - specpdl;
3835 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3836 Lisp_Object display;
3837 struct x_display_info *dpyinfo = NULL;
3838 Lisp_Object parent;
3839 struct kboard *kb;
3841 check_x ();
3843 /* Use this general default value to start with
3844 until we know if this frame has a specified name. */
3845 Vx_resource_name = Vinvocation_name;
3847 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3848 if (EQ (display, Qunbound))
3849 display = Qnil;
3850 dpyinfo = check_x_display_info (display);
3851 #ifdef MULTI_KBOARD
3852 kb = dpyinfo->kboard;
3853 #else
3854 kb = &the_only_kboard;
3855 #endif
3857 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3858 if (!STRINGP (name)
3859 && ! EQ (name, Qunbound)
3860 && ! NILP (name))
3861 error ("Invalid frame name--not a string or nil");
3863 if (STRINGP (name))
3864 Vx_resource_name = name;
3866 /* See if parent window is specified. */
3867 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3868 if (EQ (parent, Qunbound))
3869 parent = Qnil;
3870 if (! NILP (parent))
3871 CHECK_NUMBER (parent, 0);
3873 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3874 /* No need to protect DISPLAY because that's not used after passing
3875 it to make_frame_without_minibuffer. */
3876 frame = Qnil;
3877 GCPRO4 (parms, parent, name, frame);
3878 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3879 RES_TYPE_SYMBOL);
3880 if (EQ (tem, Qnone) || NILP (tem))
3881 f = make_frame_without_minibuffer (Qnil, kb, display);
3882 else if (EQ (tem, Qonly))
3884 f = make_minibuffer_frame ();
3885 minibuffer_only = 1;
3887 else if (WINDOWP (tem))
3888 f = make_frame_without_minibuffer (tem, kb, display);
3889 else
3890 f = make_frame (1);
3892 XSETFRAME (frame, f);
3894 /* Note that X Windows does support scroll bars. */
3895 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3897 f->output_method = output_x_window;
3898 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3899 bzero (f->output_data.x, sizeof (struct x_output));
3900 f->output_data.x->icon_bitmap = -1;
3901 f->output_data.x->fontset = -1;
3902 f->output_data.x->scroll_bar_foreground_pixel = -1;
3903 f->output_data.x->scroll_bar_background_pixel = -1;
3905 f->icon_name
3906 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3907 RES_TYPE_STRING);
3908 if (! STRINGP (f->icon_name))
3909 f->icon_name = Qnil;
3911 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3912 #ifdef MULTI_KBOARD
3913 FRAME_KBOARD (f) = kb;
3914 #endif
3916 /* These colors will be set anyway later, but it's important
3917 to get the color reference counts right, so initialize them! */
3919 Lisp_Object black;
3920 struct gcpro gcpro1;
3922 black = build_string ("black");
3923 GCPRO1 (black);
3924 f->output_data.x->foreground_pixel
3925 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3926 f->output_data.x->background_pixel
3927 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3928 f->output_data.x->cursor_pixel
3929 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3930 f->output_data.x->cursor_foreground_pixel
3931 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3932 f->output_data.x->border_pixel
3933 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3934 f->output_data.x->mouse_pixel
3935 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3936 UNGCPRO;
3939 /* Specify the parent under which to make this X window. */
3941 if (!NILP (parent))
3943 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3944 f->output_data.x->explicit_parent = 1;
3946 else
3948 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3949 f->output_data.x->explicit_parent = 0;
3952 /* Set the name; the functions to which we pass f expect the name to
3953 be set. */
3954 if (EQ (name, Qunbound) || NILP (name))
3956 f->name = build_string (dpyinfo->x_id_name);
3957 f->explicit_name = 0;
3959 else
3961 f->name = name;
3962 f->explicit_name = 1;
3963 /* use the frame's title when getting resources for this frame. */
3964 specbind (Qx_resource_name, name);
3967 /* Extract the window parameters from the supplied values
3968 that are needed to determine window geometry. */
3970 Lisp_Object font;
3972 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3974 BLOCK_INPUT;
3975 /* First, try whatever font the caller has specified. */
3976 if (STRINGP (font))
3978 tem = Fquery_fontset (font, Qnil);
3979 if (STRINGP (tem))
3980 font = x_new_fontset (f, XSTRING (tem)->data);
3981 else
3982 font = x_new_font (f, XSTRING (font)->data);
3985 /* Try out a font which we hope has bold and italic variations. */
3986 if (!STRINGP (font))
3987 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3988 if (!STRINGP (font))
3989 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3990 if (! STRINGP (font))
3991 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3992 if (! STRINGP (font))
3993 /* This was formerly the first thing tried, but it finds too many fonts
3994 and takes too long. */
3995 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3996 /* If those didn't work, look for something which will at least work. */
3997 if (! STRINGP (font))
3998 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3999 UNBLOCK_INPUT;
4000 if (! STRINGP (font))
4001 font = build_string ("fixed");
4003 x_default_parameter (f, parms, Qfont, font,
4004 "font", "Font", RES_TYPE_STRING);
4007 #ifdef USE_LUCID
4008 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4009 whereby it fails to get any font. */
4010 xlwmenu_default_font = f->output_data.x->font;
4011 #endif
4013 x_default_parameter (f, parms, Qborder_width, make_number (2),
4014 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4016 /* This defaults to 2 in order to match xterm. We recognize either
4017 internalBorderWidth or internalBorder (which is what xterm calls
4018 it). */
4019 if (NILP (Fassq (Qinternal_border_width, parms)))
4021 Lisp_Object value;
4023 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4024 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4025 if (! EQ (value, Qunbound))
4026 parms = Fcons (Fcons (Qinternal_border_width, value),
4027 parms);
4029 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4030 "internalBorderWidth", "internalBorderWidth",
4031 RES_TYPE_NUMBER);
4032 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4033 "verticalScrollBars", "ScrollBars",
4034 RES_TYPE_SYMBOL);
4036 /* Also do the stuff which must be set before the window exists. */
4037 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4038 "foreground", "Foreground", RES_TYPE_STRING);
4039 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4040 "background", "Background", RES_TYPE_STRING);
4041 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4042 "pointerColor", "Foreground", RES_TYPE_STRING);
4043 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4044 "cursorColor", "Foreground", RES_TYPE_STRING);
4045 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4046 "borderColor", "BorderColor", RES_TYPE_STRING);
4047 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4048 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4049 x_default_parameter (f, parms, Qline_spacing, Qnil,
4050 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4052 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4053 "scrollBarForeground",
4054 "ScrollBarForeground", 1);
4055 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4056 "scrollBarBackground",
4057 "ScrollBarBackground", 0);
4059 /* Init faces before x_default_parameter is called for scroll-bar
4060 parameters because that function calls x_set_scroll_bar_width,
4061 which calls change_frame_size, which calls Fset_window_buffer,
4062 which runs hooks, which call Fvertical_motion. At the end, we
4063 end up in init_iterator with a null face cache, which should not
4064 happen. */
4065 init_frame_faces (f);
4067 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4068 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4069 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
4070 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4071 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4072 "bufferPredicate", "BufferPredicate",
4073 RES_TYPE_SYMBOL);
4074 x_default_parameter (f, parms, Qtitle, Qnil,
4075 "title", "Title", RES_TYPE_STRING);
4077 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4078 window_prompting = x_figure_window_size (f, parms);
4080 if (window_prompting & XNegative)
4082 if (window_prompting & YNegative)
4083 f->output_data.x->win_gravity = SouthEastGravity;
4084 else
4085 f->output_data.x->win_gravity = NorthEastGravity;
4087 else
4089 if (window_prompting & YNegative)
4090 f->output_data.x->win_gravity = SouthWestGravity;
4091 else
4092 f->output_data.x->win_gravity = NorthWestGravity;
4095 f->output_data.x->size_hint_flags = window_prompting;
4097 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4098 f->no_split = minibuffer_only || EQ (tem, Qt);
4100 /* Create the X widget or window. Add the tool-bar height to the
4101 initial frame height so that the user gets a text display area of
4102 the size he specified with -g or via .Xdefaults. Later changes
4103 of the tool-bar height don't change the frame size. This is done
4104 so that users can create tall Emacs frames without having to
4105 guess how tall the tool-bar will get. */
4106 f->height += FRAME_TOOL_BAR_LINES (f);
4108 #ifdef USE_X_TOOLKIT
4109 x_window (f, window_prompting, minibuffer_only);
4110 #else
4111 x_window (f);
4112 #endif
4114 x_icon (f, parms);
4115 x_make_gc (f);
4117 /* Now consider the frame official. */
4118 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4119 Vframe_list = Fcons (frame, Vframe_list);
4121 /* We need to do this after creating the X window, so that the
4122 icon-creation functions can say whose icon they're describing. */
4123 x_default_parameter (f, parms, Qicon_type, Qnil,
4124 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4126 x_default_parameter (f, parms, Qauto_raise, Qnil,
4127 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4128 x_default_parameter (f, parms, Qauto_lower, Qnil,
4129 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4130 x_default_parameter (f, parms, Qcursor_type, Qbox,
4131 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4132 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4133 "scrollBarWidth", "ScrollBarWidth",
4134 RES_TYPE_NUMBER);
4136 /* Dimensions, especially f->height, must be done via change_frame_size.
4137 Change will not be effected unless different from the current
4138 f->height. */
4139 width = f->width;
4140 height = f->height;
4141 f->height = 0;
4142 SET_FRAME_WIDTH (f, 0);
4143 change_frame_size (f, height, width, 1, 0, 0);
4145 /* Set up faces after all frame parameters are known. */
4146 call1 (Qface_set_after_frame_default, frame);
4148 #ifdef USE_X_TOOLKIT
4149 /* Create the menu bar. */
4150 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4152 /* If this signals an error, we haven't set size hints for the
4153 frame and we didn't make it visible. */
4154 initialize_frame_menubar (f);
4156 /* This is a no-op, except under Motif where it arranges the
4157 main window for the widgets on it. */
4158 lw_set_main_areas (f->output_data.x->column_widget,
4159 f->output_data.x->menubar_widget,
4160 f->output_data.x->edit_widget);
4162 #endif /* USE_X_TOOLKIT */
4164 /* Tell the server what size and position, etc, we want, and how
4165 badly we want them. This should be done after we have the menu
4166 bar so that its size can be taken into account. */
4167 BLOCK_INPUT;
4168 x_wm_set_size_hint (f, window_prompting, 0);
4169 UNBLOCK_INPUT;
4171 /* Make the window appear on the frame and enable display, unless
4172 the caller says not to. However, with explicit parent, Emacs
4173 cannot control visibility, so don't try. */
4174 if (! f->output_data.x->explicit_parent)
4176 Lisp_Object visibility;
4178 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4179 RES_TYPE_SYMBOL);
4180 if (EQ (visibility, Qunbound))
4181 visibility = Qt;
4183 if (EQ (visibility, Qicon))
4184 x_iconify_frame (f);
4185 else if (! NILP (visibility))
4186 x_make_frame_visible (f);
4187 else
4188 /* Must have been Qnil. */
4192 UNGCPRO;
4193 return unbind_to (count, frame);
4196 /* FRAME is used only to get a handle on the X display. We don't pass the
4197 display info directly because we're called from frame.c, which doesn't
4198 know about that structure. */
4200 Lisp_Object
4201 x_get_focus_frame (frame)
4202 struct frame *frame;
4204 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4205 Lisp_Object xfocus;
4206 if (! dpyinfo->x_focus_frame)
4207 return Qnil;
4209 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4210 return xfocus;
4214 /* In certain situations, when the window manager follows a
4215 click-to-focus policy, there seems to be no way around calling
4216 XSetInputFocus to give another frame the input focus .
4218 In an ideal world, XSetInputFocus should generally be avoided so
4219 that applications don't interfere with the window manager's focus
4220 policy. But I think it's okay to use when it's clearly done
4221 following a user-command. */
4223 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4224 "Set the input focus to FRAME.\n\
4225 FRAME nil means use the selected frame.")
4226 (frame)
4227 Lisp_Object frame;
4229 struct frame *f = check_x_frame (frame);
4230 Display *dpy = FRAME_X_DISPLAY (f);
4231 int count;
4233 BLOCK_INPUT;
4234 count = x_catch_errors (dpy);
4235 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4236 RevertToParent, CurrentTime);
4237 x_uncatch_errors (dpy, count);
4238 UNBLOCK_INPUT;
4240 return Qnil;
4244 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4245 "Internal function called by `color-defined-p', which see.")
4246 (color, frame)
4247 Lisp_Object color, frame;
4249 XColor foo;
4250 FRAME_PTR f = check_x_frame (frame);
4252 CHECK_STRING (color, 1);
4254 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4255 return Qt;
4256 else
4257 return Qnil;
4260 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4261 "Internal function called by `color-values', which see.")
4262 (color, frame)
4263 Lisp_Object color, frame;
4265 XColor foo;
4266 FRAME_PTR f = check_x_frame (frame);
4268 CHECK_STRING (color, 1);
4270 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4272 Lisp_Object rgb[3];
4274 rgb[0] = make_number (foo.red);
4275 rgb[1] = make_number (foo.green);
4276 rgb[2] = make_number (foo.blue);
4277 return Flist (3, rgb);
4279 else
4280 return Qnil;
4283 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4284 "Internal function called by `display-color-p', which see.")
4285 (display)
4286 Lisp_Object display;
4288 struct x_display_info *dpyinfo = check_x_display_info (display);
4290 if (dpyinfo->n_planes <= 2)
4291 return Qnil;
4293 switch (dpyinfo->visual->class)
4295 case StaticColor:
4296 case PseudoColor:
4297 case TrueColor:
4298 case DirectColor:
4299 return Qt;
4301 default:
4302 return Qnil;
4306 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4307 0, 1, 0,
4308 "Return t if the X display supports shades of gray.\n\
4309 Note that color displays do support shades of gray.\n\
4310 The optional argument DISPLAY specifies which display to ask about.\n\
4311 DISPLAY should be either a frame or a display name (a string).\n\
4312 If omitted or nil, that stands for the selected frame's display.")
4313 (display)
4314 Lisp_Object display;
4316 struct x_display_info *dpyinfo = check_x_display_info (display);
4318 if (dpyinfo->n_planes <= 1)
4319 return Qnil;
4321 switch (dpyinfo->visual->class)
4323 case StaticColor:
4324 case PseudoColor:
4325 case TrueColor:
4326 case DirectColor:
4327 case StaticGray:
4328 case GrayScale:
4329 return Qt;
4331 default:
4332 return Qnil;
4336 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4337 0, 1, 0,
4338 "Returns the width in pixels of the X display DISPLAY.\n\
4339 The optional argument DISPLAY specifies which display to ask about.\n\
4340 DISPLAY should be either a frame or a display name (a string).\n\
4341 If omitted or nil, that stands for the selected frame's display.")
4342 (display)
4343 Lisp_Object display;
4345 struct x_display_info *dpyinfo = check_x_display_info (display);
4347 return make_number (dpyinfo->width);
4350 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4351 Sx_display_pixel_height, 0, 1, 0,
4352 "Returns the height in pixels of the X display DISPLAY.\n\
4353 The optional argument DISPLAY specifies which display to ask about.\n\
4354 DISPLAY should be either a frame or a display name (a string).\n\
4355 If omitted or nil, that stands for the selected frame's display.")
4356 (display)
4357 Lisp_Object display;
4359 struct x_display_info *dpyinfo = check_x_display_info (display);
4361 return make_number (dpyinfo->height);
4364 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4365 0, 1, 0,
4366 "Returns the number of bitplanes of the X display DISPLAY.\n\
4367 The optional argument DISPLAY specifies which display to ask about.\n\
4368 DISPLAY should be either a frame or a display name (a string).\n\
4369 If omitted or nil, that stands for the selected frame's display.")
4370 (display)
4371 Lisp_Object display;
4373 struct x_display_info *dpyinfo = check_x_display_info (display);
4375 return make_number (dpyinfo->n_planes);
4378 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4379 0, 1, 0,
4380 "Returns the number of color cells of the X display DISPLAY.\n\
4381 The optional argument DISPLAY specifies which display to ask about.\n\
4382 DISPLAY should be either a frame or a display name (a string).\n\
4383 If omitted or nil, that stands for the selected frame's display.")
4384 (display)
4385 Lisp_Object display;
4387 struct x_display_info *dpyinfo = check_x_display_info (display);
4389 return make_number (DisplayCells (dpyinfo->display,
4390 XScreenNumberOfScreen (dpyinfo->screen)));
4393 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4394 Sx_server_max_request_size,
4395 0, 1, 0,
4396 "Returns the maximum request size of the X server of display DISPLAY.\n\
4397 The optional argument DISPLAY specifies which display to ask about.\n\
4398 DISPLAY should be either a frame or a display name (a string).\n\
4399 If omitted or nil, that stands for the selected frame's display.")
4400 (display)
4401 Lisp_Object display;
4403 struct x_display_info *dpyinfo = check_x_display_info (display);
4405 return make_number (MAXREQUEST (dpyinfo->display));
4408 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4409 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4410 The optional argument DISPLAY specifies which display to ask about.\n\
4411 DISPLAY should be either a frame or a display name (a string).\n\
4412 If omitted or nil, that stands for the selected frame's display.")
4413 (display)
4414 Lisp_Object display;
4416 struct x_display_info *dpyinfo = check_x_display_info (display);
4417 char *vendor = ServerVendor (dpyinfo->display);
4419 if (! vendor) vendor = "";
4420 return build_string (vendor);
4423 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4424 "Returns the version numbers of the X server of display DISPLAY.\n\
4425 The value is a list of three integers: the major and minor\n\
4426 version numbers of the X Protocol in use, and the vendor-specific release\n\
4427 number. See also the function `x-server-vendor'.\n\n\
4428 The optional argument DISPLAY specifies which display to ask about.\n\
4429 DISPLAY should be either a frame or a display name (a string).\n\
4430 If omitted or nil, that stands for the selected frame's display.")
4431 (display)
4432 Lisp_Object display;
4434 struct x_display_info *dpyinfo = check_x_display_info (display);
4435 Display *dpy = dpyinfo->display;
4437 return Fcons (make_number (ProtocolVersion (dpy)),
4438 Fcons (make_number (ProtocolRevision (dpy)),
4439 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4442 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4443 "Returns the number of screens on the X server of display DISPLAY.\n\
4444 The optional argument DISPLAY specifies which display to ask about.\n\
4445 DISPLAY should be either a frame or a display name (a string).\n\
4446 If omitted or nil, that stands for the selected frame's display.")
4447 (display)
4448 Lisp_Object display;
4450 struct x_display_info *dpyinfo = check_x_display_info (display);
4452 return make_number (ScreenCount (dpyinfo->display));
4455 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4456 "Returns the height in millimeters of the X display DISPLAY.\n\
4457 The optional argument DISPLAY specifies which display to ask about.\n\
4458 DISPLAY should be either a frame or a display name (a string).\n\
4459 If omitted or nil, that stands for the selected frame's display.")
4460 (display)
4461 Lisp_Object display;
4463 struct x_display_info *dpyinfo = check_x_display_info (display);
4465 return make_number (HeightMMOfScreen (dpyinfo->screen));
4468 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4469 "Returns the width in millimeters 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 (WidthMMOfScreen (dpyinfo->screen));
4481 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4482 Sx_display_backing_store, 0, 1, 0,
4483 "Returns an indication of whether X display DISPLAY does backing store.\n\
4484 The value may be `always', `when-mapped', or `not-useful'.\n\
4485 The optional argument DISPLAY specifies which display to ask about.\n\
4486 DISPLAY should be either a frame or a display name (a string).\n\
4487 If omitted or nil, that stands for the selected frame's display.")
4488 (display)
4489 Lisp_Object display;
4491 struct x_display_info *dpyinfo = check_x_display_info (display);
4493 switch (DoesBackingStore (dpyinfo->screen))
4495 case Always:
4496 return intern ("always");
4498 case WhenMapped:
4499 return intern ("when-mapped");
4501 case NotUseful:
4502 return intern ("not-useful");
4504 default:
4505 error ("Strange value for BackingStore parameter of screen");
4509 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4510 Sx_display_visual_class, 0, 1, 0,
4511 "Returns the visual class of the X display DISPLAY.\n\
4512 The value is one of the symbols `static-gray', `gray-scale',\n\
4513 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4514 The optional argument DISPLAY specifies which display to ask about.\n\
4515 DISPLAY should be either a frame or a display name (a string).\n\
4516 If omitted or nil, that stands for the selected frame's display.")
4517 (display)
4518 Lisp_Object display;
4520 struct x_display_info *dpyinfo = check_x_display_info (display);
4522 switch (dpyinfo->visual->class)
4524 case StaticGray: return (intern ("static-gray"));
4525 case GrayScale: return (intern ("gray-scale"));
4526 case StaticColor: return (intern ("static-color"));
4527 case PseudoColor: return (intern ("pseudo-color"));
4528 case TrueColor: return (intern ("true-color"));
4529 case DirectColor: return (intern ("direct-color"));
4530 default:
4531 error ("Display has an unknown visual class");
4535 DEFUN ("x-display-save-under", Fx_display_save_under,
4536 Sx_display_save_under, 0, 1, 0,
4537 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4538 The optional argument DISPLAY specifies which display to ask about.\n\
4539 DISPLAY should be either a frame or a display name (a string).\n\
4540 If omitted or nil, that stands for the selected frame's display.")
4541 (display)
4542 Lisp_Object display;
4544 struct x_display_info *dpyinfo = check_x_display_info (display);
4546 if (DoesSaveUnders (dpyinfo->screen) == True)
4547 return Qt;
4548 else
4549 return Qnil;
4553 x_pixel_width (f)
4554 register struct frame *f;
4556 return PIXEL_WIDTH (f);
4560 x_pixel_height (f)
4561 register struct frame *f;
4563 return PIXEL_HEIGHT (f);
4567 x_char_width (f)
4568 register struct frame *f;
4570 return FONT_WIDTH (f->output_data.x->font);
4574 x_char_height (f)
4575 register struct frame *f;
4577 return f->output_data.x->line_height;
4581 x_screen_planes (f)
4582 register struct frame *f;
4584 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4589 /************************************************************************
4590 X Displays
4591 ************************************************************************/
4594 /* Mapping visual names to visuals. */
4596 static struct visual_class
4598 char *name;
4599 int class;
4601 visual_classes[] =
4603 {"StaticGray", StaticGray},
4604 {"GrayScale", GrayScale},
4605 {"StaticColor", StaticColor},
4606 {"PseudoColor", PseudoColor},
4607 {"TrueColor", TrueColor},
4608 {"DirectColor", DirectColor},
4609 NULL
4613 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4615 /* Value is the screen number of screen SCR. This is a substitute for
4616 the X function with the same name when that doesn't exist. */
4619 XScreenNumberOfScreen (scr)
4620 register Screen *scr;
4622 Display *dpy = scr->display;
4623 int i;
4625 for (i = 0; i < dpy->nscreens; ++i)
4626 if (scr == dpy->screens[i])
4627 break;
4629 return i;
4632 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4635 /* Select the visual that should be used on display DPYINFO. Set
4636 members of DPYINFO appropriately. Called from x_term_init. */
4638 void
4639 select_visual (dpyinfo)
4640 struct x_display_info *dpyinfo;
4642 Display *dpy = dpyinfo->display;
4643 Screen *screen = dpyinfo->screen;
4644 Lisp_Object value;
4646 /* See if a visual is specified. */
4647 value = display_x_get_resource (dpyinfo,
4648 build_string ("visualClass"),
4649 build_string ("VisualClass"),
4650 Qnil, Qnil);
4651 if (STRINGP (value))
4653 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4654 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4655 depth, a decimal number. NAME is compared with case ignored. */
4656 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
4657 char *dash;
4658 int i, class = -1;
4659 XVisualInfo vinfo;
4661 strcpy (s, XSTRING (value)->data);
4662 dash = index (s, '-');
4663 if (dash)
4665 dpyinfo->n_planes = atoi (dash + 1);
4666 *dash = '\0';
4668 else
4669 /* We won't find a matching visual with depth 0, so that
4670 an error will be printed below. */
4671 dpyinfo->n_planes = 0;
4673 /* Determine the visual class. */
4674 for (i = 0; visual_classes[i].name; ++i)
4675 if (xstricmp (s, visual_classes[i].name) == 0)
4677 class = visual_classes[i].class;
4678 break;
4681 /* Look up a matching visual for the specified class. */
4682 if (class == -1
4683 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4684 dpyinfo->n_planes, class, &vinfo))
4685 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
4687 dpyinfo->visual = vinfo.visual;
4689 else
4691 int n_visuals;
4692 XVisualInfo *vinfo, vinfo_template;
4694 dpyinfo->visual = DefaultVisualOfScreen (screen);
4696 #ifdef HAVE_X11R4
4697 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
4698 #else
4699 vinfo_template.visualid = dpyinfo->visual->visualid;
4700 #endif
4701 vinfo_template.screen = XScreenNumberOfScreen (screen);
4702 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
4703 &vinfo_template, &n_visuals);
4704 if (n_visuals != 1)
4705 fatal ("Can't get proper X visual info");
4707 dpyinfo->n_planes = vinfo->depth;
4708 XFree ((char *) vinfo);
4713 /* Return the X display structure for the display named NAME.
4714 Open a new connection if necessary. */
4716 struct x_display_info *
4717 x_display_info_for_name (name)
4718 Lisp_Object name;
4720 Lisp_Object names;
4721 struct x_display_info *dpyinfo;
4723 CHECK_STRING (name, 0);
4725 if (! EQ (Vwindow_system, intern ("x")))
4726 error ("Not using X Windows");
4728 for (dpyinfo = x_display_list, names = x_display_name_list;
4729 dpyinfo;
4730 dpyinfo = dpyinfo->next, names = XCDR (names))
4732 Lisp_Object tem;
4733 tem = Fstring_equal (XCAR (XCAR (names)), name);
4734 if (!NILP (tem))
4735 return dpyinfo;
4738 /* Use this general default value to start with. */
4739 Vx_resource_name = Vinvocation_name;
4741 validate_x_resource_name ();
4743 dpyinfo = x_term_init (name, (unsigned char *)0,
4744 (char *) XSTRING (Vx_resource_name)->data);
4746 if (dpyinfo == 0)
4747 error ("Cannot connect to X server %s", XSTRING (name)->data);
4749 x_in_use = 1;
4750 XSETFASTINT (Vwindow_system_version, 11);
4752 return dpyinfo;
4756 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4757 1, 3, 0, "Open a connection to an X server.\n\
4758 DISPLAY is the name of the display to connect to.\n\
4759 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4760 If the optional third arg MUST-SUCCEED is non-nil,\n\
4761 terminate Emacs if we can't open the connection.")
4762 (display, xrm_string, must_succeed)
4763 Lisp_Object display, xrm_string, must_succeed;
4765 unsigned char *xrm_option;
4766 struct x_display_info *dpyinfo;
4768 CHECK_STRING (display, 0);
4769 if (! NILP (xrm_string))
4770 CHECK_STRING (xrm_string, 1);
4772 if (! EQ (Vwindow_system, intern ("x")))
4773 error ("Not using X Windows");
4775 if (! NILP (xrm_string))
4776 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4777 else
4778 xrm_option = (unsigned char *) 0;
4780 validate_x_resource_name ();
4782 /* This is what opens the connection and sets x_current_display.
4783 This also initializes many symbols, such as those used for input. */
4784 dpyinfo = x_term_init (display, xrm_option,
4785 (char *) XSTRING (Vx_resource_name)->data);
4787 if (dpyinfo == 0)
4789 if (!NILP (must_succeed))
4790 fatal ("Cannot connect to X server %s.\n\
4791 Check the DISPLAY environment variable or use `-d'.\n\
4792 Also use the `xhost' program to verify that it is set to permit\n\
4793 connections from your machine.\n",
4794 XSTRING (display)->data);
4795 else
4796 error ("Cannot connect to X server %s", XSTRING (display)->data);
4799 x_in_use = 1;
4801 XSETFASTINT (Vwindow_system_version, 11);
4802 return Qnil;
4805 DEFUN ("x-close-connection", Fx_close_connection,
4806 Sx_close_connection, 1, 1, 0,
4807 "Close the connection to DISPLAY's X server.\n\
4808 For DISPLAY, specify either a frame or a display name (a string).\n\
4809 If DISPLAY is nil, that stands for the selected frame's display.")
4810 (display)
4811 Lisp_Object display;
4813 struct x_display_info *dpyinfo = check_x_display_info (display);
4814 int i;
4816 if (dpyinfo->reference_count > 0)
4817 error ("Display still has frames on it");
4819 BLOCK_INPUT;
4820 /* Free the fonts in the font table. */
4821 for (i = 0; i < dpyinfo->n_fonts; i++)
4822 if (dpyinfo->font_table[i].name)
4824 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4825 xfree (dpyinfo->font_table[i].full_name);
4826 xfree (dpyinfo->font_table[i].name);
4827 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4830 x_destroy_all_bitmaps (dpyinfo);
4831 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4833 #ifdef USE_X_TOOLKIT
4834 XtCloseDisplay (dpyinfo->display);
4835 #else
4836 XCloseDisplay (dpyinfo->display);
4837 #endif
4839 x_delete_display (dpyinfo);
4840 UNBLOCK_INPUT;
4842 return Qnil;
4845 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4846 "Return the list of display names that Emacs has connections to.")
4849 Lisp_Object tail, result;
4851 result = Qnil;
4852 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4853 result = Fcons (XCAR (XCAR (tail)), result);
4855 return result;
4858 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4859 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
4860 If ON is nil, allow buffering of requests.\n\
4861 Turning on synchronization prohibits the Xlib routines from buffering\n\
4862 requests and seriously degrades performance, but makes debugging much\n\
4863 easier.\n\
4864 The optional second argument DISPLAY specifies which display to act on.\n\
4865 DISPLAY should be either a frame or a display name (a string).\n\
4866 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
4867 (on, display)
4868 Lisp_Object display, on;
4870 struct x_display_info *dpyinfo = check_x_display_info (display);
4872 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
4874 return Qnil;
4877 /* Wait for responses to all X commands issued so far for frame F. */
4879 void
4880 x_sync (f)
4881 FRAME_PTR f;
4883 BLOCK_INPUT;
4884 XSync (FRAME_X_DISPLAY (f), False);
4885 UNBLOCK_INPUT;
4889 /***********************************************************************
4890 Image types
4891 ***********************************************************************/
4893 /* Value is the number of elements of vector VECTOR. */
4895 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4897 /* List of supported image types. Use define_image_type to add new
4898 types. Use lookup_image_type to find a type for a given symbol. */
4900 static struct image_type *image_types;
4902 /* The symbol `image' which is the car of the lists used to represent
4903 images in Lisp. */
4905 extern Lisp_Object Qimage;
4907 /* The symbol `xbm' which is used as the type symbol for XBM images. */
4909 Lisp_Object Qxbm;
4911 /* Keywords. */
4913 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
4914 extern Lisp_Object QCdata;
4915 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
4916 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
4917 Lisp_Object QCindex;
4919 /* Other symbols. */
4921 Lisp_Object Qlaplace;
4923 /* Time in seconds after which images should be removed from the cache
4924 if not displayed. */
4926 Lisp_Object Vimage_cache_eviction_delay;
4928 /* Function prototypes. */
4930 static void define_image_type P_ ((struct image_type *type));
4931 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
4932 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
4933 static void x_laplace P_ ((struct frame *, struct image *));
4934 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
4935 Lisp_Object));
4938 /* Define a new image type from TYPE. This adds a copy of TYPE to
4939 image_types and adds the symbol *TYPE->type to Vimage_types. */
4941 static void
4942 define_image_type (type)
4943 struct image_type *type;
4945 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
4946 The initialized data segment is read-only. */
4947 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
4948 bcopy (type, p, sizeof *p);
4949 p->next = image_types;
4950 image_types = p;
4951 Vimage_types = Fcons (*p->type, Vimage_types);
4955 /* Look up image type SYMBOL, and return a pointer to its image_type
4956 structure. Value is null if SYMBOL is not a known image type. */
4958 static INLINE struct image_type *
4959 lookup_image_type (symbol)
4960 Lisp_Object symbol;
4962 struct image_type *type;
4964 for (type = image_types; type; type = type->next)
4965 if (EQ (symbol, *type->type))
4966 break;
4968 return type;
4972 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
4973 valid image specification is a list whose car is the symbol
4974 `image', and whose rest is a property list. The property list must
4975 contain a value for key `:type'. That value must be the name of a
4976 supported image type. The rest of the property list depends on the
4977 image type. */
4980 valid_image_p (object)
4981 Lisp_Object object;
4983 int valid_p = 0;
4985 if (CONSP (object) && EQ (XCAR (object), Qimage))
4987 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
4988 struct image_type *type = lookup_image_type (symbol);
4990 if (type)
4991 valid_p = type->valid_p (object);
4994 return valid_p;
4998 /* Log error message with format string FORMAT and argument ARG.
4999 Signaling an error, e.g. when an image cannot be loaded, is not a
5000 good idea because this would interrupt redisplay, and the error
5001 message display would lead to another redisplay. This function
5002 therefore simply displays a message. */
5004 static void
5005 image_error (format, arg1, arg2)
5006 char *format;
5007 Lisp_Object arg1, arg2;
5009 add_to_log (format, arg1, arg2);
5014 /***********************************************************************
5015 Image specifications
5016 ***********************************************************************/
5018 enum image_value_type
5020 IMAGE_DONT_CHECK_VALUE_TYPE,
5021 IMAGE_STRING_VALUE,
5022 IMAGE_SYMBOL_VALUE,
5023 IMAGE_POSITIVE_INTEGER_VALUE,
5024 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5025 IMAGE_ASCENT_VALUE,
5026 IMAGE_INTEGER_VALUE,
5027 IMAGE_FUNCTION_VALUE,
5028 IMAGE_NUMBER_VALUE,
5029 IMAGE_BOOL_VALUE
5032 /* Structure used when parsing image specifications. */
5034 struct image_keyword
5036 /* Name of keyword. */
5037 char *name;
5039 /* The type of value allowed. */
5040 enum image_value_type type;
5042 /* Non-zero means key must be present. */
5043 int mandatory_p;
5045 /* Used to recognize duplicate keywords in a property list. */
5046 int count;
5048 /* The value that was found. */
5049 Lisp_Object value;
5053 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5054 int, Lisp_Object));
5055 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5058 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5059 has the format (image KEYWORD VALUE ...). One of the keyword/
5060 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5061 image_keywords structures of size NKEYWORDS describing other
5062 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5064 static int
5065 parse_image_spec (spec, keywords, nkeywords, type)
5066 Lisp_Object spec;
5067 struct image_keyword *keywords;
5068 int nkeywords;
5069 Lisp_Object type;
5071 int i;
5072 Lisp_Object plist;
5074 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5075 return 0;
5077 plist = XCDR (spec);
5078 while (CONSP (plist))
5080 Lisp_Object key, value;
5082 /* First element of a pair must be a symbol. */
5083 key = XCAR (plist);
5084 plist = XCDR (plist);
5085 if (!SYMBOLP (key))
5086 return 0;
5088 /* There must follow a value. */
5089 if (!CONSP (plist))
5090 return 0;
5091 value = XCAR (plist);
5092 plist = XCDR (plist);
5094 /* Find key in KEYWORDS. Error if not found. */
5095 for (i = 0; i < nkeywords; ++i)
5096 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5097 break;
5099 if (i == nkeywords)
5100 continue;
5102 /* Record that we recognized the keyword. If a keywords
5103 was found more than once, it's an error. */
5104 keywords[i].value = value;
5105 ++keywords[i].count;
5107 if (keywords[i].count > 1)
5108 return 0;
5110 /* Check type of value against allowed type. */
5111 switch (keywords[i].type)
5113 case IMAGE_STRING_VALUE:
5114 if (!STRINGP (value))
5115 return 0;
5116 break;
5118 case IMAGE_SYMBOL_VALUE:
5119 if (!SYMBOLP (value))
5120 return 0;
5121 break;
5123 case IMAGE_POSITIVE_INTEGER_VALUE:
5124 if (!INTEGERP (value) || XINT (value) <= 0)
5125 return 0;
5126 break;
5128 case IMAGE_ASCENT_VALUE:
5129 if (SYMBOLP (value) && EQ (value, Qcenter))
5130 break;
5131 else if (INTEGERP (value)
5132 && XINT (value) >= 0
5133 && XINT (value) <= 100)
5134 break;
5135 return 0;
5137 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5138 if (!INTEGERP (value) || XINT (value) < 0)
5139 return 0;
5140 break;
5142 case IMAGE_DONT_CHECK_VALUE_TYPE:
5143 break;
5145 case IMAGE_FUNCTION_VALUE:
5146 value = indirect_function (value);
5147 if (SUBRP (value)
5148 || COMPILEDP (value)
5149 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5150 break;
5151 return 0;
5153 case IMAGE_NUMBER_VALUE:
5154 if (!INTEGERP (value) && !FLOATP (value))
5155 return 0;
5156 break;
5158 case IMAGE_INTEGER_VALUE:
5159 if (!INTEGERP (value))
5160 return 0;
5161 break;
5163 case IMAGE_BOOL_VALUE:
5164 if (!NILP (value) && !EQ (value, Qt))
5165 return 0;
5166 break;
5168 default:
5169 abort ();
5170 break;
5173 if (EQ (key, QCtype) && !EQ (type, value))
5174 return 0;
5177 /* Check that all mandatory fields are present. */
5178 for (i = 0; i < nkeywords; ++i)
5179 if (keywords[i].mandatory_p && keywords[i].count == 0)
5180 return 0;
5182 return NILP (plist);
5186 /* Return the value of KEY in image specification SPEC. Value is nil
5187 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5188 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5190 static Lisp_Object
5191 image_spec_value (spec, key, found)
5192 Lisp_Object spec, key;
5193 int *found;
5195 Lisp_Object tail;
5197 xassert (valid_image_p (spec));
5199 for (tail = XCDR (spec);
5200 CONSP (tail) && CONSP (XCDR (tail));
5201 tail = XCDR (XCDR (tail)))
5203 if (EQ (XCAR (tail), key))
5205 if (found)
5206 *found = 1;
5207 return XCAR (XCDR (tail));
5211 if (found)
5212 *found = 0;
5213 return Qnil;
5219 /***********************************************************************
5220 Image type independent image structures
5221 ***********************************************************************/
5223 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5224 static void free_image P_ ((struct frame *f, struct image *img));
5227 /* Allocate and return a new image structure for image specification
5228 SPEC. SPEC has a hash value of HASH. */
5230 static struct image *
5231 make_image (spec, hash)
5232 Lisp_Object spec;
5233 unsigned hash;
5235 struct image *img = (struct image *) xmalloc (sizeof *img);
5237 xassert (valid_image_p (spec));
5238 bzero (img, sizeof *img);
5239 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5240 xassert (img->type != NULL);
5241 img->spec = spec;
5242 img->data.lisp_val = Qnil;
5243 img->ascent = DEFAULT_IMAGE_ASCENT;
5244 img->hash = hash;
5245 return img;
5249 /* Free image IMG which was used on frame F, including its resources. */
5251 static void
5252 free_image (f, img)
5253 struct frame *f;
5254 struct image *img;
5256 if (img)
5258 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5260 /* Remove IMG from the hash table of its cache. */
5261 if (img->prev)
5262 img->prev->next = img->next;
5263 else
5264 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5266 if (img->next)
5267 img->next->prev = img->prev;
5269 c->images[img->id] = NULL;
5271 /* Free resources, then free IMG. */
5272 img->type->free (f, img);
5273 xfree (img);
5278 /* Prepare image IMG for display on frame F. Must be called before
5279 drawing an image. */
5281 void
5282 prepare_image_for_display (f, img)
5283 struct frame *f;
5284 struct image *img;
5286 EMACS_TIME t;
5288 /* We're about to display IMG, so set its timestamp to `now'. */
5289 EMACS_GET_TIME (t);
5290 img->timestamp = EMACS_SECS (t);
5292 /* If IMG doesn't have a pixmap yet, load it now, using the image
5293 type dependent loader function. */
5294 if (img->pixmap == 0 && !img->load_failed_p)
5295 img->load_failed_p = img->type->load (f, img) == 0;
5299 /* Value is the number of pixels for the ascent of image IMG when
5300 drawn in face FACE. */
5303 image_ascent (img, face)
5304 struct image *img;
5305 struct face *face;
5307 int height = img->height + img->margin;
5308 int ascent;
5310 if (img->ascent == CENTERED_IMAGE_ASCENT)
5312 if (face->font)
5313 ascent = height / 2 - (face->font->descent - face->font->ascent) / 2;
5314 else
5315 ascent = height / 2;
5317 else
5318 ascent = height * img->ascent / 100.0;
5320 return ascent;
5325 /***********************************************************************
5326 Helper functions for X image types
5327 ***********************************************************************/
5329 static void x_clear_image P_ ((struct frame *f, struct image *img));
5330 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5331 struct image *img,
5332 Lisp_Object color_name,
5333 unsigned long dflt));
5335 /* Free X resources of image IMG which is used on frame F. */
5337 static void
5338 x_clear_image (f, img)
5339 struct frame *f;
5340 struct image *img;
5342 if (img->pixmap)
5344 BLOCK_INPUT;
5345 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5346 img->pixmap = 0;
5347 UNBLOCK_INPUT;
5350 if (img->ncolors)
5352 BLOCK_INPUT;
5353 x_free_colors (f, img->colors, img->ncolors);
5354 UNBLOCK_INPUT;
5356 xfree (img->colors);
5357 img->colors = NULL;
5358 img->ncolors = 0;
5363 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5364 cannot be allocated, use DFLT. Add a newly allocated color to
5365 IMG->colors, so that it can be freed again. Value is the pixel
5366 color. */
5368 static unsigned long
5369 x_alloc_image_color (f, img, color_name, dflt)
5370 struct frame *f;
5371 struct image *img;
5372 Lisp_Object color_name;
5373 unsigned long dflt;
5375 XColor color;
5376 unsigned long result;
5378 xassert (STRINGP (color_name));
5380 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5382 /* This isn't called frequently so we get away with simply
5383 reallocating the color vector to the needed size, here. */
5384 ++img->ncolors;
5385 img->colors =
5386 (unsigned long *) xrealloc (img->colors,
5387 img->ncolors * sizeof *img->colors);
5388 img->colors[img->ncolors - 1] = color.pixel;
5389 result = color.pixel;
5391 else
5392 result = dflt;
5394 return result;
5399 /***********************************************************************
5400 Image Cache
5401 ***********************************************************************/
5403 static void cache_image P_ ((struct frame *f, struct image *img));
5406 /* Return a new, initialized image cache that is allocated from the
5407 heap. Call free_image_cache to free an image cache. */
5409 struct image_cache *
5410 make_image_cache ()
5412 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5413 int size;
5415 bzero (c, sizeof *c);
5416 c->size = 50;
5417 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5418 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5419 c->buckets = (struct image **) xmalloc (size);
5420 bzero (c->buckets, size);
5421 return c;
5425 /* Free image cache of frame F. Be aware that X frames share images
5426 caches. */
5428 void
5429 free_image_cache (f)
5430 struct frame *f;
5432 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5433 if (c)
5435 int i;
5437 /* Cache should not be referenced by any frame when freed. */
5438 xassert (c->refcount == 0);
5440 for (i = 0; i < c->used; ++i)
5441 free_image (f, c->images[i]);
5442 xfree (c->images);
5443 xfree (c->buckets);
5444 xfree (c);
5445 FRAME_X_IMAGE_CACHE (f) = NULL;
5450 /* Clear image cache of frame F. FORCE_P non-zero means free all
5451 images. FORCE_P zero means clear only images that haven't been
5452 displayed for some time. Should be called from time to time to
5453 reduce the number of loaded images. If image-eviction-seconds is
5454 non-nil, this frees images in the cache which weren't displayed for
5455 at least that many seconds. */
5457 void
5458 clear_image_cache (f, force_p)
5459 struct frame *f;
5460 int force_p;
5462 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5464 if (c && INTEGERP (Vimage_cache_eviction_delay))
5466 EMACS_TIME t;
5467 unsigned long old;
5468 int i, any_freed_p = 0;
5470 EMACS_GET_TIME (t);
5471 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5473 for (i = 0; i < c->used; ++i)
5475 struct image *img = c->images[i];
5476 if (img != NULL
5477 && (force_p
5478 || (img->timestamp > old)))
5480 free_image (f, img);
5481 any_freed_p = 1;
5485 /* We may be clearing the image cache because, for example,
5486 Emacs was iconified for a longer period of time. In that
5487 case, current matrices may still contain references to
5488 images freed above. So, clear these matrices. */
5489 if (any_freed_p)
5491 clear_current_matrices (f);
5492 ++windows_or_buffers_changed;
5498 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5499 0, 1, 0,
5500 "Clear the image cache of FRAME.\n\
5501 FRAME nil or omitted means use the selected frame.\n\
5502 FRAME t means clear the image caches of all frames.")
5503 (frame)
5504 Lisp_Object frame;
5506 if (EQ (frame, Qt))
5508 Lisp_Object tail;
5510 FOR_EACH_FRAME (tail, frame)
5511 if (FRAME_X_P (XFRAME (frame)))
5512 clear_image_cache (XFRAME (frame), 1);
5514 else
5515 clear_image_cache (check_x_frame (frame), 1);
5517 return Qnil;
5521 /* Return the id of image with Lisp specification SPEC on frame F.
5522 SPEC must be a valid Lisp image specification (see valid_image_p). */
5525 lookup_image (f, spec)
5526 struct frame *f;
5527 Lisp_Object spec;
5529 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5530 struct image *img;
5531 int i;
5532 unsigned hash;
5533 struct gcpro gcpro1;
5534 EMACS_TIME now;
5536 /* F must be a window-system frame, and SPEC must be a valid image
5537 specification. */
5538 xassert (FRAME_WINDOW_P (f));
5539 xassert (valid_image_p (spec));
5541 GCPRO1 (spec);
5543 /* Look up SPEC in the hash table of the image cache. */
5544 hash = sxhash (spec, 0);
5545 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5547 for (img = c->buckets[i]; img; img = img->next)
5548 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5549 break;
5551 /* If not found, create a new image and cache it. */
5552 if (img == NULL)
5554 img = make_image (spec, hash);
5555 cache_image (f, img);
5556 img->load_failed_p = img->type->load (f, img) == 0;
5557 xassert (!interrupt_input_blocked);
5559 /* If we can't load the image, and we don't have a width and
5560 height, use some arbitrary width and height so that we can
5561 draw a rectangle for it. */
5562 if (img->load_failed_p)
5564 Lisp_Object value;
5566 value = image_spec_value (spec, QCwidth, NULL);
5567 img->width = (INTEGERP (value)
5568 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5569 value = image_spec_value (spec, QCheight, NULL);
5570 img->height = (INTEGERP (value)
5571 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5573 else
5575 /* Handle image type independent image attributes
5576 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
5577 Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
5578 Lisp_Object file;
5580 ascent = image_spec_value (spec, QCascent, NULL);
5581 if (INTEGERP (ascent))
5582 img->ascent = XFASTINT (ascent);
5583 else if (EQ (ascent, Qcenter))
5584 img->ascent = CENTERED_IMAGE_ASCENT;
5586 margin = image_spec_value (spec, QCmargin, NULL);
5587 if (INTEGERP (margin) && XINT (margin) >= 0)
5588 img->margin = XFASTINT (margin);
5590 relief = image_spec_value (spec, QCrelief, NULL);
5591 if (INTEGERP (relief))
5593 img->relief = XINT (relief);
5594 img->margin += abs (img->relief);
5597 /* Should we apply a Laplace edge-detection algorithm? */
5598 algorithm = image_spec_value (spec, QCalgorithm, NULL);
5599 if (img->pixmap && EQ (algorithm, Qlaplace))
5600 x_laplace (f, img);
5602 /* Should we built a mask heuristically? */
5603 heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
5604 if (img->pixmap && !img->mask && !NILP (heuristic_mask))
5605 x_build_heuristic_mask (f, img, heuristic_mask);
5609 /* We're using IMG, so set its timestamp to `now'. */
5610 EMACS_GET_TIME (now);
5611 img->timestamp = EMACS_SECS (now);
5613 UNGCPRO;
5615 /* Value is the image id. */
5616 return img->id;
5620 /* Cache image IMG in the image cache of frame F. */
5622 static void
5623 cache_image (f, img)
5624 struct frame *f;
5625 struct image *img;
5627 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5628 int i;
5630 /* Find a free slot in c->images. */
5631 for (i = 0; i < c->used; ++i)
5632 if (c->images[i] == NULL)
5633 break;
5635 /* If no free slot found, maybe enlarge c->images. */
5636 if (i == c->used && c->used == c->size)
5638 c->size *= 2;
5639 c->images = (struct image **) xrealloc (c->images,
5640 c->size * sizeof *c->images);
5643 /* Add IMG to c->images, and assign IMG an id. */
5644 c->images[i] = img;
5645 img->id = i;
5646 if (i == c->used)
5647 ++c->used;
5649 /* Add IMG to the cache's hash table. */
5650 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5651 img->next = c->buckets[i];
5652 if (img->next)
5653 img->next->prev = img;
5654 img->prev = NULL;
5655 c->buckets[i] = img;
5659 /* Call FN on every image in the image cache of frame F. Used to mark
5660 Lisp Objects in the image cache. */
5662 void
5663 forall_images_in_image_cache (f, fn)
5664 struct frame *f;
5665 void (*fn) P_ ((struct image *img));
5667 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
5669 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5670 if (c)
5672 int i;
5673 for (i = 0; i < c->used; ++i)
5674 if (c->images[i])
5675 fn (c->images[i]);
5682 /***********************************************************************
5683 X support code
5684 ***********************************************************************/
5686 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
5687 XImage **, Pixmap *));
5688 static void x_destroy_x_image P_ ((XImage *));
5689 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
5692 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5693 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5694 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5695 via xmalloc. Print error messages via image_error if an error
5696 occurs. Value is non-zero if successful. */
5698 static int
5699 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
5700 struct frame *f;
5701 int width, height, depth;
5702 XImage **ximg;
5703 Pixmap *pixmap;
5705 Display *display = FRAME_X_DISPLAY (f);
5706 Screen *screen = FRAME_X_SCREEN (f);
5707 Window window = FRAME_X_WINDOW (f);
5709 xassert (interrupt_input_blocked);
5711 if (depth <= 0)
5712 depth = DefaultDepthOfScreen (screen);
5713 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
5714 depth, ZPixmap, 0, NULL, width, height,
5715 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
5716 if (*ximg == NULL)
5718 image_error ("Unable to allocate X image", Qnil, Qnil);
5719 return 0;
5722 /* Allocate image raster. */
5723 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
5725 /* Allocate a pixmap of the same size. */
5726 *pixmap = XCreatePixmap (display, window, width, height, depth);
5727 if (*pixmap == 0)
5729 x_destroy_x_image (*ximg);
5730 *ximg = NULL;
5731 image_error ("Unable to create X pixmap", Qnil, Qnil);
5732 return 0;
5735 return 1;
5739 /* Destroy XImage XIMG. Free XIMG->data. */
5741 static void
5742 x_destroy_x_image (ximg)
5743 XImage *ximg;
5745 xassert (interrupt_input_blocked);
5746 if (ximg)
5748 xfree (ximg->data);
5749 ximg->data = NULL;
5750 XDestroyImage (ximg);
5755 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5756 are width and height of both the image and pixmap. */
5758 static void
5759 x_put_x_image (f, ximg, pixmap, width, height)
5760 struct frame *f;
5761 XImage *ximg;
5762 Pixmap pixmap;
5764 GC gc;
5766 xassert (interrupt_input_blocked);
5767 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
5768 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
5769 XFreeGC (FRAME_X_DISPLAY (f), gc);
5774 /***********************************************************************
5775 File Handling
5776 ***********************************************************************/
5778 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
5779 static char *slurp_file P_ ((char *, int *));
5782 /* Find image file FILE. Look in data-directory, then
5783 x-bitmap-file-path. Value is the full name of the file found, or
5784 nil if not found. */
5786 static Lisp_Object
5787 x_find_image_file (file)
5788 Lisp_Object file;
5790 Lisp_Object file_found, search_path;
5791 struct gcpro gcpro1, gcpro2;
5792 int fd;
5794 file_found = Qnil;
5795 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
5796 GCPRO2 (file_found, search_path);
5798 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5799 fd = openp (search_path, file, "", &file_found, 0);
5801 if (fd < 0)
5802 file_found = Qnil;
5803 else
5804 close (fd);
5806 UNGCPRO;
5807 return file_found;
5811 /* Read FILE into memory. Value is a pointer to a buffer allocated
5812 with xmalloc holding FILE's contents. Value is null if an error
5813 occured. *SIZE is set to the size of the file. */
5815 static char *
5816 slurp_file (file, size)
5817 char *file;
5818 int *size;
5820 FILE *fp = NULL;
5821 char *buf = NULL;
5822 struct stat st;
5824 if (stat (file, &st) == 0
5825 && (fp = fopen (file, "r")) != NULL
5826 && (buf = (char *) xmalloc (st.st_size),
5827 fread (buf, 1, st.st_size, fp) == st.st_size))
5829 *size = st.st_size;
5830 fclose (fp);
5832 else
5834 if (fp)
5835 fclose (fp);
5836 if (buf)
5838 xfree (buf);
5839 buf = NULL;
5843 return buf;
5848 /***********************************************************************
5849 XBM images
5850 ***********************************************************************/
5852 static int xbm_scan P_ ((char **, char *, char *, int *));
5853 static int xbm_load P_ ((struct frame *f, struct image *img));
5854 static int xbm_load_image P_ ((struct frame *f, struct image *img,
5855 char *, char *));
5856 static int xbm_image_p P_ ((Lisp_Object object));
5857 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
5858 unsigned char **));
5859 static int xbm_file_p P_ ((Lisp_Object));
5862 /* Indices of image specification fields in xbm_format, below. */
5864 enum xbm_keyword_index
5866 XBM_TYPE,
5867 XBM_FILE,
5868 XBM_WIDTH,
5869 XBM_HEIGHT,
5870 XBM_DATA,
5871 XBM_FOREGROUND,
5872 XBM_BACKGROUND,
5873 XBM_ASCENT,
5874 XBM_MARGIN,
5875 XBM_RELIEF,
5876 XBM_ALGORITHM,
5877 XBM_HEURISTIC_MASK,
5878 XBM_LAST
5881 /* Vector of image_keyword structures describing the format
5882 of valid XBM image specifications. */
5884 static struct image_keyword xbm_format[XBM_LAST] =
5886 {":type", IMAGE_SYMBOL_VALUE, 1},
5887 {":file", IMAGE_STRING_VALUE, 0},
5888 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5889 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5890 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5891 {":foreground", IMAGE_STRING_VALUE, 0},
5892 {":background", IMAGE_STRING_VALUE, 0},
5893 {":ascent", IMAGE_ASCENT_VALUE, 0},
5894 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5895 {":relief", IMAGE_INTEGER_VALUE, 0},
5896 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5897 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5900 /* Structure describing the image type XBM. */
5902 static struct image_type xbm_type =
5904 &Qxbm,
5905 xbm_image_p,
5906 xbm_load,
5907 x_clear_image,
5908 NULL
5911 /* Tokens returned from xbm_scan. */
5913 enum xbm_token
5915 XBM_TK_IDENT = 256,
5916 XBM_TK_NUMBER
5920 /* Return non-zero if OBJECT is a valid XBM-type image specification.
5921 A valid specification is a list starting with the symbol `image'
5922 The rest of the list is a property list which must contain an
5923 entry `:type xbm..
5925 If the specification specifies a file to load, it must contain
5926 an entry `:file FILENAME' where FILENAME is a string.
5928 If the specification is for a bitmap loaded from memory it must
5929 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
5930 WIDTH and HEIGHT are integers > 0. DATA may be:
5932 1. a string large enough to hold the bitmap data, i.e. it must
5933 have a size >= (WIDTH + 7) / 8 * HEIGHT
5935 2. a bool-vector of size >= WIDTH * HEIGHT
5937 3. a vector of strings or bool-vectors, one for each line of the
5938 bitmap.
5940 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
5941 may not be specified in this case because they are defined in the
5942 XBM file.
5944 Both the file and data forms may contain the additional entries
5945 `:background COLOR' and `:foreground COLOR'. If not present,
5946 foreground and background of the frame on which the image is
5947 displayed is used. */
5949 static int
5950 xbm_image_p (object)
5951 Lisp_Object object;
5953 struct image_keyword kw[XBM_LAST];
5955 bcopy (xbm_format, kw, sizeof kw);
5956 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
5957 return 0;
5959 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
5961 if (kw[XBM_FILE].count)
5963 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
5964 return 0;
5966 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
5968 /* In-memory XBM file. */
5969 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
5970 return 0;
5972 else
5974 Lisp_Object data;
5975 int width, height;
5977 /* Entries for `:width', `:height' and `:data' must be present. */
5978 if (!kw[XBM_WIDTH].count
5979 || !kw[XBM_HEIGHT].count
5980 || !kw[XBM_DATA].count)
5981 return 0;
5983 data = kw[XBM_DATA].value;
5984 width = XFASTINT (kw[XBM_WIDTH].value);
5985 height = XFASTINT (kw[XBM_HEIGHT].value);
5987 /* Check type of data, and width and height against contents of
5988 data. */
5989 if (VECTORP (data))
5991 int i;
5993 /* Number of elements of the vector must be >= height. */
5994 if (XVECTOR (data)->size < height)
5995 return 0;
5997 /* Each string or bool-vector in data must be large enough
5998 for one line of the image. */
5999 for (i = 0; i < height; ++i)
6001 Lisp_Object elt = XVECTOR (data)->contents[i];
6003 if (STRINGP (elt))
6005 if (XSTRING (elt)->size
6006 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6007 return 0;
6009 else if (BOOL_VECTOR_P (elt))
6011 if (XBOOL_VECTOR (elt)->size < width)
6012 return 0;
6014 else
6015 return 0;
6018 else if (STRINGP (data))
6020 if (XSTRING (data)->size
6021 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6022 return 0;
6024 else if (BOOL_VECTOR_P (data))
6026 if (XBOOL_VECTOR (data)->size < width * height)
6027 return 0;
6029 else
6030 return 0;
6033 return 1;
6037 /* Scan a bitmap file. FP is the stream to read from. Value is
6038 either an enumerator from enum xbm_token, or a character for a
6039 single-character token, or 0 at end of file. If scanning an
6040 identifier, store the lexeme of the identifier in SVAL. If
6041 scanning a number, store its value in *IVAL. */
6043 static int
6044 xbm_scan (s, end, sval, ival)
6045 char **s, *end;
6046 char *sval;
6047 int *ival;
6049 int c;
6051 /* Skip white space. */
6052 while (*s < end && (c = *(*s)++, isspace (c)))
6055 if (*s >= end)
6056 c = 0;
6057 else if (isdigit (c))
6059 int value = 0, digit;
6061 if (c == '0' && *s < end)
6063 c = *(*s)++;
6064 if (c == 'x' || c == 'X')
6066 while (*s < end)
6068 c = *(*s)++;
6069 if (isdigit (c))
6070 digit = c - '0';
6071 else if (c >= 'a' && c <= 'f')
6072 digit = c - 'a' + 10;
6073 else if (c >= 'A' && c <= 'F')
6074 digit = c - 'A' + 10;
6075 else
6076 break;
6077 value = 16 * value + digit;
6080 else if (isdigit (c))
6082 value = c - '0';
6083 while (*s < end
6084 && (c = *(*s)++, isdigit (c)))
6085 value = 8 * value + c - '0';
6088 else
6090 value = c - '0';
6091 while (*s < end
6092 && (c = *(*s)++, isdigit (c)))
6093 value = 10 * value + c - '0';
6096 if (*s < end)
6097 *s = *s - 1;
6098 *ival = value;
6099 c = XBM_TK_NUMBER;
6101 else if (isalpha (c) || c == '_')
6103 *sval++ = c;
6104 while (*s < end
6105 && (c = *(*s)++, (isalnum (c) || c == '_')))
6106 *sval++ = c;
6107 *sval = 0;
6108 if (*s < end)
6109 *s = *s - 1;
6110 c = XBM_TK_IDENT;
6113 return c;
6117 /* Replacement for XReadBitmapFileData which isn't available under old
6118 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6119 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6120 the image. Return in *DATA the bitmap data allocated with xmalloc.
6121 Value is non-zero if successful. DATA null means just test if
6122 CONTENTS looks like an im-memory XBM file. */
6124 static int
6125 xbm_read_bitmap_data (contents, end, width, height, data)
6126 char *contents, *end;
6127 int *width, *height;
6128 unsigned char **data;
6130 char *s = contents;
6131 char buffer[BUFSIZ];
6132 int padding_p = 0;
6133 int v10 = 0;
6134 int bytes_per_line, i, nbytes;
6135 unsigned char *p;
6136 int value;
6137 int LA1;
6139 #define match() \
6140 LA1 = xbm_scan (&s, end, buffer, &value)
6142 #define expect(TOKEN) \
6143 if (LA1 != (TOKEN)) \
6144 goto failure; \
6145 else \
6146 match ()
6148 #define expect_ident(IDENT) \
6149 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6150 match (); \
6151 else \
6152 goto failure
6154 *width = *height = -1;
6155 if (data)
6156 *data = NULL;
6157 LA1 = xbm_scan (&s, end, buffer, &value);
6159 /* Parse defines for width, height and hot-spots. */
6160 while (LA1 == '#')
6162 match ();
6163 expect_ident ("define");
6164 expect (XBM_TK_IDENT);
6166 if (LA1 == XBM_TK_NUMBER);
6168 char *p = strrchr (buffer, '_');
6169 p = p ? p + 1 : buffer;
6170 if (strcmp (p, "width") == 0)
6171 *width = value;
6172 else if (strcmp (p, "height") == 0)
6173 *height = value;
6175 expect (XBM_TK_NUMBER);
6178 if (*width < 0 || *height < 0)
6179 goto failure;
6180 else if (data == NULL)
6181 goto success;
6183 /* Parse bits. Must start with `static'. */
6184 expect_ident ("static");
6185 if (LA1 == XBM_TK_IDENT)
6187 if (strcmp (buffer, "unsigned") == 0)
6189 match ();
6190 expect_ident ("char");
6192 else if (strcmp (buffer, "short") == 0)
6194 match ();
6195 v10 = 1;
6196 if (*width % 16 && *width % 16 < 9)
6197 padding_p = 1;
6199 else if (strcmp (buffer, "char") == 0)
6200 match ();
6201 else
6202 goto failure;
6204 else
6205 goto failure;
6207 expect (XBM_TK_IDENT);
6208 expect ('[');
6209 expect (']');
6210 expect ('=');
6211 expect ('{');
6213 bytes_per_line = (*width + 7) / 8 + padding_p;
6214 nbytes = bytes_per_line * *height;
6215 p = *data = (char *) xmalloc (nbytes);
6217 if (v10)
6219 for (i = 0; i < nbytes; i += 2)
6221 int val = value;
6222 expect (XBM_TK_NUMBER);
6224 *p++ = val;
6225 if (!padding_p || ((i + 2) % bytes_per_line))
6226 *p++ = value >> 8;
6228 if (LA1 == ',' || LA1 == '}')
6229 match ();
6230 else
6231 goto failure;
6234 else
6236 for (i = 0; i < nbytes; ++i)
6238 int val = value;
6239 expect (XBM_TK_NUMBER);
6241 *p++ = val;
6243 if (LA1 == ',' || LA1 == '}')
6244 match ();
6245 else
6246 goto failure;
6250 success:
6251 return 1;
6253 failure:
6255 if (data && *data)
6257 xfree (*data);
6258 *data = NULL;
6260 return 0;
6262 #undef match
6263 #undef expect
6264 #undef expect_ident
6268 /* Load XBM image IMG which will be displayed on frame F from buffer
6269 CONTENTS. END is the end of the buffer. Value is non-zero if
6270 successful. */
6272 static int
6273 xbm_load_image (f, img, contents, end)
6274 struct frame *f;
6275 struct image *img;
6276 char *contents, *end;
6278 int rc;
6279 unsigned char *data;
6280 int success_p = 0;
6282 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
6283 if (rc)
6285 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6286 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6287 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6288 Lisp_Object value;
6290 xassert (img->width > 0 && img->height > 0);
6292 /* Get foreground and background colors, maybe allocate colors. */
6293 value = image_spec_value (img->spec, QCforeground, NULL);
6294 if (!NILP (value))
6295 foreground = x_alloc_image_color (f, img, value, foreground);
6297 value = image_spec_value (img->spec, QCbackground, NULL);
6298 if (!NILP (value))
6299 background = x_alloc_image_color (f, img, value, background);
6301 BLOCK_INPUT;
6302 img->pixmap
6303 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6304 FRAME_X_WINDOW (f),
6305 data,
6306 img->width, img->height,
6307 foreground, background,
6308 depth);
6309 xfree (data);
6311 if (img->pixmap == 0)
6313 x_clear_image (f, img);
6314 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6316 else
6317 success_p = 1;
6319 UNBLOCK_INPUT;
6321 else
6322 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6324 return success_p;
6328 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6330 static int
6331 xbm_file_p (data)
6332 Lisp_Object data;
6334 int w, h;
6335 return (STRINGP (data)
6336 && xbm_read_bitmap_data (XSTRING (data)->data,
6337 (XSTRING (data)->data
6338 + STRING_BYTES (XSTRING (data))),
6339 &w, &h, NULL));
6343 /* Fill image IMG which is used on frame F with pixmap data. Value is
6344 non-zero if successful. */
6346 static int
6347 xbm_load (f, img)
6348 struct frame *f;
6349 struct image *img;
6351 int success_p = 0;
6352 Lisp_Object file_name;
6354 xassert (xbm_image_p (img->spec));
6356 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6357 file_name = image_spec_value (img->spec, QCfile, NULL);
6358 if (STRINGP (file_name))
6360 Lisp_Object file;
6361 char *contents;
6362 int size;
6363 struct gcpro gcpro1;
6365 file = x_find_image_file (file_name);
6366 GCPRO1 (file);
6367 if (!STRINGP (file))
6369 image_error ("Cannot find image file `%s'", file_name, Qnil);
6370 UNGCPRO;
6371 return 0;
6374 contents = slurp_file (XSTRING (file)->data, &size);
6375 if (contents == NULL)
6377 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6378 UNGCPRO;
6379 return 0;
6382 success_p = xbm_load_image (f, img, contents, contents + size);
6383 UNGCPRO;
6385 else
6387 struct image_keyword fmt[XBM_LAST];
6388 Lisp_Object data;
6389 unsigned char *bitmap_data;
6390 int depth;
6391 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6392 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6393 char *bits;
6394 int parsed_p, height, width;
6395 int in_memory_file_p = 0;
6397 /* See if data looks like an in-memory XBM file. */
6398 data = image_spec_value (img->spec, QCdata, NULL);
6399 in_memory_file_p = xbm_file_p (data);
6401 /* Parse the image specification. */
6402 bcopy (xbm_format, fmt, sizeof fmt);
6403 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6404 xassert (parsed_p);
6406 /* Get specified width, and height. */
6407 if (!in_memory_file_p)
6409 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6410 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6411 xassert (img->width > 0 && img->height > 0);
6414 BLOCK_INPUT;
6416 /* Get foreground and background colors, maybe allocate colors. */
6417 if (fmt[XBM_FOREGROUND].count)
6418 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6419 foreground);
6420 if (fmt[XBM_BACKGROUND].count)
6421 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6422 background);
6424 if (in_memory_file_p)
6425 success_p = xbm_load_image (f, img, XSTRING (data)->data,
6426 (XSTRING (data)->data
6427 + STRING_BYTES (XSTRING (data))));
6428 else
6430 if (VECTORP (data))
6432 int i;
6433 char *p;
6434 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6436 p = bits = (char *) alloca (nbytes * img->height);
6437 for (i = 0; i < img->height; ++i, p += nbytes)
6439 Lisp_Object line = XVECTOR (data)->contents[i];
6440 if (STRINGP (line))
6441 bcopy (XSTRING (line)->data, p, nbytes);
6442 else
6443 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6446 else if (STRINGP (data))
6447 bits = XSTRING (data)->data;
6448 else
6449 bits = XBOOL_VECTOR (data)->data;
6451 /* Create the pixmap. */
6452 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6453 img->pixmap
6454 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6455 FRAME_X_WINDOW (f),
6456 bits,
6457 img->width, img->height,
6458 foreground, background,
6459 depth);
6460 if (img->pixmap)
6461 success_p = 1;
6462 else
6464 image_error ("Unable to create pixmap for XBM image `%s'",
6465 img->spec, Qnil);
6466 x_clear_image (f, img);
6470 UNBLOCK_INPUT;
6473 return success_p;
6478 /***********************************************************************
6479 XPM images
6480 ***********************************************************************/
6482 #if HAVE_XPM
6484 static int xpm_image_p P_ ((Lisp_Object object));
6485 static int xpm_load P_ ((struct frame *f, struct image *img));
6486 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6488 #include "X11/xpm.h"
6490 /* The symbol `xpm' identifying XPM-format images. */
6492 Lisp_Object Qxpm;
6494 /* Indices of image specification fields in xpm_format, below. */
6496 enum xpm_keyword_index
6498 XPM_TYPE,
6499 XPM_FILE,
6500 XPM_DATA,
6501 XPM_ASCENT,
6502 XPM_MARGIN,
6503 XPM_RELIEF,
6504 XPM_ALGORITHM,
6505 XPM_HEURISTIC_MASK,
6506 XPM_COLOR_SYMBOLS,
6507 XPM_LAST
6510 /* Vector of image_keyword structures describing the format
6511 of valid XPM image specifications. */
6513 static struct image_keyword xpm_format[XPM_LAST] =
6515 {":type", IMAGE_SYMBOL_VALUE, 1},
6516 {":file", IMAGE_STRING_VALUE, 0},
6517 {":data", IMAGE_STRING_VALUE, 0},
6518 {":ascent", IMAGE_ASCENT_VALUE, 0},
6519 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6520 {":relief", IMAGE_INTEGER_VALUE, 0},
6521 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6522 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6523 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6526 /* Structure describing the image type XBM. */
6528 static struct image_type xpm_type =
6530 &Qxpm,
6531 xpm_image_p,
6532 xpm_load,
6533 x_clear_image,
6534 NULL
6538 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6539 for XPM images. Such a list must consist of conses whose car and
6540 cdr are strings. */
6542 static int
6543 xpm_valid_color_symbols_p (color_symbols)
6544 Lisp_Object color_symbols;
6546 while (CONSP (color_symbols))
6548 Lisp_Object sym = XCAR (color_symbols);
6549 if (!CONSP (sym)
6550 || !STRINGP (XCAR (sym))
6551 || !STRINGP (XCDR (sym)))
6552 break;
6553 color_symbols = XCDR (color_symbols);
6556 return NILP (color_symbols);
6560 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6562 static int
6563 xpm_image_p (object)
6564 Lisp_Object object;
6566 struct image_keyword fmt[XPM_LAST];
6567 bcopy (xpm_format, fmt, sizeof fmt);
6568 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
6569 /* Either `:file' or `:data' must be present. */
6570 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
6571 /* Either no `:color-symbols' or it's a list of conses
6572 whose car and cdr are strings. */
6573 && (fmt[XPM_COLOR_SYMBOLS].count == 0
6574 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
6578 /* Load image IMG which will be displayed on frame F. Value is
6579 non-zero if successful. */
6581 static int
6582 xpm_load (f, img)
6583 struct frame *f;
6584 struct image *img;
6586 int rc, i;
6587 XpmAttributes attrs;
6588 Lisp_Object specified_file, color_symbols;
6590 /* Configure the XPM lib. Use the visual of frame F. Allocate
6591 close colors. Return colors allocated. */
6592 bzero (&attrs, sizeof attrs);
6593 attrs.visual = FRAME_X_VISUAL (f);
6594 attrs.colormap = FRAME_X_COLORMAP (f);
6595 attrs.valuemask |= XpmVisual;
6596 attrs.valuemask |= XpmColormap;
6597 attrs.valuemask |= XpmReturnAllocPixels;
6598 #ifdef XpmAllocCloseColors
6599 attrs.alloc_close_colors = 1;
6600 attrs.valuemask |= XpmAllocCloseColors;
6601 #else
6602 attrs.closeness = 600;
6603 attrs.valuemask |= XpmCloseness;
6604 #endif
6606 /* If image specification contains symbolic color definitions, add
6607 these to `attrs'. */
6608 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
6609 if (CONSP (color_symbols))
6611 Lisp_Object tail;
6612 XpmColorSymbol *xpm_syms;
6613 int i, size;
6615 attrs.valuemask |= XpmColorSymbols;
6617 /* Count number of symbols. */
6618 attrs.numsymbols = 0;
6619 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
6620 ++attrs.numsymbols;
6622 /* Allocate an XpmColorSymbol array. */
6623 size = attrs.numsymbols * sizeof *xpm_syms;
6624 xpm_syms = (XpmColorSymbol *) alloca (size);
6625 bzero (xpm_syms, size);
6626 attrs.colorsymbols = xpm_syms;
6628 /* Fill the color symbol array. */
6629 for (tail = color_symbols, i = 0;
6630 CONSP (tail);
6631 ++i, tail = XCDR (tail))
6633 Lisp_Object name = XCAR (XCAR (tail));
6634 Lisp_Object color = XCDR (XCAR (tail));
6635 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
6636 strcpy (xpm_syms[i].name, XSTRING (name)->data);
6637 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
6638 strcpy (xpm_syms[i].value, XSTRING (color)->data);
6642 /* Create a pixmap for the image, either from a file, or from a
6643 string buffer containing data in the same format as an XPM file. */
6644 BLOCK_INPUT;
6645 specified_file = image_spec_value (img->spec, QCfile, NULL);
6646 if (STRINGP (specified_file))
6648 Lisp_Object file = x_find_image_file (specified_file);
6649 if (!STRINGP (file))
6651 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6652 UNBLOCK_INPUT;
6653 return 0;
6656 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6657 XSTRING (file)->data, &img->pixmap, &img->mask,
6658 &attrs);
6660 else
6662 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
6663 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6664 XSTRING (buffer)->data,
6665 &img->pixmap, &img->mask,
6666 &attrs);
6668 UNBLOCK_INPUT;
6670 if (rc == XpmSuccess)
6672 /* Remember allocated colors. */
6673 img->ncolors = attrs.nalloc_pixels;
6674 img->colors = (unsigned long *) xmalloc (img->ncolors
6675 * sizeof *img->colors);
6676 for (i = 0; i < attrs.nalloc_pixels; ++i)
6678 img->colors[i] = attrs.alloc_pixels[i];
6679 #ifdef DEBUG_X_COLORS
6680 register_color (img->colors[i]);
6681 #endif
6684 img->width = attrs.width;
6685 img->height = attrs.height;
6686 xassert (img->width > 0 && img->height > 0);
6688 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6689 BLOCK_INPUT;
6690 XpmFreeAttributes (&attrs);
6691 UNBLOCK_INPUT;
6693 else
6695 switch (rc)
6697 case XpmOpenFailed:
6698 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
6699 break;
6701 case XpmFileInvalid:
6702 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
6703 break;
6705 case XpmNoMemory:
6706 image_error ("Out of memory (%s)", img->spec, Qnil);
6707 break;
6709 case XpmColorFailed:
6710 image_error ("Color allocation error (%s)", img->spec, Qnil);
6711 break;
6713 default:
6714 image_error ("Unknown error (%s)", img->spec, Qnil);
6715 break;
6719 return rc == XpmSuccess;
6722 #endif /* HAVE_XPM != 0 */
6725 /***********************************************************************
6726 Color table
6727 ***********************************************************************/
6729 /* An entry in the color table mapping an RGB color to a pixel color. */
6731 struct ct_color
6733 int r, g, b;
6734 unsigned long pixel;
6736 /* Next in color table collision list. */
6737 struct ct_color *next;
6740 /* The bucket vector size to use. Must be prime. */
6742 #define CT_SIZE 101
6744 /* Value is a hash of the RGB color given by R, G, and B. */
6746 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6748 /* The color hash table. */
6750 struct ct_color **ct_table;
6752 /* Number of entries in the color table. */
6754 int ct_colors_allocated;
6756 /* Function prototypes. */
6758 static void init_color_table P_ ((void));
6759 static void free_color_table P_ ((void));
6760 static unsigned long *colors_in_color_table P_ ((int *n));
6761 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
6762 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
6765 /* Initialize the color table. */
6767 static void
6768 init_color_table ()
6770 int size = CT_SIZE * sizeof (*ct_table);
6771 ct_table = (struct ct_color **) xmalloc (size);
6772 bzero (ct_table, size);
6773 ct_colors_allocated = 0;
6777 /* Free memory associated with the color table. */
6779 static void
6780 free_color_table ()
6782 int i;
6783 struct ct_color *p, *next;
6785 for (i = 0; i < CT_SIZE; ++i)
6786 for (p = ct_table[i]; p; p = next)
6788 next = p->next;
6789 xfree (p);
6792 xfree (ct_table);
6793 ct_table = NULL;
6797 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6798 entry for that color already is in the color table, return the
6799 pixel color of that entry. Otherwise, allocate a new color for R,
6800 G, B, and make an entry in the color table. */
6802 static unsigned long
6803 lookup_rgb_color (f, r, g, b)
6804 struct frame *f;
6805 int r, g, b;
6807 unsigned hash = CT_HASH_RGB (r, g, b);
6808 int i = hash % CT_SIZE;
6809 struct ct_color *p;
6811 for (p = ct_table[i]; p; p = p->next)
6812 if (p->r == r && p->g == g && p->b == b)
6813 break;
6815 if (p == NULL)
6817 XColor color;
6818 Colormap cmap;
6819 int rc;
6821 color.red = r;
6822 color.green = g;
6823 color.blue = b;
6825 BLOCK_INPUT;
6826 cmap = FRAME_X_COLORMAP (f);
6827 rc = x_alloc_nearest_color (f, cmap, &color);
6828 UNBLOCK_INPUT;
6830 if (rc)
6832 ++ct_colors_allocated;
6834 p = (struct ct_color *) xmalloc (sizeof *p);
6835 p->r = r;
6836 p->g = g;
6837 p->b = b;
6838 p->pixel = color.pixel;
6839 p->next = ct_table[i];
6840 ct_table[i] = p;
6842 else
6843 return FRAME_FOREGROUND_PIXEL (f);
6846 return p->pixel;
6850 /* Look up pixel color PIXEL which is used on frame F in the color
6851 table. If not already present, allocate it. Value is PIXEL. */
6853 static unsigned long
6854 lookup_pixel_color (f, pixel)
6855 struct frame *f;
6856 unsigned long pixel;
6858 int i = pixel % CT_SIZE;
6859 struct ct_color *p;
6861 for (p = ct_table[i]; p; p = p->next)
6862 if (p->pixel == pixel)
6863 break;
6865 if (p == NULL)
6867 XColor color;
6868 Colormap cmap;
6869 int rc;
6871 BLOCK_INPUT;
6873 cmap = FRAME_X_COLORMAP (f);
6874 color.pixel = pixel;
6875 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
6876 rc = x_alloc_nearest_color (f, cmap, &color);
6877 UNBLOCK_INPUT;
6879 if (rc)
6881 ++ct_colors_allocated;
6883 p = (struct ct_color *) xmalloc (sizeof *p);
6884 p->r = color.red;
6885 p->g = color.green;
6886 p->b = color.blue;
6887 p->pixel = pixel;
6888 p->next = ct_table[i];
6889 ct_table[i] = p;
6891 else
6892 return FRAME_FOREGROUND_PIXEL (f);
6895 return p->pixel;
6899 /* Value is a vector of all pixel colors contained in the color table,
6900 allocated via xmalloc. Set *N to the number of colors. */
6902 static unsigned long *
6903 colors_in_color_table (n)
6904 int *n;
6906 int i, j;
6907 struct ct_color *p;
6908 unsigned long *colors;
6910 if (ct_colors_allocated == 0)
6912 *n = 0;
6913 colors = NULL;
6915 else
6917 colors = (unsigned long *) xmalloc (ct_colors_allocated
6918 * sizeof *colors);
6919 *n = ct_colors_allocated;
6921 for (i = j = 0; i < CT_SIZE; ++i)
6922 for (p = ct_table[i]; p; p = p->next)
6923 colors[j++] = p->pixel;
6926 return colors;
6931 /***********************************************************************
6932 Algorithms
6933 ***********************************************************************/
6935 static void x_laplace_write_row P_ ((struct frame *, long *,
6936 int, XImage *, int));
6937 static void x_laplace_read_row P_ ((struct frame *, Colormap,
6938 XColor *, int, XImage *, int));
6941 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
6942 frame we operate on, CMAP is the color-map in effect, and WIDTH is
6943 the width of one row in the image. */
6945 static void
6946 x_laplace_read_row (f, cmap, colors, width, ximg, y)
6947 struct frame *f;
6948 Colormap cmap;
6949 XColor *colors;
6950 int width;
6951 XImage *ximg;
6952 int y;
6954 int x;
6956 for (x = 0; x < width; ++x)
6957 colors[x].pixel = XGetPixel (ximg, x, y);
6959 XQueryColors (FRAME_X_DISPLAY (f), cmap, colors, width);
6963 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
6964 containing the pixel colors to write. F is the frame we are
6965 working on. */
6967 static void
6968 x_laplace_write_row (f, pixels, width, ximg, y)
6969 struct frame *f;
6970 long *pixels;
6971 int width;
6972 XImage *ximg;
6973 int y;
6975 int x;
6977 for (x = 0; x < width; ++x)
6978 XPutPixel (ximg, x, y, pixels[x]);
6982 /* Transform image IMG which is used on frame F with a Laplace
6983 edge-detection algorithm. The result is an image that can be used
6984 to draw disabled buttons, for example. */
6986 static void
6987 x_laplace (f, img)
6988 struct frame *f;
6989 struct image *img;
6991 Colormap cmap = FRAME_X_COLORMAP (f);
6992 XImage *ximg, *oimg;
6993 XColor *in[3];
6994 long *out;
6995 Pixmap pixmap;
6996 int x, y, i;
6997 long pixel;
6998 int in_y, out_y, rc;
6999 int mv2 = 45000;
7001 BLOCK_INPUT;
7003 /* Get the X image IMG->pixmap. */
7004 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7005 0, 0, img->width, img->height, ~0, ZPixmap);
7007 /* Allocate 3 input rows, and one output row of colors. */
7008 for (i = 0; i < 3; ++i)
7009 in[i] = (XColor *) alloca (img->width * sizeof (XColor));
7010 out = (long *) alloca (img->width * sizeof (long));
7012 /* Create an X image for output. */
7013 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7014 &oimg, &pixmap);
7016 /* Fill first two rows. */
7017 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
7018 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
7019 in_y = 2;
7021 /* Write first row, all zeros. */
7022 init_color_table ();
7023 pixel = lookup_rgb_color (f, 0, 0, 0);
7024 for (x = 0; x < img->width; ++x)
7025 out[x] = pixel;
7026 x_laplace_write_row (f, out, img->width, oimg, 0);
7027 out_y = 1;
7029 for (y = 2; y < img->height; ++y)
7031 int rowa = y % 3;
7032 int rowb = (y + 2) % 3;
7034 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
7036 for (x = 0; x < img->width - 2; ++x)
7038 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
7039 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
7040 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
7042 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
7043 b & 0xffff);
7046 x_laplace_write_row (f, out, img->width, oimg, out_y++);
7049 /* Write last line, all zeros. */
7050 for (x = 0; x < img->width; ++x)
7051 out[x] = pixel;
7052 x_laplace_write_row (f, out, img->width, oimg, out_y);
7054 /* Free the input image, and free resources of IMG. */
7055 XDestroyImage (ximg);
7056 x_clear_image (f, img);
7058 /* Put the output image into pixmap, and destroy it. */
7059 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7060 x_destroy_x_image (oimg);
7062 /* Remember new pixmap and colors in IMG. */
7063 img->pixmap = pixmap;
7064 img->colors = colors_in_color_table (&img->ncolors);
7065 free_color_table ();
7067 UNBLOCK_INPUT;
7071 /* Build a mask for image IMG which is used on frame F. FILE is the
7072 name of an image file, for error messages. HOW determines how to
7073 determine the background color of IMG. If it is a list '(R G B)',
7074 with R, G, and B being integers >= 0, take that as the color of the
7075 background. Otherwise, determine the background color of IMG
7076 heuristically. Value is non-zero if successful. */
7078 static int
7079 x_build_heuristic_mask (f, img, how)
7080 struct frame *f;
7081 struct image *img;
7082 Lisp_Object how;
7084 Display *dpy = FRAME_X_DISPLAY (f);
7085 XImage *ximg, *mask_img;
7086 int x, y, rc, look_at_corners_p;
7087 unsigned long bg;
7089 BLOCK_INPUT;
7091 /* Create an image and pixmap serving as mask. */
7092 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7093 &mask_img, &img->mask);
7094 if (!rc)
7096 UNBLOCK_INPUT;
7097 return 0;
7100 /* Get the X image of IMG->pixmap. */
7101 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7102 ~0, ZPixmap);
7104 /* Determine the background color of ximg. If HOW is `(R G B)'
7105 take that as color. Otherwise, try to determine the color
7106 heuristically. */
7107 look_at_corners_p = 1;
7109 if (CONSP (how))
7111 int rgb[3], i = 0;
7113 while (i < 3
7114 && CONSP (how)
7115 && NATNUMP (XCAR (how)))
7117 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
7118 how = XCDR (how);
7121 if (i == 3 && NILP (how))
7123 char color_name[30];
7124 XColor exact, color;
7125 Colormap cmap;
7127 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
7129 cmap = FRAME_X_COLORMAP (f);
7130 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
7132 bg = color.pixel;
7133 look_at_corners_p = 0;
7138 if (look_at_corners_p)
7140 unsigned long corners[4];
7141 int i, best_count;
7143 /* Get the colors at the corners of ximg. */
7144 corners[0] = XGetPixel (ximg, 0, 0);
7145 corners[1] = XGetPixel (ximg, img->width - 1, 0);
7146 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
7147 corners[3] = XGetPixel (ximg, 0, img->height - 1);
7149 /* Choose the most frequently found color as background. */
7150 for (i = best_count = 0; i < 4; ++i)
7152 int j, n;
7154 for (j = n = 0; j < 4; ++j)
7155 if (corners[i] == corners[j])
7156 ++n;
7158 if (n > best_count)
7159 bg = corners[i], best_count = n;
7163 /* Set all bits in mask_img to 1 whose color in ximg is different
7164 from the background color bg. */
7165 for (y = 0; y < img->height; ++y)
7166 for (x = 0; x < img->width; ++x)
7167 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7169 /* Put mask_img into img->mask. */
7170 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7171 x_destroy_x_image (mask_img);
7172 XDestroyImage (ximg);
7174 UNBLOCK_INPUT;
7175 return 1;
7180 /***********************************************************************
7181 PBM (mono, gray, color)
7182 ***********************************************************************/
7184 static int pbm_image_p P_ ((Lisp_Object object));
7185 static int pbm_load P_ ((struct frame *f, struct image *img));
7186 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7188 /* The symbol `pbm' identifying images of this type. */
7190 Lisp_Object Qpbm;
7192 /* Indices of image specification fields in gs_format, below. */
7194 enum pbm_keyword_index
7196 PBM_TYPE,
7197 PBM_FILE,
7198 PBM_DATA,
7199 PBM_ASCENT,
7200 PBM_MARGIN,
7201 PBM_RELIEF,
7202 PBM_ALGORITHM,
7203 PBM_HEURISTIC_MASK,
7204 PBM_LAST
7207 /* Vector of image_keyword structures describing the format
7208 of valid user-defined image specifications. */
7210 static struct image_keyword pbm_format[PBM_LAST] =
7212 {":type", IMAGE_SYMBOL_VALUE, 1},
7213 {":file", IMAGE_STRING_VALUE, 0},
7214 {":data", IMAGE_STRING_VALUE, 0},
7215 {":ascent", IMAGE_ASCENT_VALUE, 0},
7216 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7217 {":relief", IMAGE_INTEGER_VALUE, 0},
7218 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7219 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7222 /* Structure describing the image type `pbm'. */
7224 static struct image_type pbm_type =
7226 &Qpbm,
7227 pbm_image_p,
7228 pbm_load,
7229 x_clear_image,
7230 NULL
7234 /* Return non-zero if OBJECT is a valid PBM image specification. */
7236 static int
7237 pbm_image_p (object)
7238 Lisp_Object object;
7240 struct image_keyword fmt[PBM_LAST];
7242 bcopy (pbm_format, fmt, sizeof fmt);
7244 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
7245 return 0;
7247 /* Must specify either :data or :file. */
7248 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7252 /* Scan a decimal number from *S and return it. Advance *S while
7253 reading the number. END is the end of the string. Value is -1 at
7254 end of input. */
7256 static int
7257 pbm_scan_number (s, end)
7258 unsigned char **s, *end;
7260 int c, val = -1;
7262 while (*s < end)
7264 /* Skip white-space. */
7265 while (*s < end && (c = *(*s)++, isspace (c)))
7268 if (c == '#')
7270 /* Skip comment to end of line. */
7271 while (*s < end && (c = *(*s)++, c != '\n'))
7274 else if (isdigit (c))
7276 /* Read decimal number. */
7277 val = c - '0';
7278 while (*s < end && (c = *(*s)++, isdigit (c)))
7279 val = 10 * val + c - '0';
7280 break;
7282 else
7283 break;
7286 return val;
7290 /* Load PBM image IMG for use on frame F. */
7292 static int
7293 pbm_load (f, img)
7294 struct frame *f;
7295 struct image *img;
7297 int raw_p, x, y;
7298 int width, height, max_color_idx = 0;
7299 XImage *ximg;
7300 Lisp_Object file, specified_file;
7301 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7302 struct gcpro gcpro1;
7303 unsigned char *contents = NULL;
7304 unsigned char *end, *p;
7305 int size;
7307 specified_file = image_spec_value (img->spec, QCfile, NULL);
7308 file = Qnil;
7309 GCPRO1 (file);
7311 if (STRINGP (specified_file))
7313 file = x_find_image_file (specified_file);
7314 if (!STRINGP (file))
7316 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7317 UNGCPRO;
7318 return 0;
7321 contents = slurp_file (XSTRING (file)->data, &size);
7322 if (contents == NULL)
7324 image_error ("Error reading `%s'", file, Qnil);
7325 UNGCPRO;
7326 return 0;
7329 p = contents;
7330 end = contents + size;
7332 else
7334 Lisp_Object data;
7335 data = image_spec_value (img->spec, QCdata, NULL);
7336 p = XSTRING (data)->data;
7337 end = p + STRING_BYTES (XSTRING (data));
7340 /* Check magic number. */
7341 if (end - p < 2 || *p++ != 'P')
7343 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7344 error:
7345 xfree (contents);
7346 UNGCPRO;
7347 return 0;
7350 switch (*p++)
7352 case '1':
7353 raw_p = 0, type = PBM_MONO;
7354 break;
7356 case '2':
7357 raw_p = 0, type = PBM_GRAY;
7358 break;
7360 case '3':
7361 raw_p = 0, type = PBM_COLOR;
7362 break;
7364 case '4':
7365 raw_p = 1, type = PBM_MONO;
7366 break;
7368 case '5':
7369 raw_p = 1, type = PBM_GRAY;
7370 break;
7372 case '6':
7373 raw_p = 1, type = PBM_COLOR;
7374 break;
7376 default:
7377 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7378 goto error;
7381 /* Read width, height, maximum color-component. Characters
7382 starting with `#' up to the end of a line are ignored. */
7383 width = pbm_scan_number (&p, end);
7384 height = pbm_scan_number (&p, end);
7386 if (type != PBM_MONO)
7388 max_color_idx = pbm_scan_number (&p, end);
7389 if (raw_p && max_color_idx > 255)
7390 max_color_idx = 255;
7393 if (width < 0
7394 || height < 0
7395 || (type != PBM_MONO && max_color_idx < 0))
7396 goto error;
7398 BLOCK_INPUT;
7399 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7400 &ximg, &img->pixmap))
7402 UNBLOCK_INPUT;
7403 goto error;
7406 /* Initialize the color hash table. */
7407 init_color_table ();
7409 if (type == PBM_MONO)
7411 int c = 0, g;
7413 for (y = 0; y < height; ++y)
7414 for (x = 0; x < width; ++x)
7416 if (raw_p)
7418 if ((x & 7) == 0)
7419 c = *p++;
7420 g = c & 0x80;
7421 c <<= 1;
7423 else
7424 g = pbm_scan_number (&p, end);
7426 XPutPixel (ximg, x, y, (g
7427 ? FRAME_FOREGROUND_PIXEL (f)
7428 : FRAME_BACKGROUND_PIXEL (f)));
7431 else
7433 for (y = 0; y < height; ++y)
7434 for (x = 0; x < width; ++x)
7436 int r, g, b;
7438 if (type == PBM_GRAY)
7439 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
7440 else if (raw_p)
7442 r = *p++;
7443 g = *p++;
7444 b = *p++;
7446 else
7448 r = pbm_scan_number (&p, end);
7449 g = pbm_scan_number (&p, end);
7450 b = pbm_scan_number (&p, end);
7453 if (r < 0 || g < 0 || b < 0)
7455 xfree (ximg->data);
7456 ximg->data = NULL;
7457 XDestroyImage (ximg);
7458 UNBLOCK_INPUT;
7459 image_error ("Invalid pixel value in image `%s'",
7460 img->spec, Qnil);
7461 goto error;
7464 /* RGB values are now in the range 0..max_color_idx.
7465 Scale this to the range 0..0xffff supported by X. */
7466 r = (double) r * 65535 / max_color_idx;
7467 g = (double) g * 65535 / max_color_idx;
7468 b = (double) b * 65535 / max_color_idx;
7469 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7473 /* Store in IMG->colors the colors allocated for the image, and
7474 free the color table. */
7475 img->colors = colors_in_color_table (&img->ncolors);
7476 free_color_table ();
7478 /* Put the image into a pixmap. */
7479 x_put_x_image (f, ximg, img->pixmap, width, height);
7480 x_destroy_x_image (ximg);
7481 UNBLOCK_INPUT;
7483 img->width = width;
7484 img->height = height;
7486 UNGCPRO;
7487 xfree (contents);
7488 return 1;
7493 /***********************************************************************
7495 ***********************************************************************/
7497 #if HAVE_PNG
7499 #include <png.h>
7501 /* Function prototypes. */
7503 static int png_image_p P_ ((Lisp_Object object));
7504 static int png_load P_ ((struct frame *f, struct image *img));
7506 /* The symbol `png' identifying images of this type. */
7508 Lisp_Object Qpng;
7510 /* Indices of image specification fields in png_format, below. */
7512 enum png_keyword_index
7514 PNG_TYPE,
7515 PNG_DATA,
7516 PNG_FILE,
7517 PNG_ASCENT,
7518 PNG_MARGIN,
7519 PNG_RELIEF,
7520 PNG_ALGORITHM,
7521 PNG_HEURISTIC_MASK,
7522 PNG_LAST
7525 /* Vector of image_keyword structures describing the format
7526 of valid user-defined image specifications. */
7528 static struct image_keyword png_format[PNG_LAST] =
7530 {":type", IMAGE_SYMBOL_VALUE, 1},
7531 {":data", IMAGE_STRING_VALUE, 0},
7532 {":file", IMAGE_STRING_VALUE, 0},
7533 {":ascent", IMAGE_ASCENT_VALUE, 0},
7534 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7535 {":relief", IMAGE_INTEGER_VALUE, 0},
7536 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7537 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7540 /* Structure describing the image type `png'. */
7542 static struct image_type png_type =
7544 &Qpng,
7545 png_image_p,
7546 png_load,
7547 x_clear_image,
7548 NULL
7552 /* Return non-zero if OBJECT is a valid PNG image specification. */
7554 static int
7555 png_image_p (object)
7556 Lisp_Object object;
7558 struct image_keyword fmt[PNG_LAST];
7559 bcopy (png_format, fmt, sizeof fmt);
7561 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
7562 return 0;
7564 /* Must specify either the :data or :file keyword. */
7565 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7569 /* Error and warning handlers installed when the PNG library
7570 is initialized. */
7572 static void
7573 my_png_error (png_ptr, msg)
7574 png_struct *png_ptr;
7575 char *msg;
7577 xassert (png_ptr != NULL);
7578 image_error ("PNG error: %s", build_string (msg), Qnil);
7579 longjmp (png_ptr->jmpbuf, 1);
7583 static void
7584 my_png_warning (png_ptr, msg)
7585 png_struct *png_ptr;
7586 char *msg;
7588 xassert (png_ptr != NULL);
7589 image_error ("PNG warning: %s", build_string (msg), Qnil);
7592 /* Memory source for PNG decoding. */
7594 struct png_memory_storage
7596 unsigned char *bytes; /* The data */
7597 size_t len; /* How big is it? */
7598 int index; /* Where are we? */
7602 /* Function set as reader function when reading PNG image from memory.
7603 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7604 bytes from the input to DATA. */
7606 static void
7607 png_read_from_memory (png_ptr, data, length)
7608 png_structp png_ptr;
7609 png_bytep data;
7610 png_size_t length;
7612 struct png_memory_storage *tbr
7613 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
7615 if (length > tbr->len - tbr->index)
7616 png_error (png_ptr, "Read error");
7618 bcopy (tbr->bytes + tbr->index, data, length);
7619 tbr->index = tbr->index + length;
7622 /* Load PNG image IMG for use on frame F. Value is non-zero if
7623 successful. */
7625 static int
7626 png_load (f, img)
7627 struct frame *f;
7628 struct image *img;
7630 Lisp_Object file, specified_file;
7631 Lisp_Object specified_data;
7632 int x, y, i;
7633 XImage *ximg, *mask_img = NULL;
7634 struct gcpro gcpro1;
7635 png_struct *png_ptr = NULL;
7636 png_info *info_ptr = NULL, *end_info = NULL;
7637 FILE *fp = NULL;
7638 png_byte sig[8];
7639 png_byte *pixels = NULL;
7640 png_byte **rows = NULL;
7641 png_uint_32 width, height;
7642 int bit_depth, color_type, interlace_type;
7643 png_byte channels;
7644 png_uint_32 row_bytes;
7645 int transparent_p;
7646 char *gamma_str;
7647 double screen_gamma, image_gamma;
7648 int intent;
7649 struct png_memory_storage tbr; /* Data to be read */
7651 /* Find out what file to load. */
7652 specified_file = image_spec_value (img->spec, QCfile, NULL);
7653 specified_data = image_spec_value (img->spec, QCdata, NULL);
7654 file = Qnil;
7655 GCPRO1 (file);
7657 if (NILP (specified_data))
7659 file = x_find_image_file (specified_file);
7660 if (!STRINGP (file))
7662 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7663 UNGCPRO;
7664 return 0;
7667 /* Open the image file. */
7668 fp = fopen (XSTRING (file)->data, "rb");
7669 if (!fp)
7671 image_error ("Cannot open image file `%s'", file, Qnil);
7672 UNGCPRO;
7673 fclose (fp);
7674 return 0;
7677 /* Check PNG signature. */
7678 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7679 || !png_check_sig (sig, sizeof sig))
7681 image_error ("Not a PNG file: `%s'", file, Qnil);
7682 UNGCPRO;
7683 fclose (fp);
7684 return 0;
7687 else
7689 /* Read from memory. */
7690 tbr.bytes = XSTRING (specified_data)->data;
7691 tbr.len = STRING_BYTES (XSTRING (specified_data));
7692 tbr.index = 0;
7694 /* Check PNG signature. */
7695 if (tbr.len < sizeof sig
7696 || !png_check_sig (tbr.bytes, sizeof sig))
7698 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
7699 UNGCPRO;
7700 return 0;
7703 /* Need to skip past the signature. */
7704 tbr.bytes += sizeof (sig);
7707 /* Initialize read and info structs for PNG lib. */
7708 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7709 my_png_error, my_png_warning);
7710 if (!png_ptr)
7712 if (fp) fclose (fp);
7713 UNGCPRO;
7714 return 0;
7717 info_ptr = png_create_info_struct (png_ptr);
7718 if (!info_ptr)
7720 png_destroy_read_struct (&png_ptr, NULL, NULL);
7721 if (fp) fclose (fp);
7722 UNGCPRO;
7723 return 0;
7726 end_info = png_create_info_struct (png_ptr);
7727 if (!end_info)
7729 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7730 if (fp) fclose (fp);
7731 UNGCPRO;
7732 return 0;
7735 /* Set error jump-back. We come back here when the PNG library
7736 detects an error. */
7737 if (setjmp (png_ptr->jmpbuf))
7739 error:
7740 if (png_ptr)
7741 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7742 xfree (pixels);
7743 xfree (rows);
7744 if (fp) fclose (fp);
7745 UNGCPRO;
7746 return 0;
7749 /* Read image info. */
7750 if (!NILP (specified_data))
7751 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
7752 else
7753 png_init_io (png_ptr, fp);
7755 png_set_sig_bytes (png_ptr, sizeof sig);
7756 png_read_info (png_ptr, info_ptr);
7757 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
7758 &interlace_type, NULL, NULL);
7760 /* If image contains simply transparency data, we prefer to
7761 construct a clipping mask. */
7762 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
7763 transparent_p = 1;
7764 else
7765 transparent_p = 0;
7767 /* This function is easier to write if we only have to handle
7768 one data format: RGB or RGBA with 8 bits per channel. Let's
7769 transform other formats into that format. */
7771 /* Strip more than 8 bits per channel. */
7772 if (bit_depth == 16)
7773 png_set_strip_16 (png_ptr);
7775 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7776 if available. */
7777 png_set_expand (png_ptr);
7779 /* Convert grayscale images to RGB. */
7780 if (color_type == PNG_COLOR_TYPE_GRAY
7781 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7782 png_set_gray_to_rgb (png_ptr);
7784 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
7785 gamma_str = getenv ("SCREEN_GAMMA");
7786 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
7788 /* Tell the PNG lib to handle gamma correction for us. */
7790 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7791 if (png_get_sRGB (png_ptr, info_ptr, &intent))
7792 /* There is a special chunk in the image specifying the gamma. */
7793 png_set_sRGB (png_ptr, info_ptr, intent);
7794 else
7795 #endif
7796 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
7797 /* Image contains gamma information. */
7798 png_set_gamma (png_ptr, screen_gamma, image_gamma);
7799 else
7800 /* Use a default of 0.5 for the image gamma. */
7801 png_set_gamma (png_ptr, screen_gamma, 0.5);
7803 /* Handle alpha channel by combining the image with a background
7804 color. Do this only if a real alpha channel is supplied. For
7805 simple transparency, we prefer a clipping mask. */
7806 if (!transparent_p)
7808 png_color_16 *image_background;
7810 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
7811 /* Image contains a background color with which to
7812 combine the image. */
7813 png_set_background (png_ptr, image_background,
7814 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
7815 else
7817 /* Image does not contain a background color with which
7818 to combine the image data via an alpha channel. Use
7819 the frame's background instead. */
7820 XColor color;
7821 Colormap cmap;
7822 png_color_16 frame_background;
7824 BLOCK_INPUT;
7825 cmap = FRAME_X_COLORMAP (f);
7826 color.pixel = FRAME_BACKGROUND_PIXEL (f);
7827 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
7828 UNBLOCK_INPUT;
7830 bzero (&frame_background, sizeof frame_background);
7831 frame_background.red = color.red;
7832 frame_background.green = color.green;
7833 frame_background.blue = color.blue;
7835 png_set_background (png_ptr, &frame_background,
7836 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7840 /* Update info structure. */
7841 png_read_update_info (png_ptr, info_ptr);
7843 /* Get number of channels. Valid values are 1 for grayscale images
7844 and images with a palette, 2 for grayscale images with transparency
7845 information (alpha channel), 3 for RGB images, and 4 for RGB
7846 images with alpha channel, i.e. RGBA. If conversions above were
7847 sufficient we should only have 3 or 4 channels here. */
7848 channels = png_get_channels (png_ptr, info_ptr);
7849 xassert (channels == 3 || channels == 4);
7851 /* Number of bytes needed for one row of the image. */
7852 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
7854 /* Allocate memory for the image. */
7855 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
7856 rows = (png_byte **) xmalloc (height * sizeof *rows);
7857 for (i = 0; i < height; ++i)
7858 rows[i] = pixels + i * row_bytes;
7860 /* Read the entire image. */
7861 png_read_image (png_ptr, rows);
7862 png_read_end (png_ptr, info_ptr);
7863 if (fp)
7865 fclose (fp);
7866 fp = NULL;
7869 BLOCK_INPUT;
7871 /* Create the X image and pixmap. */
7872 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7873 &img->pixmap))
7875 UNBLOCK_INPUT;
7876 goto error;
7879 /* Create an image and pixmap serving as mask if the PNG image
7880 contains an alpha channel. */
7881 if (channels == 4
7882 && !transparent_p
7883 && !x_create_x_image_and_pixmap (f, width, height, 1,
7884 &mask_img, &img->mask))
7886 x_destroy_x_image (ximg);
7887 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
7888 img->pixmap = 0;
7889 UNBLOCK_INPUT;
7890 goto error;
7893 /* Fill the X image and mask from PNG data. */
7894 init_color_table ();
7896 for (y = 0; y < height; ++y)
7898 png_byte *p = rows[y];
7900 for (x = 0; x < width; ++x)
7902 unsigned r, g, b;
7904 r = *p++ << 8;
7905 g = *p++ << 8;
7906 b = *p++ << 8;
7907 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7909 /* An alpha channel, aka mask channel, associates variable
7910 transparency with an image. Where other image formats
7911 support binary transparency---fully transparent or fully
7912 opaque---PNG allows up to 254 levels of partial transparency.
7913 The PNG library implements partial transparency by combining
7914 the image with a specified background color.
7916 I'm not sure how to handle this here nicely: because the
7917 background on which the image is displayed may change, for
7918 real alpha channel support, it would be necessary to create
7919 a new image for each possible background.
7921 What I'm doing now is that a mask is created if we have
7922 boolean transparency information. Otherwise I'm using
7923 the frame's background color to combine the image with. */
7925 if (channels == 4)
7927 if (mask_img)
7928 XPutPixel (mask_img, x, y, *p > 0);
7929 ++p;
7934 /* Remember colors allocated for this image. */
7935 img->colors = colors_in_color_table (&img->ncolors);
7936 free_color_table ();
7938 /* Clean up. */
7939 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7940 xfree (rows);
7941 xfree (pixels);
7943 img->width = width;
7944 img->height = height;
7946 /* Put the image into the pixmap, then free the X image and its buffer. */
7947 x_put_x_image (f, ximg, img->pixmap, width, height);
7948 x_destroy_x_image (ximg);
7950 /* Same for the mask. */
7951 if (mask_img)
7953 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7954 x_destroy_x_image (mask_img);
7957 UNBLOCK_INPUT;
7958 UNGCPRO;
7959 return 1;
7962 #endif /* HAVE_PNG != 0 */
7966 /***********************************************************************
7967 JPEG
7968 ***********************************************************************/
7970 #if HAVE_JPEG
7972 /* Work around a warning about HAVE_STDLIB_H being redefined in
7973 jconfig.h. */
7974 #ifdef HAVE_STDLIB_H
7975 #define HAVE_STDLIB_H_1
7976 #undef HAVE_STDLIB_H
7977 #endif /* HAVE_STLIB_H */
7979 #include <jpeglib.h>
7980 #include <jerror.h>
7981 #include <setjmp.h>
7983 #ifdef HAVE_STLIB_H_1
7984 #define HAVE_STDLIB_H 1
7985 #endif
7987 static int jpeg_image_p P_ ((Lisp_Object object));
7988 static int jpeg_load P_ ((struct frame *f, struct image *img));
7990 /* The symbol `jpeg' identifying images of this type. */
7992 Lisp_Object Qjpeg;
7994 /* Indices of image specification fields in gs_format, below. */
7996 enum jpeg_keyword_index
7998 JPEG_TYPE,
7999 JPEG_DATA,
8000 JPEG_FILE,
8001 JPEG_ASCENT,
8002 JPEG_MARGIN,
8003 JPEG_RELIEF,
8004 JPEG_ALGORITHM,
8005 JPEG_HEURISTIC_MASK,
8006 JPEG_LAST
8009 /* Vector of image_keyword structures describing the format
8010 of valid user-defined image specifications. */
8012 static struct image_keyword jpeg_format[JPEG_LAST] =
8014 {":type", IMAGE_SYMBOL_VALUE, 1},
8015 {":data", IMAGE_STRING_VALUE, 0},
8016 {":file", IMAGE_STRING_VALUE, 0},
8017 {":ascent", IMAGE_ASCENT_VALUE, 0},
8018 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8019 {":relief", IMAGE_INTEGER_VALUE, 0},
8020 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8021 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8024 /* Structure describing the image type `jpeg'. */
8026 static struct image_type jpeg_type =
8028 &Qjpeg,
8029 jpeg_image_p,
8030 jpeg_load,
8031 x_clear_image,
8032 NULL
8036 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8038 static int
8039 jpeg_image_p (object)
8040 Lisp_Object object;
8042 struct image_keyword fmt[JPEG_LAST];
8044 bcopy (jpeg_format, fmt, sizeof fmt);
8046 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8047 return 0;
8049 /* Must specify either the :data or :file keyword. */
8050 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8054 struct my_jpeg_error_mgr
8056 struct jpeg_error_mgr pub;
8057 jmp_buf setjmp_buffer;
8061 static void
8062 my_error_exit (cinfo)
8063 j_common_ptr cinfo;
8065 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8066 longjmp (mgr->setjmp_buffer, 1);
8070 /* Init source method for JPEG data source manager. Called by
8071 jpeg_read_header() before any data is actually read. See
8072 libjpeg.doc from the JPEG lib distribution. */
8074 static void
8075 our_init_source (cinfo)
8076 j_decompress_ptr cinfo;
8081 /* Fill input buffer method for JPEG data source manager. Called
8082 whenever more data is needed. We read the whole image in one step,
8083 so this only adds a fake end of input marker at the end. */
8085 static boolean
8086 our_fill_input_buffer (cinfo)
8087 j_decompress_ptr cinfo;
8089 /* Insert a fake EOI marker. */
8090 struct jpeg_source_mgr *src = cinfo->src;
8091 static JOCTET buffer[2];
8093 buffer[0] = (JOCTET) 0xFF;
8094 buffer[1] = (JOCTET) JPEG_EOI;
8096 src->next_input_byte = buffer;
8097 src->bytes_in_buffer = 2;
8098 return TRUE;
8102 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8103 is the JPEG data source manager. */
8105 static void
8106 our_skip_input_data (cinfo, num_bytes)
8107 j_decompress_ptr cinfo;
8108 long num_bytes;
8110 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
8112 if (src)
8114 if (num_bytes > src->bytes_in_buffer)
8115 ERREXIT (cinfo, JERR_INPUT_EOF);
8117 src->bytes_in_buffer -= num_bytes;
8118 src->next_input_byte += num_bytes;
8123 /* Method to terminate data source. Called by
8124 jpeg_finish_decompress() after all data has been processed. */
8126 static void
8127 our_term_source (cinfo)
8128 j_decompress_ptr cinfo;
8133 /* Set up the JPEG lib for reading an image from DATA which contains
8134 LEN bytes. CINFO is the decompression info structure created for
8135 reading the image. */
8137 static void
8138 jpeg_memory_src (cinfo, data, len)
8139 j_decompress_ptr cinfo;
8140 JOCTET *data;
8141 unsigned int len;
8143 struct jpeg_source_mgr *src;
8145 if (cinfo->src == NULL)
8147 /* First time for this JPEG object? */
8148 cinfo->src = (struct jpeg_source_mgr *)
8149 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
8150 sizeof (struct jpeg_source_mgr));
8151 src = (struct jpeg_source_mgr *) cinfo->src;
8152 src->next_input_byte = data;
8155 src = (struct jpeg_source_mgr *) cinfo->src;
8156 src->init_source = our_init_source;
8157 src->fill_input_buffer = our_fill_input_buffer;
8158 src->skip_input_data = our_skip_input_data;
8159 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
8160 src->term_source = our_term_source;
8161 src->bytes_in_buffer = len;
8162 src->next_input_byte = data;
8166 /* Load image IMG for use on frame F. Patterned after example.c
8167 from the JPEG lib. */
8169 static int
8170 jpeg_load (f, img)
8171 struct frame *f;
8172 struct image *img;
8174 struct jpeg_decompress_struct cinfo;
8175 struct my_jpeg_error_mgr mgr;
8176 Lisp_Object file, specified_file;
8177 Lisp_Object specified_data;
8178 FILE *fp = NULL;
8179 JSAMPARRAY buffer;
8180 int row_stride, x, y;
8181 XImage *ximg = NULL;
8182 int rc;
8183 unsigned long *colors;
8184 int width, height;
8185 struct gcpro gcpro1;
8187 /* Open the JPEG file. */
8188 specified_file = image_spec_value (img->spec, QCfile, NULL);
8189 specified_data = image_spec_value (img->spec, QCdata, NULL);
8190 file = Qnil;
8191 GCPRO1 (file);
8193 if (NILP (specified_data))
8195 file = x_find_image_file (specified_file);
8196 if (!STRINGP (file))
8198 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8199 UNGCPRO;
8200 return 0;
8203 fp = fopen (XSTRING (file)->data, "r");
8204 if (fp == NULL)
8206 image_error ("Cannot open `%s'", file, Qnil);
8207 UNGCPRO;
8208 return 0;
8212 /* Customize libjpeg's error handling to call my_error_exit when an
8213 error is detected. This function will perform a longjmp. */
8214 cinfo.err = jpeg_std_error (&mgr.pub);
8215 mgr.pub.error_exit = my_error_exit;
8217 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8219 if (rc == 1)
8221 /* Called from my_error_exit. Display a JPEG error. */
8222 char buffer[JMSG_LENGTH_MAX];
8223 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8224 image_error ("Error reading JPEG image `%s': %s", img->spec,
8225 build_string (buffer));
8228 /* Close the input file and destroy the JPEG object. */
8229 if (fp)
8230 fclose (fp);
8231 jpeg_destroy_decompress (&cinfo);
8233 BLOCK_INPUT;
8235 /* If we already have an XImage, free that. */
8236 x_destroy_x_image (ximg);
8238 /* Free pixmap and colors. */
8239 x_clear_image (f, img);
8241 UNBLOCK_INPUT;
8242 UNGCPRO;
8243 return 0;
8246 /* Create the JPEG decompression object. Let it read from fp.
8247 Read the JPEG image header. */
8248 jpeg_create_decompress (&cinfo);
8250 if (NILP (specified_data))
8251 jpeg_stdio_src (&cinfo, fp);
8252 else
8253 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
8254 STRING_BYTES (XSTRING (specified_data)));
8256 jpeg_read_header (&cinfo, TRUE);
8258 /* Customize decompression so that color quantization will be used.
8259 Start decompression. */
8260 cinfo.quantize_colors = TRUE;
8261 jpeg_start_decompress (&cinfo);
8262 width = img->width = cinfo.output_width;
8263 height = img->height = cinfo.output_height;
8265 BLOCK_INPUT;
8267 /* Create X image and pixmap. */
8268 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8270 UNBLOCK_INPUT;
8271 longjmp (mgr.setjmp_buffer, 2);
8274 /* Allocate colors. When color quantization is used,
8275 cinfo.actual_number_of_colors has been set with the number of
8276 colors generated, and cinfo.colormap is a two-dimensional array
8277 of color indices in the range 0..cinfo.actual_number_of_colors.
8278 No more than 255 colors will be generated. */
8280 int i, ir, ig, ib;
8282 if (cinfo.out_color_components > 2)
8283 ir = 0, ig = 1, ib = 2;
8284 else if (cinfo.out_color_components > 1)
8285 ir = 0, ig = 1, ib = 0;
8286 else
8287 ir = 0, ig = 0, ib = 0;
8289 /* Use the color table mechanism because it handles colors that
8290 cannot be allocated nicely. Such colors will be replaced with
8291 a default color, and we don't have to care about which colors
8292 can be freed safely, and which can't. */
8293 init_color_table ();
8294 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8295 * sizeof *colors);
8297 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8299 /* Multiply RGB values with 255 because X expects RGB values
8300 in the range 0..0xffff. */
8301 int r = cinfo.colormap[ir][i] << 8;
8302 int g = cinfo.colormap[ig][i] << 8;
8303 int b = cinfo.colormap[ib][i] << 8;
8304 colors[i] = lookup_rgb_color (f, r, g, b);
8307 /* Remember those colors actually allocated. */
8308 img->colors = colors_in_color_table (&img->ncolors);
8309 free_color_table ();
8312 /* Read pixels. */
8313 row_stride = width * cinfo.output_components;
8314 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
8315 row_stride, 1);
8316 for (y = 0; y < height; ++y)
8318 jpeg_read_scanlines (&cinfo, buffer, 1);
8319 for (x = 0; x < cinfo.output_width; ++x)
8320 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
8323 /* Clean up. */
8324 jpeg_finish_decompress (&cinfo);
8325 jpeg_destroy_decompress (&cinfo);
8326 if (fp)
8327 fclose (fp);
8329 /* Put the image into the pixmap. */
8330 x_put_x_image (f, ximg, img->pixmap, width, height);
8331 x_destroy_x_image (ximg);
8332 UNBLOCK_INPUT;
8333 UNGCPRO;
8334 return 1;
8337 #endif /* HAVE_JPEG */
8341 /***********************************************************************
8342 TIFF
8343 ***********************************************************************/
8345 #if HAVE_TIFF
8347 #include <tiffio.h>
8349 static int tiff_image_p P_ ((Lisp_Object object));
8350 static int tiff_load P_ ((struct frame *f, struct image *img));
8352 /* The symbol `tiff' identifying images of this type. */
8354 Lisp_Object Qtiff;
8356 /* Indices of image specification fields in tiff_format, below. */
8358 enum tiff_keyword_index
8360 TIFF_TYPE,
8361 TIFF_DATA,
8362 TIFF_FILE,
8363 TIFF_ASCENT,
8364 TIFF_MARGIN,
8365 TIFF_RELIEF,
8366 TIFF_ALGORITHM,
8367 TIFF_HEURISTIC_MASK,
8368 TIFF_LAST
8371 /* Vector of image_keyword structures describing the format
8372 of valid user-defined image specifications. */
8374 static struct image_keyword tiff_format[TIFF_LAST] =
8376 {":type", IMAGE_SYMBOL_VALUE, 1},
8377 {":data", IMAGE_STRING_VALUE, 0},
8378 {":file", IMAGE_STRING_VALUE, 0},
8379 {":ascent", IMAGE_ASCENT_VALUE, 0},
8380 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8381 {":relief", IMAGE_INTEGER_VALUE, 0},
8382 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8383 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8386 /* Structure describing the image type `tiff'. */
8388 static struct image_type tiff_type =
8390 &Qtiff,
8391 tiff_image_p,
8392 tiff_load,
8393 x_clear_image,
8394 NULL
8398 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8400 static int
8401 tiff_image_p (object)
8402 Lisp_Object object;
8404 struct image_keyword fmt[TIFF_LAST];
8405 bcopy (tiff_format, fmt, sizeof fmt);
8407 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
8408 return 0;
8410 /* Must specify either the :data or :file keyword. */
8411 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8415 /* Reading from a memory buffer for TIFF images Based on the PNG
8416 memory source, but we have to provide a lot of extra functions.
8417 Blah.
8419 We really only need to implement read and seek, but I am not
8420 convinced that the TIFF library is smart enough not to destroy
8421 itself if we only hand it the function pointers we need to
8422 override. */
8424 typedef struct
8426 unsigned char *bytes;
8427 size_t len;
8428 int index;
8430 tiff_memory_source;
8433 static size_t
8434 tiff_read_from_memory (data, buf, size)
8435 thandle_t data;
8436 tdata_t buf;
8437 tsize_t size;
8439 tiff_memory_source *src = (tiff_memory_source *) data;
8441 if (size > src->len - src->index)
8442 return (size_t) -1;
8443 bcopy (src->bytes + src->index, buf, size);
8444 src->index += size;
8445 return size;
8449 static size_t
8450 tiff_write_from_memory (data, buf, size)
8451 thandle_t data;
8452 tdata_t buf;
8453 tsize_t size;
8455 return (size_t) -1;
8459 static toff_t
8460 tiff_seek_in_memory (data, off, whence)
8461 thandle_t data;
8462 toff_t off;
8463 int whence;
8465 tiff_memory_source *src = (tiff_memory_source *) data;
8466 int idx;
8468 switch (whence)
8470 case SEEK_SET: /* Go from beginning of source. */
8471 idx = off;
8472 break;
8474 case SEEK_END: /* Go from end of source. */
8475 idx = src->len + off;
8476 break;
8478 case SEEK_CUR: /* Go from current position. */
8479 idx = src->index + off;
8480 break;
8482 default: /* Invalid `whence'. */
8483 return -1;
8486 if (idx > src->len || idx < 0)
8487 return -1;
8489 src->index = idx;
8490 return src->index;
8494 static int
8495 tiff_close_memory (data)
8496 thandle_t data;
8498 /* NOOP */
8499 return 0;
8503 static int
8504 tiff_mmap_memory (data, pbase, psize)
8505 thandle_t data;
8506 tdata_t *pbase;
8507 toff_t *psize;
8509 /* It is already _IN_ memory. */
8510 return 0;
8514 static void
8515 tiff_unmap_memory (data, base, size)
8516 thandle_t data;
8517 tdata_t base;
8518 toff_t size;
8520 /* We don't need to do this. */
8524 static toff_t
8525 tiff_size_of_memory (data)
8526 thandle_t data;
8528 return ((tiff_memory_source *) data)->len;
8532 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8533 successful. */
8535 static int
8536 tiff_load (f, img)
8537 struct frame *f;
8538 struct image *img;
8540 Lisp_Object file, specified_file;
8541 Lisp_Object specified_data;
8542 TIFF *tiff;
8543 int width, height, x, y;
8544 uint32 *buf;
8545 int rc;
8546 XImage *ximg;
8547 struct gcpro gcpro1;
8548 tiff_memory_source memsrc;
8550 specified_file = image_spec_value (img->spec, QCfile, NULL);
8551 specified_data = image_spec_value (img->spec, QCdata, NULL);
8552 file = Qnil;
8553 GCPRO1 (file);
8555 if (NILP (specified_data))
8557 /* Read from a file */
8558 file = x_find_image_file (specified_file);
8559 if (!STRINGP (file))
8561 image_error ("Cannot find image file `%s'", file, Qnil);
8562 UNGCPRO;
8563 return 0;
8566 /* Try to open the image file. */
8567 tiff = TIFFOpen (XSTRING (file)->data, "r");
8568 if (tiff == NULL)
8570 image_error ("Cannot open `%s'", file, Qnil);
8571 UNGCPRO;
8572 return 0;
8575 else
8577 /* Memory source! */
8578 memsrc.bytes = XSTRING (specified_data)->data;
8579 memsrc.len = STRING_BYTES (XSTRING (specified_data));
8580 memsrc.index = 0;
8582 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8583 (TIFFReadWriteProc) tiff_read_from_memory,
8584 (TIFFReadWriteProc) tiff_write_from_memory,
8585 tiff_seek_in_memory,
8586 tiff_close_memory,
8587 tiff_size_of_memory,
8588 tiff_mmap_memory,
8589 tiff_unmap_memory);
8591 if (!tiff)
8593 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
8594 UNGCPRO;
8595 return 0;
8599 /* Get width and height of the image, and allocate a raster buffer
8600 of width x height 32-bit values. */
8601 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8602 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8603 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8605 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8606 TIFFClose (tiff);
8607 if (!rc)
8609 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8610 xfree (buf);
8611 UNGCPRO;
8612 return 0;
8615 BLOCK_INPUT;
8617 /* Create the X image and pixmap. */
8618 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8620 UNBLOCK_INPUT;
8621 xfree (buf);
8622 UNGCPRO;
8623 return 0;
8626 /* Initialize the color table. */
8627 init_color_table ();
8629 /* Process the pixel raster. Origin is in the lower-left corner. */
8630 for (y = 0; y < height; ++y)
8632 uint32 *row = buf + y * width;
8634 for (x = 0; x < width; ++x)
8636 uint32 abgr = row[x];
8637 int r = TIFFGetR (abgr) << 8;
8638 int g = TIFFGetG (abgr) << 8;
8639 int b = TIFFGetB (abgr) << 8;
8640 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8644 /* Remember the colors allocated for the image. Free the color table. */
8645 img->colors = colors_in_color_table (&img->ncolors);
8646 free_color_table ();
8648 /* Put the image into the pixmap, then free the X image and its buffer. */
8649 x_put_x_image (f, ximg, img->pixmap, width, height);
8650 x_destroy_x_image (ximg);
8651 xfree (buf);
8652 UNBLOCK_INPUT;
8654 img->width = width;
8655 img->height = height;
8657 UNGCPRO;
8658 return 1;
8661 #endif /* HAVE_TIFF != 0 */
8665 /***********************************************************************
8667 ***********************************************************************/
8669 #if HAVE_GIF
8671 #include <gif_lib.h>
8673 static int gif_image_p P_ ((Lisp_Object object));
8674 static int gif_load P_ ((struct frame *f, struct image *img));
8676 /* The symbol `gif' identifying images of this type. */
8678 Lisp_Object Qgif;
8680 /* Indices of image specification fields in gif_format, below. */
8682 enum gif_keyword_index
8684 GIF_TYPE,
8685 GIF_DATA,
8686 GIF_FILE,
8687 GIF_ASCENT,
8688 GIF_MARGIN,
8689 GIF_RELIEF,
8690 GIF_ALGORITHM,
8691 GIF_HEURISTIC_MASK,
8692 GIF_IMAGE,
8693 GIF_LAST
8696 /* Vector of image_keyword structures describing the format
8697 of valid user-defined image specifications. */
8699 static struct image_keyword gif_format[GIF_LAST] =
8701 {":type", IMAGE_SYMBOL_VALUE, 1},
8702 {":data", IMAGE_STRING_VALUE, 0},
8703 {":file", IMAGE_STRING_VALUE, 0},
8704 {":ascent", IMAGE_ASCENT_VALUE, 0},
8705 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8706 {":relief", IMAGE_INTEGER_VALUE, 0},
8707 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8708 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8709 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
8712 /* Structure describing the image type `gif'. */
8714 static struct image_type gif_type =
8716 &Qgif,
8717 gif_image_p,
8718 gif_load,
8719 x_clear_image,
8720 NULL
8724 /* Return non-zero if OBJECT is a valid GIF image specification. */
8726 static int
8727 gif_image_p (object)
8728 Lisp_Object object;
8730 struct image_keyword fmt[GIF_LAST];
8731 bcopy (gif_format, fmt, sizeof fmt);
8733 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8734 return 0;
8736 /* Must specify either the :data or :file keyword. */
8737 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8741 /* Reading a GIF image from memory
8742 Based on the PNG memory stuff to a certain extent. */
8744 typedef struct
8746 unsigned char *bytes;
8747 size_t len;
8748 int index;
8750 gif_memory_source;
8753 /* Make the current memory source available to gif_read_from_memory.
8754 It's done this way because not all versions of libungif support
8755 a UserData field in the GifFileType structure. */
8756 static gif_memory_source *current_gif_memory_src;
8758 static int
8759 gif_read_from_memory (file, buf, len)
8760 GifFileType *file;
8761 GifByteType *buf;
8762 int len;
8764 gif_memory_source *src = current_gif_memory_src;
8766 if (len > src->len - src->index)
8767 return -1;
8769 bcopy (src->bytes + src->index, buf, len);
8770 src->index += len;
8771 return len;
8775 /* Load GIF image IMG for use on frame F. Value is non-zero if
8776 successful. */
8778 static int
8779 gif_load (f, img)
8780 struct frame *f;
8781 struct image *img;
8783 Lisp_Object file, specified_file;
8784 Lisp_Object specified_data;
8785 int rc, width, height, x, y, i;
8786 XImage *ximg;
8787 ColorMapObject *gif_color_map;
8788 unsigned long pixel_colors[256];
8789 GifFileType *gif;
8790 struct gcpro gcpro1;
8791 Lisp_Object image;
8792 int ino, image_left, image_top, image_width, image_height;
8793 gif_memory_source memsrc;
8794 unsigned char *raster;
8796 specified_file = image_spec_value (img->spec, QCfile, NULL);
8797 specified_data = image_spec_value (img->spec, QCdata, NULL);
8798 file = Qnil;
8799 GCPRO1 (file);
8801 if (NILP (specified_data))
8803 file = x_find_image_file (specified_file);
8804 if (!STRINGP (file))
8806 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8807 UNGCPRO;
8808 return 0;
8811 /* Open the GIF file. */
8812 gif = DGifOpenFileName (XSTRING (file)->data);
8813 if (gif == NULL)
8815 image_error ("Cannot open `%s'", file, Qnil);
8816 UNGCPRO;
8817 return 0;
8820 else
8822 /* Read from memory! */
8823 current_gif_memory_src = &memsrc;
8824 memsrc.bytes = XSTRING (specified_data)->data;
8825 memsrc.len = STRING_BYTES (XSTRING (specified_data));
8826 memsrc.index = 0;
8828 gif = DGifOpen(&memsrc, gif_read_from_memory);
8829 if (!gif)
8831 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8832 UNGCPRO;
8833 return 0;
8837 /* Read entire contents. */
8838 rc = DGifSlurp (gif);
8839 if (rc == GIF_ERROR)
8841 image_error ("Error reading `%s'", img->spec, Qnil);
8842 DGifCloseFile (gif);
8843 UNGCPRO;
8844 return 0;
8847 image = image_spec_value (img->spec, QCindex, NULL);
8848 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8849 if (ino >= gif->ImageCount)
8851 image_error ("Invalid image number `%s' in image `%s'",
8852 image, img->spec);
8853 DGifCloseFile (gif);
8854 UNGCPRO;
8855 return 0;
8858 width = img->width = gif->SWidth;
8859 height = img->height = gif->SHeight;
8861 BLOCK_INPUT;
8863 /* Create the X image and pixmap. */
8864 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8866 UNBLOCK_INPUT;
8867 DGifCloseFile (gif);
8868 UNGCPRO;
8869 return 0;
8872 /* Allocate colors. */
8873 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8874 if (!gif_color_map)
8875 gif_color_map = gif->SColorMap;
8876 init_color_table ();
8877 bzero (pixel_colors, sizeof pixel_colors);
8879 for (i = 0; i < gif_color_map->ColorCount; ++i)
8881 int r = gif_color_map->Colors[i].Red << 8;
8882 int g = gif_color_map->Colors[i].Green << 8;
8883 int b = gif_color_map->Colors[i].Blue << 8;
8884 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8887 img->colors = colors_in_color_table (&img->ncolors);
8888 free_color_table ();
8890 /* Clear the part of the screen image that are not covered by
8891 the image from the GIF file. Full animated GIF support
8892 requires more than can be done here (see the gif89 spec,
8893 disposal methods). Let's simply assume that the part
8894 not covered by a sub-image is in the frame's background color. */
8895 image_top = gif->SavedImages[ino].ImageDesc.Top;
8896 image_left = gif->SavedImages[ino].ImageDesc.Left;
8897 image_width = gif->SavedImages[ino].ImageDesc.Width;
8898 image_height = gif->SavedImages[ino].ImageDesc.Height;
8900 for (y = 0; y < image_top; ++y)
8901 for (x = 0; x < width; ++x)
8902 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8904 for (y = image_top + image_height; y < height; ++y)
8905 for (x = 0; x < width; ++x)
8906 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8908 for (y = image_top; y < image_top + image_height; ++y)
8910 for (x = 0; x < image_left; ++x)
8911 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8912 for (x = image_left + image_width; x < width; ++x)
8913 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8916 /* Read the GIF image into the X image. We use a local variable
8917 `raster' here because RasterBits below is a char *, and invites
8918 problems with bytes >= 0x80. */
8919 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8921 if (gif->SavedImages[ino].ImageDesc.Interlace)
8923 static int interlace_start[] = {0, 4, 2, 1};
8924 static int interlace_increment[] = {8, 8, 4, 2};
8925 int pass, inc;
8926 int row = interlace_start[0];
8928 pass = 0;
8930 for (y = 0; y < image_height; y++)
8932 if (row >= image_height)
8934 row = interlace_start[++pass];
8935 while (row >= image_height)
8936 row = interlace_start[++pass];
8939 for (x = 0; x < image_width; x++)
8941 int i = raster[(y * image_width) + x];
8942 XPutPixel (ximg, x + image_left, row + image_top,
8943 pixel_colors[i]);
8946 row += interlace_increment[pass];
8949 else
8951 for (y = 0; y < image_height; ++y)
8952 for (x = 0; x < image_width; ++x)
8954 int i = raster[y * image_width + x];
8955 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
8959 DGifCloseFile (gif);
8961 /* Put the image into the pixmap, then free the X image and its buffer. */
8962 x_put_x_image (f, ximg, img->pixmap, width, height);
8963 x_destroy_x_image (ximg);
8964 UNBLOCK_INPUT;
8966 UNGCPRO;
8967 return 1;
8970 #endif /* HAVE_GIF != 0 */
8974 /***********************************************************************
8975 Ghostscript
8976 ***********************************************************************/
8978 static int gs_image_p P_ ((Lisp_Object object));
8979 static int gs_load P_ ((struct frame *f, struct image *img));
8980 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8982 /* The symbol `postscript' identifying images of this type. */
8984 Lisp_Object Qpostscript;
8986 /* Keyword symbols. */
8988 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8990 /* Indices of image specification fields in gs_format, below. */
8992 enum gs_keyword_index
8994 GS_TYPE,
8995 GS_PT_WIDTH,
8996 GS_PT_HEIGHT,
8997 GS_FILE,
8998 GS_LOADER,
8999 GS_BOUNDING_BOX,
9000 GS_ASCENT,
9001 GS_MARGIN,
9002 GS_RELIEF,
9003 GS_ALGORITHM,
9004 GS_HEURISTIC_MASK,
9005 GS_LAST
9008 /* Vector of image_keyword structures describing the format
9009 of valid user-defined image specifications. */
9011 static struct image_keyword gs_format[GS_LAST] =
9013 {":type", IMAGE_SYMBOL_VALUE, 1},
9014 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9015 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9016 {":file", IMAGE_STRING_VALUE, 1},
9017 {":loader", IMAGE_FUNCTION_VALUE, 0},
9018 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9019 {":ascent", IMAGE_ASCENT_VALUE, 0},
9020 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9021 {":relief", IMAGE_INTEGER_VALUE, 0},
9022 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9023 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9026 /* Structure describing the image type `ghostscript'. */
9028 static struct image_type gs_type =
9030 &Qpostscript,
9031 gs_image_p,
9032 gs_load,
9033 gs_clear_image,
9034 NULL
9038 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9040 static void
9041 gs_clear_image (f, img)
9042 struct frame *f;
9043 struct image *img;
9045 /* IMG->data.ptr_val may contain a recorded colormap. */
9046 xfree (img->data.ptr_val);
9047 x_clear_image (f, img);
9051 /* Return non-zero if OBJECT is a valid Ghostscript image
9052 specification. */
9054 static int
9055 gs_image_p (object)
9056 Lisp_Object object;
9058 struct image_keyword fmt[GS_LAST];
9059 Lisp_Object tem;
9060 int i;
9062 bcopy (gs_format, fmt, sizeof fmt);
9064 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9065 return 0;
9067 /* Bounding box must be a list or vector containing 4 integers. */
9068 tem = fmt[GS_BOUNDING_BOX].value;
9069 if (CONSP (tem))
9071 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9072 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9073 return 0;
9074 if (!NILP (tem))
9075 return 0;
9077 else if (VECTORP (tem))
9079 if (XVECTOR (tem)->size != 4)
9080 return 0;
9081 for (i = 0; i < 4; ++i)
9082 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9083 return 0;
9085 else
9086 return 0;
9088 return 1;
9092 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9093 if successful. */
9095 static int
9096 gs_load (f, img)
9097 struct frame *f;
9098 struct image *img;
9100 char buffer[100];
9101 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9102 struct gcpro gcpro1, gcpro2;
9103 Lisp_Object frame;
9104 double in_width, in_height;
9105 Lisp_Object pixel_colors = Qnil;
9107 /* Compute pixel size of pixmap needed from the given size in the
9108 image specification. Sizes in the specification are in pt. 1 pt
9109 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9110 info. */
9111 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9112 in_width = XFASTINT (pt_width) / 72.0;
9113 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9114 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9115 in_height = XFASTINT (pt_height) / 72.0;
9116 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9118 /* Create the pixmap. */
9119 BLOCK_INPUT;
9120 xassert (img->pixmap == 0);
9121 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9122 img->width, img->height,
9123 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9124 UNBLOCK_INPUT;
9126 if (!img->pixmap)
9128 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9129 return 0;
9132 /* Call the loader to fill the pixmap. It returns a process object
9133 if successful. We do not record_unwind_protect here because
9134 other places in redisplay like calling window scroll functions
9135 don't either. Let the Lisp loader use `unwind-protect' instead. */
9136 GCPRO2 (window_and_pixmap_id, pixel_colors);
9138 sprintf (buffer, "%lu %lu",
9139 (unsigned long) FRAME_X_WINDOW (f),
9140 (unsigned long) img->pixmap);
9141 window_and_pixmap_id = build_string (buffer);
9143 sprintf (buffer, "%lu %lu",
9144 FRAME_FOREGROUND_PIXEL (f),
9145 FRAME_BACKGROUND_PIXEL (f));
9146 pixel_colors = build_string (buffer);
9148 XSETFRAME (frame, f);
9149 loader = image_spec_value (img->spec, QCloader, NULL);
9150 if (NILP (loader))
9151 loader = intern ("gs-load-image");
9153 img->data.lisp_val = call6 (loader, frame, img->spec,
9154 make_number (img->width),
9155 make_number (img->height),
9156 window_and_pixmap_id,
9157 pixel_colors);
9158 UNGCPRO;
9159 return PROCESSP (img->data.lisp_val);
9163 /* Kill the Ghostscript process that was started to fill PIXMAP on
9164 frame F. Called from XTread_socket when receiving an event
9165 telling Emacs that Ghostscript has finished drawing. */
9167 void
9168 x_kill_gs_process (pixmap, f)
9169 Pixmap pixmap;
9170 struct frame *f;
9172 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9173 int class, i;
9174 struct image *img;
9176 /* Find the image containing PIXMAP. */
9177 for (i = 0; i < c->used; ++i)
9178 if (c->images[i]->pixmap == pixmap)
9179 break;
9181 /* Kill the GS process. We should have found PIXMAP in the image
9182 cache and its image should contain a process object. */
9183 xassert (i < c->used);
9184 img = c->images[i];
9185 xassert (PROCESSP (img->data.lisp_val));
9186 Fkill_process (img->data.lisp_val, Qnil);
9187 img->data.lisp_val = Qnil;
9189 /* On displays with a mutable colormap, figure out the colors
9190 allocated for the image by looking at the pixels of an XImage for
9191 img->pixmap. */
9192 class = FRAME_X_VISUAL (f)->class;
9193 if (class != StaticColor && class != StaticGray && class != TrueColor)
9195 XImage *ximg;
9197 BLOCK_INPUT;
9199 /* Try to get an XImage for img->pixmep. */
9200 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9201 0, 0, img->width, img->height, ~0, ZPixmap);
9202 if (ximg)
9204 int x, y;
9206 /* Initialize the color table. */
9207 init_color_table ();
9209 /* For each pixel of the image, look its color up in the
9210 color table. After having done so, the color table will
9211 contain an entry for each color used by the image. */
9212 for (y = 0; y < img->height; ++y)
9213 for (x = 0; x < img->width; ++x)
9215 unsigned long pixel = XGetPixel (ximg, x, y);
9216 lookup_pixel_color (f, pixel);
9219 /* Record colors in the image. Free color table and XImage. */
9220 img->colors = colors_in_color_table (&img->ncolors);
9221 free_color_table ();
9222 XDestroyImage (ximg);
9224 #if 0 /* This doesn't seem to be the case. If we free the colors
9225 here, we get a BadAccess later in x_clear_image when
9226 freeing the colors. */
9227 /* We have allocated colors once, but Ghostscript has also
9228 allocated colors on behalf of us. So, to get the
9229 reference counts right, free them once. */
9230 if (img->ncolors)
9231 x_free_colors (f, img->colors, img->ncolors);
9232 #endif
9234 else
9235 image_error ("Cannot get X image of `%s'; colors will not be freed",
9236 img->spec, Qnil);
9238 UNBLOCK_INPUT;
9244 /***********************************************************************
9245 Window properties
9246 ***********************************************************************/
9248 DEFUN ("x-change-window-property", Fx_change_window_property,
9249 Sx_change_window_property, 2, 3, 0,
9250 "Change window property PROP to VALUE on the X window of FRAME.\n\
9251 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9252 selected frame. Value is VALUE.")
9253 (prop, value, frame)
9254 Lisp_Object frame, prop, value;
9256 struct frame *f = check_x_frame (frame);
9257 Atom prop_atom;
9259 CHECK_STRING (prop, 1);
9260 CHECK_STRING (value, 2);
9262 BLOCK_INPUT;
9263 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9264 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9265 prop_atom, XA_STRING, 8, PropModeReplace,
9266 XSTRING (value)->data, XSTRING (value)->size);
9268 /* Make sure the property is set when we return. */
9269 XFlush (FRAME_X_DISPLAY (f));
9270 UNBLOCK_INPUT;
9272 return value;
9276 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9277 Sx_delete_window_property, 1, 2, 0,
9278 "Remove window property PROP from X window of FRAME.\n\
9279 FRAME nil or omitted means use the selected frame. Value is PROP.")
9280 (prop, frame)
9281 Lisp_Object prop, frame;
9283 struct frame *f = check_x_frame (frame);
9284 Atom prop_atom;
9286 CHECK_STRING (prop, 1);
9287 BLOCK_INPUT;
9288 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9289 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9291 /* Make sure the property is removed when we return. */
9292 XFlush (FRAME_X_DISPLAY (f));
9293 UNBLOCK_INPUT;
9295 return prop;
9299 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9300 1, 2, 0,
9301 "Value is the value of window property PROP on FRAME.\n\
9302 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9303 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9304 value.")
9305 (prop, frame)
9306 Lisp_Object prop, frame;
9308 struct frame *f = check_x_frame (frame);
9309 Atom prop_atom;
9310 int rc;
9311 Lisp_Object prop_value = Qnil;
9312 char *tmp_data = NULL;
9313 Atom actual_type;
9314 int actual_format;
9315 unsigned long actual_size, bytes_remaining;
9317 CHECK_STRING (prop, 1);
9318 BLOCK_INPUT;
9319 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9320 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9321 prop_atom, 0, 0, False, XA_STRING,
9322 &actual_type, &actual_format, &actual_size,
9323 &bytes_remaining, (unsigned char **) &tmp_data);
9324 if (rc == Success)
9326 int size = bytes_remaining;
9328 XFree (tmp_data);
9329 tmp_data = NULL;
9331 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9332 prop_atom, 0, bytes_remaining,
9333 False, XA_STRING,
9334 &actual_type, &actual_format,
9335 &actual_size, &bytes_remaining,
9336 (unsigned char **) &tmp_data);
9337 if (rc == Success)
9338 prop_value = make_string (tmp_data, size);
9340 XFree (tmp_data);
9343 UNBLOCK_INPUT;
9344 return prop_value;
9349 /***********************************************************************
9350 Busy cursor
9351 ***********************************************************************/
9353 /* If non-null, an asynchronous timer that, when it expires, displays
9354 a busy cursor on all frames. */
9356 static struct atimer *busy_cursor_atimer;
9358 /* Non-zero means a busy cursor is currently shown. */
9360 static int busy_cursor_shown_p;
9362 /* Number of seconds to wait before displaying a busy cursor. */
9364 static Lisp_Object Vbusy_cursor_delay;
9366 /* Default number of seconds to wait before displaying a busy
9367 cursor. */
9369 #define DEFAULT_BUSY_CURSOR_DELAY 1
9371 /* Function prototypes. */
9373 static void show_busy_cursor P_ ((struct atimer *));
9374 static void hide_busy_cursor P_ ((void));
9377 /* Cancel a currently active busy-cursor timer, and start a new one. */
9379 void
9380 start_busy_cursor ()
9382 EMACS_TIME delay;
9383 int secs, usecs = 0;
9385 cancel_busy_cursor ();
9387 if (INTEGERP (Vbusy_cursor_delay)
9388 && XINT (Vbusy_cursor_delay) > 0)
9389 secs = XFASTINT (Vbusy_cursor_delay);
9390 else if (FLOATP (Vbusy_cursor_delay)
9391 && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
9393 Lisp_Object tem;
9394 tem = Ftruncate (Vbusy_cursor_delay, Qnil);
9395 secs = XFASTINT (tem);
9396 usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
9398 else
9399 secs = DEFAULT_BUSY_CURSOR_DELAY;
9401 EMACS_SET_SECS_USECS (delay, secs, usecs);
9402 busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
9403 show_busy_cursor, NULL);
9407 /* Cancel the busy cursor timer if active, hide a busy cursor if
9408 shown. */
9410 void
9411 cancel_busy_cursor ()
9413 if (busy_cursor_atimer)
9415 cancel_atimer (busy_cursor_atimer);
9416 busy_cursor_atimer = NULL;
9419 if (busy_cursor_shown_p)
9420 hide_busy_cursor ();
9424 /* Timer function of busy_cursor_atimer. TIMER is equal to
9425 busy_cursor_atimer.
9427 Display a busy cursor on all frames by mapping the frames'
9428 busy_window. Set the busy_p flag in the frames' output_data.x
9429 structure to indicate that a busy cursor is shown on the
9430 frames. */
9432 static void
9433 show_busy_cursor (timer)
9434 struct atimer *timer;
9436 /* The timer implementation will cancel this timer automatically
9437 after this function has run. Set busy_cursor_atimer to null
9438 so that we know the timer doesn't have to be canceled. */
9439 busy_cursor_atimer = NULL;
9441 if (!busy_cursor_shown_p)
9443 Lisp_Object rest, frame;
9445 BLOCK_INPUT;
9447 FOR_EACH_FRAME (rest, frame)
9448 if (FRAME_X_P (XFRAME (frame)))
9450 struct frame *f = XFRAME (frame);
9452 f->output_data.x->busy_p = 1;
9454 if (!f->output_data.x->busy_window)
9456 unsigned long mask = CWCursor;
9457 XSetWindowAttributes attrs;
9459 attrs.cursor = f->output_data.x->busy_cursor;
9461 f->output_data.x->busy_window
9462 = XCreateWindow (FRAME_X_DISPLAY (f),
9463 FRAME_OUTER_WINDOW (f),
9464 0, 0, 32000, 32000, 0, 0,
9465 InputOnly,
9466 CopyFromParent,
9467 mask, &attrs);
9470 XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
9471 XFlush (FRAME_X_DISPLAY (f));
9474 busy_cursor_shown_p = 1;
9475 UNBLOCK_INPUT;
9480 /* Hide the busy cursor on all frames, if it is currently shown. */
9482 static void
9483 hide_busy_cursor ()
9485 if (busy_cursor_shown_p)
9487 Lisp_Object rest, frame;
9489 BLOCK_INPUT;
9490 FOR_EACH_FRAME (rest, frame)
9492 struct frame *f = XFRAME (frame);
9494 if (FRAME_X_P (f)
9495 /* Watch out for newly created frames. */
9496 && f->output_data.x->busy_window)
9498 XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
9499 /* Sync here because XTread_socket looks at the busy_p flag
9500 that is reset to zero below. */
9501 XSync (FRAME_X_DISPLAY (f), False);
9502 f->output_data.x->busy_p = 0;
9506 busy_cursor_shown_p = 0;
9507 UNBLOCK_INPUT;
9513 /***********************************************************************
9514 Tool tips
9515 ***********************************************************************/
9517 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
9518 Lisp_Object));
9520 /* The frame of a currently visible tooltip, or null. */
9522 struct frame *tip_frame;
9524 /* If non-nil, a timer started that hides the last tooltip when it
9525 fires. */
9527 Lisp_Object tip_timer;
9528 Window tip_window;
9530 /* Create a frame for a tooltip on the display described by DPYINFO.
9531 PARMS is a list of frame parameters. Value is the frame. */
9533 static Lisp_Object
9534 x_create_tip_frame (dpyinfo, parms)
9535 struct x_display_info *dpyinfo;
9536 Lisp_Object parms;
9538 struct frame *f;
9539 Lisp_Object frame, tem;
9540 Lisp_Object name;
9541 long window_prompting = 0;
9542 int width, height;
9543 int count = specpdl_ptr - specpdl;
9544 struct gcpro gcpro1, gcpro2, gcpro3;
9545 struct kboard *kb;
9547 check_x ();
9549 /* Use this general default value to start with until we know if
9550 this frame has a specified name. */
9551 Vx_resource_name = Vinvocation_name;
9553 #ifdef MULTI_KBOARD
9554 kb = dpyinfo->kboard;
9555 #else
9556 kb = &the_only_kboard;
9557 #endif
9559 /* Get the name of the frame to use for resource lookup. */
9560 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
9561 if (!STRINGP (name)
9562 && !EQ (name, Qunbound)
9563 && !NILP (name))
9564 error ("Invalid frame name--not a string or nil");
9565 Vx_resource_name = name;
9567 frame = Qnil;
9568 GCPRO3 (parms, name, frame);
9569 tip_frame = f = make_frame (1);
9570 XSETFRAME (frame, f);
9571 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9573 f->output_method = output_x_window;
9574 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
9575 bzero (f->output_data.x, sizeof (struct x_output));
9576 f->output_data.x->icon_bitmap = -1;
9577 f->output_data.x->fontset = -1;
9578 f->icon_name = Qnil;
9579 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
9580 #ifdef MULTI_KBOARD
9581 FRAME_KBOARD (f) = kb;
9582 #endif
9583 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9584 f->output_data.x->explicit_parent = 0;
9586 /* Set the name; the functions to which we pass f expect the name to
9587 be set. */
9588 if (EQ (name, Qunbound) || NILP (name))
9590 f->name = build_string (dpyinfo->x_id_name);
9591 f->explicit_name = 0;
9593 else
9595 f->name = name;
9596 f->explicit_name = 1;
9597 /* use the frame's title when getting resources for this frame. */
9598 specbind (Qx_resource_name, name);
9601 /* Extract the window parameters from the supplied values
9602 that are needed to determine window geometry. */
9604 Lisp_Object font;
9606 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
9608 BLOCK_INPUT;
9609 /* First, try whatever font the caller has specified. */
9610 if (STRINGP (font))
9612 tem = Fquery_fontset (font, Qnil);
9613 if (STRINGP (tem))
9614 font = x_new_fontset (f, XSTRING (tem)->data);
9615 else
9616 font = x_new_font (f, XSTRING (font)->data);
9619 /* Try out a font which we hope has bold and italic variations. */
9620 if (!STRINGP (font))
9621 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9622 if (!STRINGP (font))
9623 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9624 if (! STRINGP (font))
9625 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9626 if (! STRINGP (font))
9627 /* This was formerly the first thing tried, but it finds too many fonts
9628 and takes too long. */
9629 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9630 /* If those didn't work, look for something which will at least work. */
9631 if (! STRINGP (font))
9632 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9633 UNBLOCK_INPUT;
9634 if (! STRINGP (font))
9635 font = build_string ("fixed");
9637 x_default_parameter (f, parms, Qfont, font,
9638 "font", "Font", RES_TYPE_STRING);
9641 x_default_parameter (f, parms, Qborder_width, make_number (2),
9642 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9644 /* This defaults to 2 in order to match xterm. We recognize either
9645 internalBorderWidth or internalBorder (which is what xterm calls
9646 it). */
9647 if (NILP (Fassq (Qinternal_border_width, parms)))
9649 Lisp_Object value;
9651 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
9652 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9653 if (! EQ (value, Qunbound))
9654 parms = Fcons (Fcons (Qinternal_border_width, value),
9655 parms);
9658 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9659 "internalBorderWidth", "internalBorderWidth",
9660 RES_TYPE_NUMBER);
9662 /* Also do the stuff which must be set before the window exists. */
9663 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9664 "foreground", "Foreground", RES_TYPE_STRING);
9665 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9666 "background", "Background", RES_TYPE_STRING);
9667 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9668 "pointerColor", "Foreground", RES_TYPE_STRING);
9669 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9670 "cursorColor", "Foreground", RES_TYPE_STRING);
9671 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9672 "borderColor", "BorderColor", RES_TYPE_STRING);
9674 /* Init faces before x_default_parameter is called for scroll-bar
9675 parameters because that function calls x_set_scroll_bar_width,
9676 which calls change_frame_size, which calls Fset_window_buffer,
9677 which runs hooks, which call Fvertical_motion. At the end, we
9678 end up in init_iterator with a null face cache, which should not
9679 happen. */
9680 init_frame_faces (f);
9682 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9683 window_prompting = x_figure_window_size (f, parms);
9685 if (window_prompting & XNegative)
9687 if (window_prompting & YNegative)
9688 f->output_data.x->win_gravity = SouthEastGravity;
9689 else
9690 f->output_data.x->win_gravity = NorthEastGravity;
9692 else
9694 if (window_prompting & YNegative)
9695 f->output_data.x->win_gravity = SouthWestGravity;
9696 else
9697 f->output_data.x->win_gravity = NorthWestGravity;
9700 f->output_data.x->size_hint_flags = window_prompting;
9702 XSetWindowAttributes attrs;
9703 unsigned long mask;
9705 BLOCK_INPUT;
9706 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
9707 /* Window managers look at the override-redirect flag to determine
9708 whether or net to give windows a decoration (Xlib spec, chapter
9709 3.2.8). */
9710 attrs.override_redirect = True;
9711 attrs.save_under = True;
9712 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9713 /* Arrange for getting MapNotify and UnmapNotify events. */
9714 attrs.event_mask = StructureNotifyMask;
9715 tip_window
9716 = FRAME_X_WINDOW (f)
9717 = XCreateWindow (FRAME_X_DISPLAY (f),
9718 FRAME_X_DISPLAY_INFO (f)->root_window,
9719 /* x, y, width, height */
9720 0, 0, 1, 1,
9721 /* Border. */
9723 CopyFromParent, InputOutput, CopyFromParent,
9724 mask, &attrs);
9725 UNBLOCK_INPUT;
9728 x_make_gc (f);
9730 x_default_parameter (f, parms, Qauto_raise, Qnil,
9731 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9732 x_default_parameter (f, parms, Qauto_lower, Qnil,
9733 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9734 x_default_parameter (f, parms, Qcursor_type, Qbox,
9735 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9737 /* Dimensions, especially f->height, must be done via change_frame_size.
9738 Change will not be effected unless different from the current
9739 f->height. */
9740 width = f->width;
9741 height = f->height;
9742 f->height = 0;
9743 SET_FRAME_WIDTH (f, 0);
9744 change_frame_size (f, height, width, 1, 0, 0);
9746 f->no_split = 1;
9748 UNGCPRO;
9750 /* It is now ok to make the frame official even if we get an error
9751 below. And the frame needs to be on Vframe_list or making it
9752 visible won't work. */
9753 Vframe_list = Fcons (frame, Vframe_list);
9755 /* Now that the frame is official, it counts as a reference to
9756 its display. */
9757 FRAME_X_DISPLAY_INFO (f)->reference_count++;
9759 return unbind_to (count, frame);
9763 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 4, 0,
9764 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
9765 A tooltip window is a small X window displaying STRING at\n\
9766 the current mouse position.\n\
9767 FRAME nil or omitted means use the selected frame.\n\
9768 PARMS is an optional list of frame parameters which can be\n\
9769 used to change the tooltip's appearance.\n\
9770 Automatically hide the tooltip after TIMEOUT seconds.\n\
9771 TIMEOUT nil means use the default timeout of 5 seconds.")
9772 (string, frame, parms, timeout)
9773 Lisp_Object string, frame, parms, timeout;
9775 struct frame *f;
9776 struct window *w;
9777 Window root, child;
9778 Lisp_Object buffer;
9779 struct buffer *old_buffer;
9780 struct text_pos pos;
9781 int i, width, height;
9782 int root_x, root_y, win_x, win_y;
9783 unsigned pmask;
9784 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9785 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9786 int count = specpdl_ptr - specpdl;
9788 specbind (Qinhibit_redisplay, Qt);
9790 GCPRO4 (string, parms, frame, timeout);
9792 CHECK_STRING (string, 0);
9793 f = check_x_frame (frame);
9794 if (NILP (timeout))
9795 timeout = make_number (5);
9796 else
9797 CHECK_NATNUM (timeout, 2);
9799 /* Hide a previous tip, if any. */
9800 Fx_hide_tip ();
9802 /* Add default values to frame parameters. */
9803 if (NILP (Fassq (Qname, parms)))
9804 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
9805 if (NILP (Fassq (Qinternal_border_width, parms)))
9806 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
9807 if (NILP (Fassq (Qborder_width, parms)))
9808 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
9809 if (NILP (Fassq (Qborder_color, parms)))
9810 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
9811 if (NILP (Fassq (Qbackground_color, parms)))
9812 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
9813 parms);
9815 /* Create a frame for the tooltip, and record it in the global
9816 variable tip_frame. */
9817 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
9818 tip_frame = f = XFRAME (frame);
9820 /* Set up the frame's root window. Currently we use a size of 80
9821 columns x 40 lines. If someone wants to show a larger tip, he
9822 will loose. I don't think this is a realistic case. */
9823 w = XWINDOW (FRAME_ROOT_WINDOW (f));
9824 w->left = w->top = make_number (0);
9825 w->width = make_number (80);
9826 w->height = make_number (40);
9827 adjust_glyphs (f);
9828 w->pseudo_window_p = 1;
9830 /* Display the tooltip text in a temporary buffer. */
9831 buffer = Fget_buffer_create (build_string (" *tip*"));
9832 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
9833 old_buffer = current_buffer;
9834 set_buffer_internal_1 (XBUFFER (buffer));
9835 Ferase_buffer ();
9836 Finsert (1, &string);
9837 clear_glyph_matrix (w->desired_matrix);
9838 clear_glyph_matrix (w->current_matrix);
9839 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
9840 try_window (FRAME_ROOT_WINDOW (f), pos);
9842 /* Compute width and height of the tooltip. */
9843 width = height = 0;
9844 for (i = 0; i < w->desired_matrix->nrows; ++i)
9846 struct glyph_row *row = &w->desired_matrix->rows[i];
9847 struct glyph *last;
9848 int row_width;
9850 /* Stop at the first empty row at the end. */
9851 if (!row->enabled_p || !row->displays_text_p)
9852 break;
9854 /* Let the row go over the full width of the frame. */
9855 row->full_width_p = 1;
9857 /* There's a glyph at the end of rows that is used to place
9858 the cursor there. Don't include the width of this glyph. */
9859 if (row->used[TEXT_AREA])
9861 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
9862 row_width = row->pixel_width - last->pixel_width;
9864 else
9865 row_width = row->pixel_width;
9867 height += row->height;
9868 width = max (width, row_width);
9871 /* Add the frame's internal border to the width and height the X
9872 window should have. */
9873 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9874 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9876 /* Move the tooltip window where the mouse pointer is. Resize and
9877 show it. */
9878 BLOCK_INPUT;
9879 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
9880 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
9881 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9882 root_x + 5, root_y - height - 5, width, height);
9883 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9884 UNBLOCK_INPUT;
9886 /* Draw into the window. */
9887 w->must_be_updated_p = 1;
9888 update_single_window (w, 1);
9890 /* Restore original current buffer. */
9891 set_buffer_internal_1 (old_buffer);
9892 windows_or_buffers_changed = old_windows_or_buffers_changed;
9894 /* Let the tip disappear after timeout seconds. */
9895 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
9896 intern ("x-hide-tip"));
9898 UNGCPRO;
9899 return unbind_to (count, Qnil);
9903 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
9904 "Hide the current tooltip window, if there is any.\n\
9905 Value is t is tooltip was open, nil otherwise.")
9908 int count = specpdl_ptr - specpdl;
9909 int deleted_p = 0;
9911 specbind (Qinhibit_redisplay, Qt);
9913 if (!NILP (tip_timer))
9915 call1 (intern ("cancel-timer"), tip_timer);
9916 tip_timer = Qnil;
9919 if (tip_frame)
9921 Lisp_Object frame;
9923 XSETFRAME (frame, tip_frame);
9924 Fdelete_frame (frame, Qt);
9925 tip_frame = NULL;
9926 deleted_p = 1;
9929 return unbind_to (count, deleted_p ? Qt : Qnil);
9934 /***********************************************************************
9935 File selection dialog
9936 ***********************************************************************/
9938 #ifdef USE_MOTIF
9940 /* Callback for "OK" and "Cancel" on file selection dialog. */
9942 static void
9943 file_dialog_cb (widget, client_data, call_data)
9944 Widget widget;
9945 XtPointer call_data, client_data;
9947 int *result = (int *) client_data;
9948 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
9949 *result = cb->reason;
9953 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
9954 "Read file name, prompting with PROMPT in directory DIR.\n\
9955 Use a file selection dialog.\n\
9956 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
9957 specified. Don't let the user enter a file name in the file\n\
9958 selection dialog's entry field, if MUSTMATCH is non-nil.")
9959 (prompt, dir, default_filename, mustmatch)
9960 Lisp_Object prompt, dir, default_filename, mustmatch;
9962 int result;
9963 struct frame *f = SELECTED_FRAME ();
9964 Lisp_Object file = Qnil;
9965 Widget dialog, text, list, help;
9966 Arg al[10];
9967 int ac = 0;
9968 extern XtAppContext Xt_app_con;
9969 char *title;
9970 XmString dir_xmstring, pattern_xmstring;
9971 int popup_activated_flag;
9972 int count = specpdl_ptr - specpdl;
9973 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
9975 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
9976 CHECK_STRING (prompt, 0);
9977 CHECK_STRING (dir, 1);
9979 /* Prevent redisplay. */
9980 specbind (Qinhibit_redisplay, Qt);
9982 BLOCK_INPUT;
9984 /* Create the dialog with PROMPT as title, using DIR as initial
9985 directory and using "*" as pattern. */
9986 dir = Fexpand_file_name (dir, Qnil);
9987 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
9988 pattern_xmstring = XmStringCreateLocalized ("*");
9990 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
9991 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
9992 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
9993 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
9994 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
9995 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
9996 "fsb", al, ac);
9997 XmStringFree (dir_xmstring);
9998 XmStringFree (pattern_xmstring);
10000 /* Add callbacks for OK and Cancel. */
10001 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
10002 (XtPointer) &result);
10003 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
10004 (XtPointer) &result);
10006 /* Disable the help button since we can't display help. */
10007 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
10008 XtSetSensitive (help, False);
10010 /* Mark OK button as default. */
10011 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
10012 XmNshowAsDefault, True, NULL);
10014 /* If MUSTMATCH is non-nil, disable the file entry field of the
10015 dialog, so that the user must select a file from the files list
10016 box. We can't remove it because we wouldn't have a way to get at
10017 the result file name, then. */
10018 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
10019 if (!NILP (mustmatch))
10021 Widget label;
10022 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
10023 XtSetSensitive (text, False);
10024 XtSetSensitive (label, False);
10027 /* Manage the dialog, so that list boxes get filled. */
10028 XtManageChild (dialog);
10030 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10031 must include the path for this to work. */
10032 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
10033 if (STRINGP (default_filename))
10035 XmString default_xmstring;
10036 int item_pos;
10038 default_xmstring
10039 = XmStringCreateLocalized (XSTRING (default_filename)->data);
10041 if (!XmListItemExists (list, default_xmstring))
10043 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10044 XmListAddItem (list, default_xmstring, 0);
10045 item_pos = 0;
10047 else
10048 item_pos = XmListItemPos (list, default_xmstring);
10049 XmStringFree (default_xmstring);
10051 /* Select the item and scroll it into view. */
10052 XmListSelectPos (list, item_pos, True);
10053 XmListSetPos (list, item_pos);
10056 /* Process all events until the user presses Cancel or OK. */
10057 for (result = 0; result == 0;)
10059 XEvent event;
10060 Widget widget, parent;
10062 XtAppNextEvent (Xt_app_con, &event);
10064 /* See if the receiver of the event is one of the widgets of
10065 the file selection dialog. If so, dispatch it. If not,
10066 discard it. */
10067 widget = XtWindowToWidget (event.xany.display, event.xany.window);
10068 parent = widget;
10069 while (parent && parent != dialog)
10070 parent = XtParent (parent);
10072 if (parent == dialog
10073 || (event.type == Expose
10074 && !process_expose_from_menu (event)))
10075 XtDispatchEvent (&event);
10078 /* Get the result. */
10079 if (result == XmCR_OK)
10081 XmString text;
10082 String data;
10084 XtVaGetValues (dialog, XmNtextString, &text, 0);
10085 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
10086 XmStringFree (text);
10087 file = build_string (data);
10088 XtFree (data);
10090 else
10091 file = Qnil;
10093 /* Clean up. */
10094 XtUnmanageChild (dialog);
10095 XtDestroyWidget (dialog);
10096 UNBLOCK_INPUT;
10097 UNGCPRO;
10099 /* Make "Cancel" equivalent to C-g. */
10100 if (NILP (file))
10101 Fsignal (Qquit, Qnil);
10103 return unbind_to (count, file);
10106 #endif /* USE_MOTIF */
10110 /***********************************************************************
10111 Initialization
10112 ***********************************************************************/
10114 void
10115 syms_of_xfns ()
10117 /* This is zero if not using X windows. */
10118 x_in_use = 0;
10120 /* The section below is built by the lisp expression at the top of the file,
10121 just above where these variables are declared. */
10122 /*&&& init symbols here &&&*/
10123 Qauto_raise = intern ("auto-raise");
10124 staticpro (&Qauto_raise);
10125 Qauto_lower = intern ("auto-lower");
10126 staticpro (&Qauto_lower);
10127 Qbar = intern ("bar");
10128 staticpro (&Qbar);
10129 Qborder_color = intern ("border-color");
10130 staticpro (&Qborder_color);
10131 Qborder_width = intern ("border-width");
10132 staticpro (&Qborder_width);
10133 Qbox = intern ("box");
10134 staticpro (&Qbox);
10135 Qcursor_color = intern ("cursor-color");
10136 staticpro (&Qcursor_color);
10137 Qcursor_type = intern ("cursor-type");
10138 staticpro (&Qcursor_type);
10139 Qgeometry = intern ("geometry");
10140 staticpro (&Qgeometry);
10141 Qicon_left = intern ("icon-left");
10142 staticpro (&Qicon_left);
10143 Qicon_top = intern ("icon-top");
10144 staticpro (&Qicon_top);
10145 Qicon_type = intern ("icon-type");
10146 staticpro (&Qicon_type);
10147 Qicon_name = intern ("icon-name");
10148 staticpro (&Qicon_name);
10149 Qinternal_border_width = intern ("internal-border-width");
10150 staticpro (&Qinternal_border_width);
10151 Qleft = intern ("left");
10152 staticpro (&Qleft);
10153 Qright = intern ("right");
10154 staticpro (&Qright);
10155 Qmouse_color = intern ("mouse-color");
10156 staticpro (&Qmouse_color);
10157 Qnone = intern ("none");
10158 staticpro (&Qnone);
10159 Qparent_id = intern ("parent-id");
10160 staticpro (&Qparent_id);
10161 Qscroll_bar_width = intern ("scroll-bar-width");
10162 staticpro (&Qscroll_bar_width);
10163 Qsuppress_icon = intern ("suppress-icon");
10164 staticpro (&Qsuppress_icon);
10165 Qundefined_color = intern ("undefined-color");
10166 staticpro (&Qundefined_color);
10167 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
10168 staticpro (&Qvertical_scroll_bars);
10169 Qvisibility = intern ("visibility");
10170 staticpro (&Qvisibility);
10171 Qwindow_id = intern ("window-id");
10172 staticpro (&Qwindow_id);
10173 Qouter_window_id = intern ("outer-window-id");
10174 staticpro (&Qouter_window_id);
10175 Qx_frame_parameter = intern ("x-frame-parameter");
10176 staticpro (&Qx_frame_parameter);
10177 Qx_resource_name = intern ("x-resource-name");
10178 staticpro (&Qx_resource_name);
10179 Quser_position = intern ("user-position");
10180 staticpro (&Quser_position);
10181 Quser_size = intern ("user-size");
10182 staticpro (&Quser_size);
10183 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
10184 staticpro (&Qscroll_bar_foreground);
10185 Qscroll_bar_background = intern ("scroll-bar-background");
10186 staticpro (&Qscroll_bar_background);
10187 Qscreen_gamma = intern ("screen-gamma");
10188 staticpro (&Qscreen_gamma);
10189 Qline_spacing = intern ("line-spacing");
10190 staticpro (&Qline_spacing);
10191 Qcenter = intern ("center");
10192 staticpro (&Qcenter);
10193 /* This is the end of symbol initialization. */
10195 /* Text property `display' should be nonsticky by default. */
10196 Vtext_property_default_nonsticky
10197 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10200 Qlaplace = intern ("laplace");
10201 staticpro (&Qlaplace);
10203 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10204 staticpro (&Qface_set_after_frame_default);
10206 Fput (Qundefined_color, Qerror_conditions,
10207 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10208 Fput (Qundefined_color, Qerror_message,
10209 build_string ("Undefined color"));
10211 init_x_parm_symbols ();
10213 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10214 "List of directories to search for bitmap files for X.");
10215 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
10217 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10218 "The shape of the pointer when over text.\n\
10219 Changing the value does not affect existing frames\n\
10220 unless you set the mouse color.");
10221 Vx_pointer_shape = Qnil;
10223 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
10224 "The name Emacs uses to look up X resources.\n\
10225 `x-get-resource' uses this as the first component of the instance name\n\
10226 when requesting resource values.\n\
10227 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10228 was invoked, or to the value specified with the `-name' or `-rn'\n\
10229 switches, if present.\n\
10231 It may be useful to bind this variable locally around a call\n\
10232 to `x-get-resource'. See also the variable `x-resource-class'.");
10233 Vx_resource_name = Qnil;
10235 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
10236 "The class Emacs uses to look up X resources.\n\
10237 `x-get-resource' uses this as the first component of the instance class\n\
10238 when requesting resource values.\n\
10239 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10241 Setting this variable permanently is not a reasonable thing to do,\n\
10242 but binding this variable locally around a call to `x-get-resource'\n\
10243 is a reasonable practice. See also the variable `x-resource-name'.");
10244 Vx_resource_class = build_string (EMACS_CLASS);
10246 #if 0 /* This doesn't really do anything. */
10247 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
10248 "The shape of the pointer when not over text.\n\
10249 This variable takes effect when you create a new frame\n\
10250 or when you set the mouse color.");
10251 #endif
10252 Vx_nontext_pointer_shape = Qnil;
10254 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
10255 "The shape of the pointer when Emacs is busy.\n\
10256 This variable takes effect when you create a new frame\n\
10257 or when you set the mouse color.");
10258 Vx_busy_pointer_shape = Qnil;
10260 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
10261 "Non-zero means Emacs displays a busy cursor on window systems.");
10262 display_busy_cursor_p = 1;
10264 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
10265 "*Seconds to wait before displaying a busy-cursor.\n\
10266 Value must be an integer or float.");
10267 Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
10269 #if 0 /* This doesn't really do anything. */
10270 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
10271 "The shape of the pointer when over the mode line.\n\
10272 This variable takes effect when you create a new frame\n\
10273 or when you set the mouse color.");
10274 #endif
10275 Vx_mode_pointer_shape = Qnil;
10277 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10278 &Vx_sensitive_text_pointer_shape,
10279 "The shape of the pointer when over mouse-sensitive text.\n\
10280 This variable takes effect when you create a new frame\n\
10281 or when you set the mouse color.");
10282 Vx_sensitive_text_pointer_shape = Qnil;
10284 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10285 "A string indicating the foreground color of the cursor box.");
10286 Vx_cursor_fore_pixel = Qnil;
10288 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10289 "Non-nil if no X window manager is in use.\n\
10290 Emacs doesn't try to figure this out; this is always nil\n\
10291 unless you set it to something else.");
10292 /* We don't have any way to find this out, so set it to nil
10293 and maybe the user would like to set it to t. */
10294 Vx_no_window_manager = Qnil;
10296 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10297 &Vx_pixel_size_width_font_regexp,
10298 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10300 Since Emacs gets width of a font matching with this regexp from\n\
10301 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10302 such a font. This is especially effective for such large fonts as\n\
10303 Chinese, Japanese, and Korean.");
10304 Vx_pixel_size_width_font_regexp = Qnil;
10306 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10307 "Time after which cached images are removed from the cache.\n\
10308 When an image has not been displayed this many seconds, remove it\n\
10309 from the image cache. Value must be an integer or nil with nil\n\
10310 meaning don't clear the cache.");
10311 Vimage_cache_eviction_delay = make_number (30 * 60);
10313 #ifdef USE_X_TOOLKIT
10314 Fprovide (intern ("x-toolkit"));
10315 #endif
10316 #ifdef USE_MOTIF
10317 Fprovide (intern ("motif"));
10318 #endif
10320 defsubr (&Sx_get_resource);
10322 /* X window properties. */
10323 defsubr (&Sx_change_window_property);
10324 defsubr (&Sx_delete_window_property);
10325 defsubr (&Sx_window_property);
10327 defsubr (&Sxw_display_color_p);
10328 defsubr (&Sx_display_grayscale_p);
10329 defsubr (&Sxw_color_defined_p);
10330 defsubr (&Sxw_color_values);
10331 defsubr (&Sx_server_max_request_size);
10332 defsubr (&Sx_server_vendor);
10333 defsubr (&Sx_server_version);
10334 defsubr (&Sx_display_pixel_width);
10335 defsubr (&Sx_display_pixel_height);
10336 defsubr (&Sx_display_mm_width);
10337 defsubr (&Sx_display_mm_height);
10338 defsubr (&Sx_display_screens);
10339 defsubr (&Sx_display_planes);
10340 defsubr (&Sx_display_color_cells);
10341 defsubr (&Sx_display_visual_class);
10342 defsubr (&Sx_display_backing_store);
10343 defsubr (&Sx_display_save_under);
10344 defsubr (&Sx_parse_geometry);
10345 defsubr (&Sx_create_frame);
10346 defsubr (&Sx_open_connection);
10347 defsubr (&Sx_close_connection);
10348 defsubr (&Sx_display_list);
10349 defsubr (&Sx_synchronize);
10350 defsubr (&Sx_focus_frame);
10352 /* Setting callback functions for fontset handler. */
10353 get_font_info_func = x_get_font_info;
10355 #if 0 /* This function pointer doesn't seem to be used anywhere.
10356 And the pointer assigned has the wrong type, anyway. */
10357 list_fonts_func = x_list_fonts;
10358 #endif
10360 load_font_func = x_load_font;
10361 find_ccl_program_func = x_find_ccl_program;
10362 query_font_func = x_query_font;
10363 set_frame_fontset_func = x_set_font;
10364 check_window_system_func = check_x;
10366 /* Images. */
10367 Qxbm = intern ("xbm");
10368 staticpro (&Qxbm);
10369 QCtype = intern (":type");
10370 staticpro (&QCtype);
10371 QCalgorithm = intern (":algorithm");
10372 staticpro (&QCalgorithm);
10373 QCheuristic_mask = intern (":heuristic-mask");
10374 staticpro (&QCheuristic_mask);
10375 QCcolor_symbols = intern (":color-symbols");
10376 staticpro (&QCcolor_symbols);
10377 QCascent = intern (":ascent");
10378 staticpro (&QCascent);
10379 QCmargin = intern (":margin");
10380 staticpro (&QCmargin);
10381 QCrelief = intern (":relief");
10382 staticpro (&QCrelief);
10383 Qpostscript = intern ("postscript");
10384 staticpro (&Qpostscript);
10385 QCloader = intern (":loader");
10386 staticpro (&QCloader);
10387 QCbounding_box = intern (":bounding-box");
10388 staticpro (&QCbounding_box);
10389 QCpt_width = intern (":pt-width");
10390 staticpro (&QCpt_width);
10391 QCpt_height = intern (":pt-height");
10392 staticpro (&QCpt_height);
10393 QCindex = intern (":index");
10394 staticpro (&QCindex);
10395 Qpbm = intern ("pbm");
10396 staticpro (&Qpbm);
10398 #if HAVE_XPM
10399 Qxpm = intern ("xpm");
10400 staticpro (&Qxpm);
10401 #endif
10403 #if HAVE_JPEG
10404 Qjpeg = intern ("jpeg");
10405 staticpro (&Qjpeg);
10406 #endif
10408 #if HAVE_TIFF
10409 Qtiff = intern ("tiff");
10410 staticpro (&Qtiff);
10411 #endif
10413 #if HAVE_GIF
10414 Qgif = intern ("gif");
10415 staticpro (&Qgif);
10416 #endif
10418 #if HAVE_PNG
10419 Qpng = intern ("png");
10420 staticpro (&Qpng);
10421 #endif
10423 defsubr (&Sclear_image_cache);
10425 busy_cursor_atimer = NULL;
10426 busy_cursor_shown_p = 0;
10428 defsubr (&Sx_show_tip);
10429 defsubr (&Sx_hide_tip);
10430 staticpro (&tip_timer);
10431 tip_timer = Qnil;
10433 #ifdef USE_MOTIF
10434 defsubr (&Sx_file_dialog);
10435 #endif
10439 void
10440 init_xfns ()
10442 image_types = NULL;
10443 Vimage_types = Qnil;
10445 define_image_type (&xbm_type);
10446 define_image_type (&gs_type);
10447 define_image_type (&pbm_type);
10449 #if HAVE_XPM
10450 define_image_type (&xpm_type);
10451 #endif
10453 #if HAVE_JPEG
10454 define_image_type (&jpeg_type);
10455 #endif
10457 #if HAVE_TIFF
10458 define_image_type (&tiff_type);
10459 #endif
10461 #if HAVE_GIF
10462 define_image_type (&gif_type);
10463 #endif
10465 #if HAVE_PNG
10466 define_image_type (&png_type);
10467 #endif
10470 #endif /* HAVE_X_WINDOWS */