(cvs-menu): Don't move point. Use popup-menu.
[emacs.git] / src / xfns.c
blobea7f3a0625295c6900d587aad528e58766d6c9d2
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
31 #include "lisp.h"
32 #include "xterm.h"
33 #include "frame.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "intervals.h"
37 #include "dispextern.h"
38 #include "keyboard.h"
39 #include "blockinput.h"
40 #include <epaths.h>
41 #include "charset.h"
42 #include "coding.h"
43 #include "fontset.h"
44 #include "systime.h"
45 #include "termhooks.h"
46 #include "atimer.h"
48 #ifdef HAVE_X_WINDOWS
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
54 #ifndef VMS
55 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
56 #include "bitmaps/gray.xbm"
57 #else
58 #include <X11/bitmaps/gray>
59 #endif
60 #else
61 #include "[.bitmaps]gray.xbm"
62 #endif
64 #ifdef USE_X_TOOLKIT
65 #include <X11/Shell.h>
67 #ifndef USE_MOTIF
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* USE_MOTIF */
72 #ifdef USG
73 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
74 #include <X11/Xos.h>
75 #define USG
76 #else
77 #include <X11/Xos.h>
78 #endif
80 #include "widget.h"
82 #include "../lwlib/lwlib.h"
84 #ifdef USE_MOTIF
85 #include <Xm/Xm.h>
86 #include <Xm/DialogS.h>
87 #include <Xm/FileSB.h>
88 #endif
90 /* Do the EDITRES protocol if running X11R5
91 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
93 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
94 #define HACK_EDITRES
95 extern void _XEditResCheckMessages ();
96 #endif /* R5 + Athena */
98 /* Unique id counter for widgets created by the Lucid Widget Library. */
100 extern LWLIB_ID widget_id_tick;
102 #ifdef USE_LUCID
103 /* This is part of a kludge--see lwlib/xlwmenu.c. */
104 extern XFontStruct *xlwmenu_default_font;
105 #endif
107 extern void free_frame_menubar ();
108 extern double atof ();
110 #endif /* USE_X_TOOLKIT */
112 #define min(a,b) ((a) < (b) ? (a) : (b))
113 #define max(a,b) ((a) > (b) ? (a) : (b))
115 #ifdef HAVE_X11R4
116 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
117 #else
118 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
119 #endif
121 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
122 it, and including `bitmaps/gray' more than once is a problem when
123 config.h defines `static' as an empty replacement string. */
125 int gray_bitmap_width = gray_width;
126 int gray_bitmap_height = gray_height;
127 unsigned char *gray_bitmap_bits = gray_bits;
129 /* The name we're using in resource queries. Most often "emacs". */
131 Lisp_Object Vx_resource_name;
133 /* The application class we're using in resource queries.
134 Normally "Emacs". */
136 Lisp_Object Vx_resource_class;
138 /* Non-zero means we're allowed to display a busy cursor. */
140 int display_busy_cursor_p;
142 /* The background and shape of the mouse pointer, and shape when not
143 over text or in the modeline. */
145 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
146 Lisp_Object Vx_busy_pointer_shape;
148 /* The shape when over mouse-sensitive text. */
150 Lisp_Object Vx_sensitive_text_pointer_shape;
152 /* Color of chars displayed in cursor box. */
154 Lisp_Object Vx_cursor_fore_pixel;
156 /* Nonzero if using X. */
158 static int x_in_use;
160 /* Non nil if no window manager is in use. */
162 Lisp_Object Vx_no_window_manager;
164 /* Search path for bitmap files. */
166 Lisp_Object Vx_bitmap_file_path;
168 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
170 Lisp_Object Vx_pixel_size_width_font_regexp;
172 /* Evaluate this expression to rebuild the section of syms_of_xfns
173 that initializes and staticpros the symbols declared below. Note
174 that Emacs 18 has a bug that keeps C-x C-e from being able to
175 evaluate this expression.
177 (progn
178 ;; Accumulate a list of the symbols we want to initialize from the
179 ;; declarations at the top of the file.
180 (goto-char (point-min))
181 (search-forward "/\*&&& symbols declared here &&&*\/\n")
182 (let (symbol-list)
183 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
184 (setq symbol-list
185 (cons (buffer-substring (match-beginning 1) (match-end 1))
186 symbol-list))
187 (forward-line 1))
188 (setq symbol-list (nreverse symbol-list))
189 ;; Delete the section of syms_of_... where we initialize the symbols.
190 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
191 (let ((start (point)))
192 (while (looking-at "^ Q")
193 (forward-line 2))
194 (kill-region start (point)))
195 ;; Write a new symbol initialization section.
196 (while symbol-list
197 (insert (format " %s = intern (\"" (car symbol-list)))
198 (let ((start (point)))
199 (insert (substring (car symbol-list) 1))
200 (subst-char-in-region start (point) ?_ ?-))
201 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
202 (setq symbol-list (cdr symbol-list)))))
206 /*&&& symbols declared here &&&*/
207 Lisp_Object Qauto_raise;
208 Lisp_Object Qauto_lower;
209 Lisp_Object Qbar;
210 Lisp_Object Qborder_color;
211 Lisp_Object Qborder_width;
212 Lisp_Object Qbox;
213 Lisp_Object Qcursor_color;
214 Lisp_Object Qcursor_type;
215 Lisp_Object Qgeometry;
216 Lisp_Object Qicon_left;
217 Lisp_Object Qicon_top;
218 Lisp_Object Qicon_type;
219 Lisp_Object Qicon_name;
220 Lisp_Object Qinternal_border_width;
221 Lisp_Object Qleft;
222 Lisp_Object Qright;
223 Lisp_Object Qmouse_color;
224 Lisp_Object Qnone;
225 Lisp_Object Qouter_window_id;
226 Lisp_Object Qparent_id;
227 Lisp_Object Qscroll_bar_width;
228 Lisp_Object Qsuppress_icon;
229 extern Lisp_Object Qtop;
230 Lisp_Object Qundefined_color;
231 Lisp_Object Qvertical_scroll_bars;
232 Lisp_Object Qvisibility;
233 Lisp_Object Qwindow_id;
234 Lisp_Object Qx_frame_parameter;
235 Lisp_Object Qx_resource_name;
236 Lisp_Object Quser_position;
237 Lisp_Object Quser_size;
238 extern Lisp_Object Qdisplay;
239 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
240 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
241 Lisp_Object Qcompound_text;
243 /* The below are defined in frame.c. */
245 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
246 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
247 extern Lisp_Object Qtool_bar_lines;
249 extern Lisp_Object Vwindow_system_version;
251 Lisp_Object Qface_set_after_frame_default;
254 /* Error if we are not connected to X. */
256 void
257 check_x ()
259 if (! x_in_use)
260 error ("X windows are not in use or not initialized");
263 /* Nonzero if we can use mouse menus.
264 You should not call this unless HAVE_MENUS is defined. */
267 have_menus_p ()
269 return x_in_use;
272 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
273 and checking validity for X. */
275 FRAME_PTR
276 check_x_frame (frame)
277 Lisp_Object frame;
279 FRAME_PTR f;
281 if (NILP (frame))
282 frame = selected_frame;
283 CHECK_LIVE_FRAME (frame, 0);
284 f = XFRAME (frame);
285 if (! FRAME_X_P (f))
286 error ("Non-X frame used");
287 return f;
290 /* Let the user specify an X display with a frame.
291 nil stands for the selected frame--or, if that is not an X frame,
292 the first X display on the list. */
294 static struct x_display_info *
295 check_x_display_info (frame)
296 Lisp_Object frame;
298 if (NILP (frame))
300 struct frame *sf = XFRAME (selected_frame);
302 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
303 return FRAME_X_DISPLAY_INFO (sf);
304 else if (x_display_list != 0)
305 return x_display_list;
306 else
307 error ("X windows are not in use or not initialized");
309 else if (STRINGP (frame))
310 return x_display_info_for_name (frame);
311 else
313 FRAME_PTR f;
315 CHECK_LIVE_FRAME (frame, 0);
316 f = XFRAME (frame);
317 if (! FRAME_X_P (f))
318 error ("Non-X frame used");
319 return FRAME_X_DISPLAY_INFO (f);
324 /* Return the Emacs frame-object corresponding to an X window.
325 It could be the frame's main window or an icon window. */
327 /* This function can be called during GC, so use GC_xxx type test macros. */
329 struct frame *
330 x_window_to_frame (dpyinfo, wdesc)
331 struct x_display_info *dpyinfo;
332 int wdesc;
334 Lisp_Object tail, frame;
335 struct frame *f;
337 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
339 frame = XCAR (tail);
340 if (!GC_FRAMEP (frame))
341 continue;
342 f = XFRAME (frame);
343 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
344 continue;
345 if (f->output_data.x->busy_window == wdesc)
346 return f;
347 #ifdef USE_X_TOOLKIT
348 if ((f->output_data.x->edit_widget
349 && XtWindow (f->output_data.x->edit_widget) == wdesc)
350 /* A tooltip frame? */
351 || (!f->output_data.x->edit_widget
352 && FRAME_X_WINDOW (f) == wdesc)
353 || f->output_data.x->icon_desc == wdesc)
354 return f;
355 #else /* not USE_X_TOOLKIT */
356 if (FRAME_X_WINDOW (f) == wdesc
357 || f->output_data.x->icon_desc == wdesc)
358 return f;
359 #endif /* not USE_X_TOOLKIT */
361 return 0;
364 #ifdef USE_X_TOOLKIT
365 /* Like x_window_to_frame but also compares the window with the widget's
366 windows. */
368 struct frame *
369 x_any_window_to_frame (dpyinfo, wdesc)
370 struct x_display_info *dpyinfo;
371 int wdesc;
373 Lisp_Object tail, frame;
374 struct frame *f, *found;
375 struct x_output *x;
377 found = NULL;
378 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
380 frame = XCAR (tail);
381 if (!GC_FRAMEP (frame))
382 continue;
384 f = XFRAME (frame);
385 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
387 /* This frame matches if the window is any of its widgets. */
388 x = f->output_data.x;
389 if (x->busy_window == wdesc)
390 found = f;
391 else if (x->widget)
393 if (wdesc == XtWindow (x->widget)
394 || wdesc == XtWindow (x->column_widget)
395 || wdesc == XtWindow (x->edit_widget))
396 found = f;
397 /* Match if the window is this frame's menubar. */
398 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
399 found = f;
401 else if (FRAME_X_WINDOW (f) == wdesc)
402 /* A tooltip frame. */
403 found = f;
407 return found;
410 /* Likewise, but exclude the menu bar widget. */
412 struct frame *
413 x_non_menubar_window_to_frame (dpyinfo, wdesc)
414 struct x_display_info *dpyinfo;
415 int wdesc;
417 Lisp_Object tail, frame;
418 struct frame *f;
419 struct x_output *x;
421 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
423 frame = XCAR (tail);
424 if (!GC_FRAMEP (frame))
425 continue;
426 f = XFRAME (frame);
427 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
428 continue;
429 x = f->output_data.x;
430 /* This frame matches if the window is any of its widgets. */
431 if (x->busy_window == wdesc)
432 return f;
433 else if (x->widget)
435 if (wdesc == XtWindow (x->widget)
436 || wdesc == XtWindow (x->column_widget)
437 || wdesc == XtWindow (x->edit_widget))
438 return f;
440 else if (FRAME_X_WINDOW (f) == wdesc)
441 /* A tooltip frame. */
442 return f;
444 return 0;
447 /* Likewise, but consider only the menu bar widget. */
449 struct frame *
450 x_menubar_window_to_frame (dpyinfo, wdesc)
451 struct x_display_info *dpyinfo;
452 int wdesc;
454 Lisp_Object tail, frame;
455 struct frame *f;
456 struct x_output *x;
458 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
460 frame = XCAR (tail);
461 if (!GC_FRAMEP (frame))
462 continue;
463 f = XFRAME (frame);
464 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
465 continue;
466 x = f->output_data.x;
467 /* Match if the window is this frame's menubar. */
468 if (x->menubar_widget
469 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
470 return f;
472 return 0;
475 /* Return the frame whose principal (outermost) window is WDESC.
476 If WDESC is some other (smaller) window, we return 0. */
478 struct frame *
479 x_top_window_to_frame (dpyinfo, wdesc)
480 struct x_display_info *dpyinfo;
481 int wdesc;
483 Lisp_Object tail, frame;
484 struct frame *f;
485 struct x_output *x;
487 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
489 frame = XCAR (tail);
490 if (!GC_FRAMEP (frame))
491 continue;
492 f = XFRAME (frame);
493 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
494 continue;
495 x = f->output_data.x;
497 if (x->widget)
499 /* This frame matches if the window is its topmost widget. */
500 if (wdesc == XtWindow (x->widget))
501 return f;
502 #if 0 /* I don't know why it did this,
503 but it seems logically wrong,
504 and it causes trouble for MapNotify events. */
505 /* Match if the window is this frame's menubar. */
506 if (x->menubar_widget
507 && wdesc == XtWindow (x->menubar_widget))
508 return f;
509 #endif
511 else if (FRAME_X_WINDOW (f) == wdesc)
512 /* Tooltip frame. */
513 return f;
515 return 0;
517 #endif /* USE_X_TOOLKIT */
521 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
522 id, which is just an int that this section returns. Bitmaps are
523 reference counted so they can be shared among frames.
525 Bitmap indices are guaranteed to be > 0, so a negative number can
526 be used to indicate no bitmap.
528 If you use x_create_bitmap_from_data, then you must keep track of
529 the bitmaps yourself. That is, creating a bitmap from the same
530 data more than once will not be caught. */
533 /* Functions to access the contents of a bitmap, given an id. */
536 x_bitmap_height (f, id)
537 FRAME_PTR f;
538 int id;
540 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
544 x_bitmap_width (f, id)
545 FRAME_PTR f;
546 int id;
548 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
552 x_bitmap_pixmap (f, id)
553 FRAME_PTR f;
554 int id;
556 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
560 /* Allocate a new bitmap record. Returns index of new record. */
562 static int
563 x_allocate_bitmap_record (f)
564 FRAME_PTR f;
566 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
567 int i;
569 if (dpyinfo->bitmaps == NULL)
571 dpyinfo->bitmaps_size = 10;
572 dpyinfo->bitmaps
573 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
574 dpyinfo->bitmaps_last = 1;
575 return 1;
578 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
579 return ++dpyinfo->bitmaps_last;
581 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
582 if (dpyinfo->bitmaps[i].refcount == 0)
583 return i + 1;
585 dpyinfo->bitmaps_size *= 2;
586 dpyinfo->bitmaps
587 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
588 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
589 return ++dpyinfo->bitmaps_last;
592 /* Add one reference to the reference count of the bitmap with id ID. */
594 void
595 x_reference_bitmap (f, id)
596 FRAME_PTR f;
597 int id;
599 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
602 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
605 x_create_bitmap_from_data (f, bits, width, height)
606 struct frame *f;
607 char *bits;
608 unsigned int width, height;
610 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
611 Pixmap bitmap;
612 int id;
614 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
615 bits, width, height);
617 if (! bitmap)
618 return -1;
620 id = x_allocate_bitmap_record (f);
621 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
622 dpyinfo->bitmaps[id - 1].file = NULL;
623 dpyinfo->bitmaps[id - 1].refcount = 1;
624 dpyinfo->bitmaps[id - 1].depth = 1;
625 dpyinfo->bitmaps[id - 1].height = height;
626 dpyinfo->bitmaps[id - 1].width = width;
628 return id;
631 /* Create bitmap from file FILE for frame F. */
634 x_create_bitmap_from_file (f, file)
635 struct frame *f;
636 Lisp_Object file;
638 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
639 unsigned int width, height;
640 Pixmap bitmap;
641 int xhot, yhot, result, id;
642 Lisp_Object found;
643 int fd;
644 char *filename;
646 /* Look for an existing bitmap with the same name. */
647 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
649 if (dpyinfo->bitmaps[id].refcount
650 && dpyinfo->bitmaps[id].file
651 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
653 ++dpyinfo->bitmaps[id].refcount;
654 return id + 1;
658 /* Search bitmap-file-path for the file, if appropriate. */
659 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
660 if (fd < 0)
661 return -1;
662 /* XReadBitmapFile won't handle magic file names. */
663 if (fd == 0)
664 return -1;
665 emacs_close (fd);
667 filename = (char *) XSTRING (found)->data;
669 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
670 filename, &width, &height, &bitmap, &xhot, &yhot);
671 if (result != BitmapSuccess)
672 return -1;
674 id = x_allocate_bitmap_record (f);
675 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
676 dpyinfo->bitmaps[id - 1].refcount = 1;
677 dpyinfo->bitmaps[id - 1].file
678 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
679 dpyinfo->bitmaps[id - 1].depth = 1;
680 dpyinfo->bitmaps[id - 1].height = height;
681 dpyinfo->bitmaps[id - 1].width = width;
682 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
684 return id;
687 /* Remove reference to bitmap with id number ID. */
689 void
690 x_destroy_bitmap (f, id)
691 FRAME_PTR f;
692 int id;
694 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
696 if (id > 0)
698 --dpyinfo->bitmaps[id - 1].refcount;
699 if (dpyinfo->bitmaps[id - 1].refcount == 0)
701 BLOCK_INPUT;
702 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
703 if (dpyinfo->bitmaps[id - 1].file)
705 xfree (dpyinfo->bitmaps[id - 1].file);
706 dpyinfo->bitmaps[id - 1].file = NULL;
708 UNBLOCK_INPUT;
713 /* Free all the bitmaps for the display specified by DPYINFO. */
715 static void
716 x_destroy_all_bitmaps (dpyinfo)
717 struct x_display_info *dpyinfo;
719 int i;
720 for (i = 0; i < dpyinfo->bitmaps_last; i++)
721 if (dpyinfo->bitmaps[i].refcount > 0)
723 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
724 if (dpyinfo->bitmaps[i].file)
725 xfree (dpyinfo->bitmaps[i].file);
727 dpyinfo->bitmaps_last = 0;
730 /* Connect the frame-parameter names for X frames
731 to the ways of passing the parameter values to the window system.
733 The name of a parameter, as a Lisp symbol,
734 has an `x-frame-parameter' property which is an integer in Lisp
735 that is an index in this table. */
737 struct x_frame_parm_table
739 char *name;
740 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 static void x_create_im P_ ((struct frame *));
744 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
745 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
746 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
749 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
750 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
751 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
752 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
755 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
756 Lisp_Object));
757 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
758 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
759 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
760 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
761 Lisp_Object));
762 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
763 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
764 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
765 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
766 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
767 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
768 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
769 Lisp_Object));
770 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
771 Lisp_Object));
772 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
773 Lisp_Object,
774 Lisp_Object,
775 char *, char *,
776 int));
777 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
779 static struct x_frame_parm_table x_frame_parms[] =
781 "auto-raise", x_set_autoraise,
782 "auto-lower", x_set_autolower,
783 "background-color", x_set_background_color,
784 "border-color", x_set_border_color,
785 "border-width", x_set_border_width,
786 "cursor-color", x_set_cursor_color,
787 "cursor-type", x_set_cursor_type,
788 "font", x_set_font,
789 "foreground-color", x_set_foreground_color,
790 "icon-name", x_set_icon_name,
791 "icon-type", x_set_icon_type,
792 "internal-border-width", x_set_internal_border_width,
793 "menu-bar-lines", x_set_menu_bar_lines,
794 "mouse-color", x_set_mouse_color,
795 "name", x_explicitly_set_name,
796 "scroll-bar-width", x_set_scroll_bar_width,
797 "title", x_set_title,
798 "unsplittable", x_set_unsplittable,
799 "vertical-scroll-bars", x_set_vertical_scroll_bars,
800 "visibility", x_set_visibility,
801 "tool-bar-lines", x_set_tool_bar_lines,
802 "scroll-bar-foreground", x_set_scroll_bar_foreground,
803 "scroll-bar-background", x_set_scroll_bar_background,
804 "screen-gamma", x_set_screen_gamma,
805 "line-spacing", x_set_line_spacing
808 /* Attach the `x-frame-parameter' properties to
809 the Lisp symbol names of parameters relevant to X. */
811 void
812 init_x_parm_symbols ()
814 int i;
816 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
817 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
818 make_number (i));
821 /* Change the parameters of frame F as specified by ALIST.
822 If a parameter is not specially recognized, do nothing special;
823 otherwise call the `x_set_...' function for that parameter.
824 Except for certain geometry properties, always call store_frame_param
825 to store the new value in the parameter alist. */
827 void
828 x_set_frame_parameters (f, alist)
829 FRAME_PTR f;
830 Lisp_Object alist;
832 Lisp_Object tail;
834 /* If both of these parameters are present, it's more efficient to
835 set them both at once. So we wait until we've looked at the
836 entire list before we set them. */
837 int width, height;
839 /* Same here. */
840 Lisp_Object left, top;
842 /* Same with these. */
843 Lisp_Object icon_left, icon_top;
845 /* Record in these vectors all the parms specified. */
846 Lisp_Object *parms;
847 Lisp_Object *values;
848 int i, p;
849 int left_no_change = 0, top_no_change = 0;
850 int icon_left_no_change = 0, icon_top_no_change = 0;
852 struct gcpro gcpro1, gcpro2;
854 i = 0;
855 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
856 i++;
858 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
859 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
861 /* Extract parm names and values into those vectors. */
863 i = 0;
864 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
866 Lisp_Object elt;
868 elt = Fcar (tail);
869 parms[i] = Fcar (elt);
870 values[i] = Fcdr (elt);
871 i++;
873 /* TAIL and ALIST are not used again below here. */
874 alist = tail = Qnil;
876 GCPRO2 (*parms, *values);
877 gcpro1.nvars = i;
878 gcpro2.nvars = i;
880 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
881 because their values appear in VALUES and strings are not valid. */
882 top = left = Qunbound;
883 icon_left = icon_top = Qunbound;
885 /* Provide default values for HEIGHT and WIDTH. */
886 if (FRAME_NEW_WIDTH (f))
887 width = FRAME_NEW_WIDTH (f);
888 else
889 width = FRAME_WIDTH (f);
891 if (FRAME_NEW_HEIGHT (f))
892 height = FRAME_NEW_HEIGHT (f);
893 else
894 height = FRAME_HEIGHT (f);
896 /* Process foreground_color and background_color before anything else.
897 They are independent of other properties, but other properties (e.g.,
898 cursor_color) are dependent upon them. */
899 for (p = 0; p < i; p++)
901 Lisp_Object prop, val;
903 prop = parms[p];
904 val = values[p];
905 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
907 register Lisp_Object param_index, old_value;
909 param_index = Fget (prop, Qx_frame_parameter);
910 old_value = get_frame_param (f, prop);
911 store_frame_param (f, prop, val);
912 if (NATNUMP (param_index)
913 && (XFASTINT (param_index)
914 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
915 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
919 /* Now process them in reverse of specified order. */
920 for (i--; i >= 0; i--)
922 Lisp_Object prop, val;
924 prop = parms[i];
925 val = values[i];
927 if (EQ (prop, Qwidth) && NUMBERP (val))
928 width = XFASTINT (val);
929 else if (EQ (prop, Qheight) && NUMBERP (val))
930 height = XFASTINT (val);
931 else if (EQ (prop, Qtop))
932 top = val;
933 else if (EQ (prop, Qleft))
934 left = val;
935 else if (EQ (prop, Qicon_top))
936 icon_top = val;
937 else if (EQ (prop, Qicon_left))
938 icon_left = val;
939 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
940 /* Processed above. */
941 continue;
942 else
944 register Lisp_Object param_index, old_value;
946 param_index = Fget (prop, Qx_frame_parameter);
947 old_value = get_frame_param (f, prop);
948 store_frame_param (f, prop, val);
949 if (NATNUMP (param_index)
950 && (XFASTINT (param_index)
951 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
952 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
956 /* Don't die if just one of these was set. */
957 if (EQ (left, Qunbound))
959 left_no_change = 1;
960 if (f->output_data.x->left_pos < 0)
961 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
962 else
963 XSETINT (left, f->output_data.x->left_pos);
965 if (EQ (top, Qunbound))
967 top_no_change = 1;
968 if (f->output_data.x->top_pos < 0)
969 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
970 else
971 XSETINT (top, f->output_data.x->top_pos);
974 /* If one of the icon positions was not set, preserve or default it. */
975 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
977 icon_left_no_change = 1;
978 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
979 if (NILP (icon_left))
980 XSETINT (icon_left, 0);
982 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
984 icon_top_no_change = 1;
985 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
986 if (NILP (icon_top))
987 XSETINT (icon_top, 0);
990 /* Don't set these parameters unless they've been explicitly
991 specified. The window might be mapped or resized while we're in
992 this function, and we don't want to override that unless the lisp
993 code has asked for it.
995 Don't set these parameters unless they actually differ from the
996 window's current parameters; the window may not actually exist
997 yet. */
999 Lisp_Object frame;
1001 check_frame_size (f, &height, &width);
1003 XSETFRAME (frame, f);
1005 if (width != FRAME_WIDTH (f)
1006 || height != FRAME_HEIGHT (f)
1007 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1008 Fset_frame_size (frame, make_number (width), make_number (height));
1010 if ((!NILP (left) || !NILP (top))
1011 && ! (left_no_change && top_no_change)
1012 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1013 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1015 int leftpos = 0;
1016 int toppos = 0;
1018 /* Record the signs. */
1019 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1020 if (EQ (left, Qminus))
1021 f->output_data.x->size_hint_flags |= XNegative;
1022 else if (INTEGERP (left))
1024 leftpos = XINT (left);
1025 if (leftpos < 0)
1026 f->output_data.x->size_hint_flags |= XNegative;
1028 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1029 && CONSP (XCDR (left))
1030 && INTEGERP (XCAR (XCDR (left))))
1032 leftpos = - XINT (XCAR (XCDR (left)));
1033 f->output_data.x->size_hint_flags |= XNegative;
1035 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1036 && CONSP (XCDR (left))
1037 && INTEGERP (XCAR (XCDR (left))))
1039 leftpos = XINT (XCAR (XCDR (left)));
1042 if (EQ (top, Qminus))
1043 f->output_data.x->size_hint_flags |= YNegative;
1044 else if (INTEGERP (top))
1046 toppos = XINT (top);
1047 if (toppos < 0)
1048 f->output_data.x->size_hint_flags |= YNegative;
1050 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1051 && CONSP (XCDR (top))
1052 && INTEGERP (XCAR (XCDR (top))))
1054 toppos = - XINT (XCAR (XCDR (top)));
1055 f->output_data.x->size_hint_flags |= YNegative;
1057 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1058 && CONSP (XCDR (top))
1059 && INTEGERP (XCAR (XCDR (top))))
1061 toppos = XINT (XCAR (XCDR (top)));
1065 /* Store the numeric value of the position. */
1066 f->output_data.x->top_pos = toppos;
1067 f->output_data.x->left_pos = leftpos;
1069 f->output_data.x->win_gravity = NorthWestGravity;
1071 /* Actually set that position, and convert to absolute. */
1072 x_set_offset (f, leftpos, toppos, -1);
1075 if ((!NILP (icon_left) || !NILP (icon_top))
1076 && ! (icon_left_no_change && icon_top_no_change))
1077 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1080 UNGCPRO;
1083 /* Store the screen positions of frame F into XPTR and YPTR.
1084 These are the positions of the containing window manager window,
1085 not Emacs's own window. */
1087 void
1088 x_real_positions (f, xptr, yptr)
1089 FRAME_PTR f;
1090 int *xptr, *yptr;
1092 int win_x, win_y;
1093 Window child;
1095 /* This is pretty gross, but seems to be the easiest way out of
1096 the problem that arises when restarting window-managers. */
1098 #ifdef USE_X_TOOLKIT
1099 Window outer = (f->output_data.x->widget
1100 ? XtWindow (f->output_data.x->widget)
1101 : FRAME_X_WINDOW (f));
1102 #else
1103 Window outer = f->output_data.x->window_desc;
1104 #endif
1105 Window tmp_root_window;
1106 Window *tmp_children;
1107 unsigned int tmp_nchildren;
1109 while (1)
1111 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1112 Window outer_window;
1114 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1115 &f->output_data.x->parent_desc,
1116 &tmp_children, &tmp_nchildren);
1117 XFree ((char *) tmp_children);
1119 win_x = win_y = 0;
1121 /* Find the position of the outside upper-left corner of
1122 the inner window, with respect to the outer window. */
1123 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1124 outer_window = f->output_data.x->parent_desc;
1125 else
1126 outer_window = outer;
1128 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1130 /* From-window, to-window. */
1131 outer_window,
1132 FRAME_X_DISPLAY_INFO (f)->root_window,
1134 /* From-position, to-position. */
1135 0, 0, &win_x, &win_y,
1137 /* Child of win. */
1138 &child);
1140 /* It is possible for the window returned by the XQueryNotify
1141 to become invalid by the time we call XTranslateCoordinates.
1142 That can happen when you restart some window managers.
1143 If so, we get an error in XTranslateCoordinates.
1144 Detect that and try the whole thing over. */
1145 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1147 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1148 break;
1151 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1154 *xptr = win_x;
1155 *yptr = win_y;
1158 /* Insert a description of internally-recorded parameters of frame X
1159 into the parameter alist *ALISTPTR that is to be given to the user.
1160 Only parameters that are specific to the X window system
1161 and whose values are not correctly recorded in the frame's
1162 param_alist need to be considered here. */
1164 void
1165 x_report_frame_params (f, alistptr)
1166 struct frame *f;
1167 Lisp_Object *alistptr;
1169 char buf[16];
1170 Lisp_Object tem;
1172 /* Represent negative positions (off the top or left screen edge)
1173 in a way that Fmodify_frame_parameters will understand correctly. */
1174 XSETINT (tem, f->output_data.x->left_pos);
1175 if (f->output_data.x->left_pos >= 0)
1176 store_in_alist (alistptr, Qleft, tem);
1177 else
1178 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1180 XSETINT (tem, f->output_data.x->top_pos);
1181 if (f->output_data.x->top_pos >= 0)
1182 store_in_alist (alistptr, Qtop, tem);
1183 else
1184 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1186 store_in_alist (alistptr, Qborder_width,
1187 make_number (f->output_data.x->border_width));
1188 store_in_alist (alistptr, Qinternal_border_width,
1189 make_number (f->output_data.x->internal_border_width));
1190 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1191 store_in_alist (alistptr, Qwindow_id,
1192 build_string (buf));
1193 #ifdef USE_X_TOOLKIT
1194 /* Tooltip frame may not have this widget. */
1195 if (f->output_data.x->widget)
1196 #endif
1197 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1198 store_in_alist (alistptr, Qouter_window_id,
1199 build_string (buf));
1200 store_in_alist (alistptr, Qicon_name, f->icon_name);
1201 FRAME_SAMPLE_VISIBILITY (f);
1202 store_in_alist (alistptr, Qvisibility,
1203 (FRAME_VISIBLE_P (f) ? Qt
1204 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1205 store_in_alist (alistptr, Qdisplay,
1206 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1208 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1209 tem = Qnil;
1210 else
1211 XSETFASTINT (tem, f->output_data.x->parent_desc);
1212 store_in_alist (alistptr, Qparent_id, tem);
1217 /* Gamma-correct COLOR on frame F. */
1219 void
1220 gamma_correct (f, color)
1221 struct frame *f;
1222 XColor *color;
1224 if (f->gamma)
1226 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1227 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1228 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1233 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1234 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1235 allocate the color. Value is zero if COLOR_NAME is invalid, or
1236 no color could be allocated. */
1239 x_defined_color (f, color_name, color, alloc_p)
1240 struct frame *f;
1241 char *color_name;
1242 XColor *color;
1243 int alloc_p;
1245 int success_p;
1246 Display *dpy = FRAME_X_DISPLAY (f);
1247 Colormap cmap = FRAME_X_COLORMAP (f);
1249 BLOCK_INPUT;
1250 success_p = XParseColor (dpy, cmap, color_name, color);
1251 if (success_p && alloc_p)
1252 success_p = x_alloc_nearest_color (f, cmap, color);
1253 UNBLOCK_INPUT;
1255 return success_p;
1259 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1260 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1261 Signal an error if color can't be allocated. */
1264 x_decode_color (f, color_name, mono_color)
1265 FRAME_PTR f;
1266 Lisp_Object color_name;
1267 int mono_color;
1269 XColor cdef;
1271 CHECK_STRING (color_name, 0);
1273 #if 0 /* Don't do this. It's wrong when we're not using the default
1274 colormap, it makes freeing difficult, and it's probably not
1275 an important optimization. */
1276 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1277 return BLACK_PIX_DEFAULT (f);
1278 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1279 return WHITE_PIX_DEFAULT (f);
1280 #endif
1282 /* Return MONO_COLOR for monochrome frames. */
1283 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1284 return mono_color;
1286 /* x_defined_color is responsible for coping with failures
1287 by looking for a near-miss. */
1288 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1289 return cdef.pixel;
1291 Fsignal (Qerror, Fcons (build_string ("undefined color"),
1292 Fcons (color_name, Qnil)));
1297 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1298 the previous value of that parameter, NEW_VALUE is the new value. */
1300 static void
1301 x_set_line_spacing (f, new_value, old_value)
1302 struct frame *f;
1303 Lisp_Object new_value, old_value;
1305 if (NILP (new_value))
1306 f->extra_line_spacing = 0;
1307 else if (NATNUMP (new_value))
1308 f->extra_line_spacing = XFASTINT (new_value);
1309 else
1310 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1311 Fcons (new_value, Qnil)));
1312 if (FRAME_VISIBLE_P (f))
1313 redraw_frame (f);
1317 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1318 the previous value of that parameter, NEW_VALUE is the new value. */
1320 static void
1321 x_set_screen_gamma (f, new_value, old_value)
1322 struct frame *f;
1323 Lisp_Object new_value, old_value;
1325 if (NILP (new_value))
1326 f->gamma = 0;
1327 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1328 /* The value 0.4545 is the normal viewing gamma. */
1329 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1330 else
1331 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1332 Fcons (new_value, Qnil)));
1334 clear_face_cache (0);
1338 /* Functions called only from `x_set_frame_param'
1339 to set individual parameters.
1341 If FRAME_X_WINDOW (f) is 0,
1342 the frame is being created and its X-window does not exist yet.
1343 In that case, just record the parameter's new value
1344 in the standard place; do not attempt to change the window. */
1346 void
1347 x_set_foreground_color (f, arg, oldval)
1348 struct frame *f;
1349 Lisp_Object arg, oldval;
1351 unsigned long pixel
1352 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1354 unload_color (f, f->output_data.x->foreground_pixel);
1355 f->output_data.x->foreground_pixel = pixel;
1357 if (FRAME_X_WINDOW (f) != 0)
1359 BLOCK_INPUT;
1360 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1361 f->output_data.x->foreground_pixel);
1362 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1363 f->output_data.x->foreground_pixel);
1364 UNBLOCK_INPUT;
1365 update_face_from_frame_parameter (f, Qforeground_color, arg);
1366 if (FRAME_VISIBLE_P (f))
1367 redraw_frame (f);
1371 void
1372 x_set_background_color (f, arg, oldval)
1373 struct frame *f;
1374 Lisp_Object arg, oldval;
1376 unsigned long pixel
1377 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1379 unload_color (f, f->output_data.x->background_pixel);
1380 f->output_data.x->background_pixel = pixel;
1382 if (FRAME_X_WINDOW (f) != 0)
1384 BLOCK_INPUT;
1385 /* The main frame area. */
1386 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1387 f->output_data.x->background_pixel);
1388 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1389 f->output_data.x->background_pixel);
1390 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1391 f->output_data.x->background_pixel);
1392 XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1393 f->output_data.x->background_pixel);
1395 Lisp_Object bar;
1396 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
1397 bar = XSCROLL_BAR (bar)->next)
1398 XSetWindowBackground (FRAME_X_DISPLAY (f),
1399 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
1400 f->output_data.x->background_pixel);
1402 UNBLOCK_INPUT;
1404 update_face_from_frame_parameter (f, Qbackground_color, arg);
1406 if (FRAME_VISIBLE_P (f))
1407 redraw_frame (f);
1411 void
1412 x_set_mouse_color (f, arg, oldval)
1413 struct frame *f;
1414 Lisp_Object arg, oldval;
1416 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1417 Cursor busy_cursor;
1418 int count;
1419 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1420 unsigned long mask_color = f->output_data.x->background_pixel;
1422 /* Don't let pointers be invisible. */
1423 if (mask_color == pixel
1424 && mask_color == f->output_data.x->background_pixel)
1425 pixel = f->output_data.x->foreground_pixel;
1427 unload_color (f, f->output_data.x->mouse_pixel);
1428 f->output_data.x->mouse_pixel = pixel;
1430 BLOCK_INPUT;
1432 /* It's not okay to crash if the user selects a screwy cursor. */
1433 count = x_catch_errors (FRAME_X_DISPLAY (f));
1435 if (!EQ (Qnil, Vx_pointer_shape))
1437 CHECK_NUMBER (Vx_pointer_shape, 0);
1438 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
1440 else
1441 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1442 x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
1444 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1446 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1447 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1448 XINT (Vx_nontext_pointer_shape));
1450 else
1451 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
1452 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1454 if (!EQ (Qnil, Vx_busy_pointer_shape))
1456 CHECK_NUMBER (Vx_busy_pointer_shape, 0);
1457 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1458 XINT (Vx_busy_pointer_shape));
1460 else
1461 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
1462 x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s");
1464 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1465 if (!EQ (Qnil, Vx_mode_pointer_shape))
1467 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1468 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1469 XINT (Vx_mode_pointer_shape));
1471 else
1472 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1473 x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
1475 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1477 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1478 cross_cursor
1479 = XCreateFontCursor (FRAME_X_DISPLAY (f),
1480 XINT (Vx_sensitive_text_pointer_shape));
1482 else
1483 cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
1485 /* Check and report errors with the above calls. */
1486 x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
1487 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1490 XColor fore_color, back_color;
1492 fore_color.pixel = f->output_data.x->mouse_pixel;
1493 back_color.pixel = mask_color;
1494 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
1495 &fore_color);
1496 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
1497 &back_color);
1498 XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
1499 &fore_color, &back_color);
1500 XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
1501 &fore_color, &back_color);
1502 XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
1503 &fore_color, &back_color);
1504 XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
1505 &fore_color, &back_color);
1506 XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
1507 &fore_color, &back_color);
1510 if (FRAME_X_WINDOW (f) != 0)
1511 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
1513 if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
1514 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
1515 f->output_data.x->text_cursor = cursor;
1517 if (nontext_cursor != f->output_data.x->nontext_cursor
1518 && f->output_data.x->nontext_cursor != 0)
1519 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
1520 f->output_data.x->nontext_cursor = nontext_cursor;
1522 if (busy_cursor != f->output_data.x->busy_cursor
1523 && f->output_data.x->busy_cursor != 0)
1524 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
1525 f->output_data.x->busy_cursor = busy_cursor;
1527 if (mode_cursor != f->output_data.x->modeline_cursor
1528 && f->output_data.x->modeline_cursor != 0)
1529 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
1530 f->output_data.x->modeline_cursor = mode_cursor;
1532 if (cross_cursor != f->output_data.x->cross_cursor
1533 && f->output_data.x->cross_cursor != 0)
1534 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
1535 f->output_data.x->cross_cursor = cross_cursor;
1537 XFlush (FRAME_X_DISPLAY (f));
1538 UNBLOCK_INPUT;
1540 update_face_from_frame_parameter (f, Qmouse_color, arg);
1543 void
1544 x_set_cursor_color (f, arg, oldval)
1545 struct frame *f;
1546 Lisp_Object arg, oldval;
1548 unsigned long fore_pixel, pixel;
1549 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1551 if (!NILP (Vx_cursor_fore_pixel))
1553 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1554 WHITE_PIX_DEFAULT (f));
1555 fore_pixel_allocated_p = 1;
1557 else
1558 fore_pixel = f->output_data.x->background_pixel;
1560 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1561 pixel_allocated_p = 1;
1563 /* Make sure that the cursor color differs from the background color. */
1564 if (pixel == f->output_data.x->background_pixel)
1566 if (pixel_allocated_p)
1568 x_free_colors (f, &pixel, 1);
1569 pixel_allocated_p = 0;
1572 pixel = f->output_data.x->mouse_pixel;
1573 if (pixel == fore_pixel)
1575 if (fore_pixel_allocated_p)
1577 x_free_colors (f, &fore_pixel, 1);
1578 fore_pixel_allocated_p = 0;
1580 fore_pixel = f->output_data.x->background_pixel;
1584 unload_color (f, f->output_data.x->cursor_foreground_pixel);
1585 if (!fore_pixel_allocated_p)
1586 fore_pixel = x_copy_color (f, fore_pixel);
1587 f->output_data.x->cursor_foreground_pixel = fore_pixel;
1589 unload_color (f, f->output_data.x->cursor_pixel);
1590 if (!pixel_allocated_p)
1591 pixel = x_copy_color (f, pixel);
1592 f->output_data.x->cursor_pixel = pixel;
1594 if (FRAME_X_WINDOW (f) != 0)
1596 BLOCK_INPUT;
1597 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1598 f->output_data.x->cursor_pixel);
1599 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1600 fore_pixel);
1601 UNBLOCK_INPUT;
1603 if (FRAME_VISIBLE_P (f))
1605 x_update_cursor (f, 0);
1606 x_update_cursor (f, 1);
1610 update_face_from_frame_parameter (f, Qcursor_color, arg);
1613 /* Set the border-color of frame F to value described by ARG.
1614 ARG can be a string naming a color.
1615 The border-color is used for the border that is drawn by the X server.
1616 Note that this does not fully take effect if done before
1617 F has an x-window; it must be redone when the window is created.
1619 Note: this is done in two routines because of the way X10 works.
1621 Note: under X11, this is normally the province of the window manager,
1622 and so emacs' border colors may be overridden. */
1624 void
1625 x_set_border_color (f, arg, oldval)
1626 struct frame *f;
1627 Lisp_Object arg, oldval;
1629 int pix;
1631 CHECK_STRING (arg, 0);
1632 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1633 x_set_border_pixel (f, pix);
1634 update_face_from_frame_parameter (f, Qborder_color, arg);
1637 /* Set the border-color of frame F to pixel value PIX.
1638 Note that this does not fully take effect if done before
1639 F has an x-window. */
1641 void
1642 x_set_border_pixel (f, pix)
1643 struct frame *f;
1644 int pix;
1646 unload_color (f, f->output_data.x->border_pixel);
1647 f->output_data.x->border_pixel = pix;
1649 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1651 BLOCK_INPUT;
1652 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1653 (unsigned long)pix);
1654 UNBLOCK_INPUT;
1656 if (FRAME_VISIBLE_P (f))
1657 redraw_frame (f);
1662 /* Value is the internal representation of the specified cursor type
1663 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1664 of the bar cursor. */
1666 enum text_cursor_kinds
1667 x_specified_cursor_type (arg, width)
1668 Lisp_Object arg;
1669 int *width;
1671 enum text_cursor_kinds type;
1673 if (EQ (arg, Qbar))
1675 type = BAR_CURSOR;
1676 *width = 2;
1678 else if (CONSP (arg)
1679 && EQ (XCAR (arg), Qbar)
1680 && INTEGERP (XCDR (arg))
1681 && XINT (XCDR (arg)) >= 0)
1683 type = BAR_CURSOR;
1684 *width = XINT (XCDR (arg));
1686 else if (NILP (arg))
1687 type = NO_CURSOR;
1688 else
1689 /* Treat anything unknown as "box cursor".
1690 It was bad to signal an error; people have trouble fixing
1691 .Xdefaults with Emacs, when it has something bad in it. */
1692 type = FILLED_BOX_CURSOR;
1694 return type;
1697 void
1698 x_set_cursor_type (f, arg, oldval)
1699 FRAME_PTR f;
1700 Lisp_Object arg, oldval;
1702 int width;
1704 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1705 f->output_data.x->cursor_width = width;
1707 /* Make sure the cursor gets redrawn. This is overkill, but how
1708 often do people change cursor types? */
1709 update_mode_lines++;
1712 void
1713 x_set_icon_type (f, arg, oldval)
1714 struct frame *f;
1715 Lisp_Object arg, oldval;
1717 int result;
1719 if (STRINGP (arg))
1721 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1722 return;
1724 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1725 return;
1727 BLOCK_INPUT;
1728 if (NILP (arg))
1729 result = x_text_icon (f,
1730 (char *) XSTRING ((!NILP (f->icon_name)
1731 ? f->icon_name
1732 : f->name))->data);
1733 else
1734 result = x_bitmap_icon (f, arg);
1736 if (result)
1738 UNBLOCK_INPUT;
1739 error ("No icon window available");
1742 XFlush (FRAME_X_DISPLAY (f));
1743 UNBLOCK_INPUT;
1746 /* Return non-nil if frame F wants a bitmap icon. */
1748 Lisp_Object
1749 x_icon_type (f)
1750 FRAME_PTR f;
1752 Lisp_Object tem;
1754 tem = assq_no_quit (Qicon_type, f->param_alist);
1755 if (CONSP (tem))
1756 return XCDR (tem);
1757 else
1758 return Qnil;
1761 void
1762 x_set_icon_name (f, arg, oldval)
1763 struct frame *f;
1764 Lisp_Object arg, oldval;
1766 int result;
1768 if (STRINGP (arg))
1770 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1771 return;
1773 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1774 return;
1776 f->icon_name = arg;
1778 if (f->output_data.x->icon_bitmap != 0)
1779 return;
1781 BLOCK_INPUT;
1783 result = x_text_icon (f,
1784 (char *) XSTRING ((!NILP (f->icon_name)
1785 ? f->icon_name
1786 : !NILP (f->title)
1787 ? f->title
1788 : f->name))->data);
1790 if (result)
1792 UNBLOCK_INPUT;
1793 error ("No icon window available");
1796 XFlush (FRAME_X_DISPLAY (f));
1797 UNBLOCK_INPUT;
1800 void
1801 x_set_font (f, arg, oldval)
1802 struct frame *f;
1803 Lisp_Object arg, oldval;
1805 Lisp_Object result;
1806 Lisp_Object fontset_name;
1807 Lisp_Object frame;
1809 CHECK_STRING (arg, 1);
1811 fontset_name = Fquery_fontset (arg, Qnil);
1813 BLOCK_INPUT;
1814 result = (STRINGP (fontset_name)
1815 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1816 : x_new_font (f, XSTRING (arg)->data));
1817 UNBLOCK_INPUT;
1819 if (EQ (result, Qnil))
1820 error ("Font `%s' is not defined", XSTRING (arg)->data);
1821 else if (EQ (result, Qt))
1822 error ("The characters of the given font have varying widths");
1823 else if (STRINGP (result))
1825 store_frame_param (f, Qfont, result);
1826 recompute_basic_faces (f);
1828 else
1829 abort ();
1831 do_pending_window_change (0);
1833 /* Don't call `face-set-after-frame-default' when faces haven't been
1834 initialized yet. This is the case when called from
1835 Fx_create_frame. In that case, the X widget or window doesn't
1836 exist either, and we can end up in x_report_frame_params with a
1837 null widget which gives a segfault. */
1838 if (FRAME_FACE_CACHE (f))
1840 XSETFRAME (frame, f);
1841 call1 (Qface_set_after_frame_default, frame);
1845 void
1846 x_set_border_width (f, arg, oldval)
1847 struct frame *f;
1848 Lisp_Object arg, oldval;
1850 CHECK_NUMBER (arg, 0);
1852 if (XINT (arg) == f->output_data.x->border_width)
1853 return;
1855 if (FRAME_X_WINDOW (f) != 0)
1856 error ("Cannot change the border width of a window");
1858 f->output_data.x->border_width = XINT (arg);
1861 void
1862 x_set_internal_border_width (f, arg, oldval)
1863 struct frame *f;
1864 Lisp_Object arg, oldval;
1866 int old = f->output_data.x->internal_border_width;
1868 CHECK_NUMBER (arg, 0);
1869 f->output_data.x->internal_border_width = XINT (arg);
1870 if (f->output_data.x->internal_border_width < 0)
1871 f->output_data.x->internal_border_width = 0;
1873 #ifdef USE_X_TOOLKIT
1874 if (f->output_data.x->edit_widget)
1875 widget_store_internal_border (f->output_data.x->edit_widget);
1876 #endif
1878 if (f->output_data.x->internal_border_width == old)
1879 return;
1881 if (FRAME_X_WINDOW (f) != 0)
1883 x_set_window_size (f, 0, f->width, f->height);
1884 SET_FRAME_GARBAGED (f);
1885 do_pending_window_change (0);
1889 void
1890 x_set_visibility (f, value, oldval)
1891 struct frame *f;
1892 Lisp_Object value, oldval;
1894 Lisp_Object frame;
1895 XSETFRAME (frame, f);
1897 if (NILP (value))
1898 Fmake_frame_invisible (frame, Qt);
1899 else if (EQ (value, Qicon))
1900 Ficonify_frame (frame);
1901 else
1902 Fmake_frame_visible (frame);
1905 static void
1906 x_set_menu_bar_lines_1 (window, n)
1907 Lisp_Object window;
1908 int n;
1910 struct window *w = XWINDOW (window);
1912 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1913 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1915 if (INTEGERP (w->orig_top))
1916 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
1917 if (INTEGERP (w->orig_height))
1918 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
1920 /* Handle just the top child in a vertical split. */
1921 if (!NILP (w->vchild))
1922 x_set_menu_bar_lines_1 (w->vchild, n);
1924 /* Adjust all children in a horizontal split. */
1925 for (window = w->hchild; !NILP (window); window = w->next)
1927 w = XWINDOW (window);
1928 x_set_menu_bar_lines_1 (window, n);
1932 void
1933 x_set_menu_bar_lines (f, value, oldval)
1934 struct frame *f;
1935 Lisp_Object value, oldval;
1937 int nlines;
1938 #ifndef USE_X_TOOLKIT
1939 int olines = FRAME_MENU_BAR_LINES (f);
1940 #endif
1942 /* Right now, menu bars don't work properly in minibuf-only frames;
1943 most of the commands try to apply themselves to the minibuffer
1944 frame itself, and get an error because you can't switch buffers
1945 in or split the minibuffer window. */
1946 if (FRAME_MINIBUF_ONLY_P (f))
1947 return;
1949 if (INTEGERP (value))
1950 nlines = XINT (value);
1951 else
1952 nlines = 0;
1954 /* Make sure we redisplay all windows in this frame. */
1955 windows_or_buffers_changed++;
1957 #ifdef USE_X_TOOLKIT
1958 FRAME_MENU_BAR_LINES (f) = 0;
1959 if (nlines)
1961 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1962 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1963 /* Make sure next redisplay shows the menu bar. */
1964 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1966 else
1968 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1969 free_frame_menubar (f);
1970 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1971 if (FRAME_X_P (f))
1972 f->output_data.x->menubar_widget = 0;
1974 #else /* not USE_X_TOOLKIT */
1975 FRAME_MENU_BAR_LINES (f) = nlines;
1976 x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
1977 #endif /* not USE_X_TOOLKIT */
1978 adjust_glyphs (f);
1982 /* Set the number of lines used for the tool bar of frame F to VALUE.
1983 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1984 is the old number of tool bar lines. This function changes the
1985 height of all windows on frame F to match the new tool bar height.
1986 The frame's height doesn't change. */
1988 void
1989 x_set_tool_bar_lines (f, value, oldval)
1990 struct frame *f;
1991 Lisp_Object value, oldval;
1993 int delta, nlines;
1995 /* Use VALUE only if an integer >= 0. */
1996 if (INTEGERP (value) && XINT (value) >= 0)
1997 nlines = XFASTINT (value);
1998 else
1999 nlines = 0;
2001 /* Make sure we redisplay all windows in this frame. */
2002 ++windows_or_buffers_changed;
2004 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2005 FRAME_TOOL_BAR_LINES (f) = nlines;
2006 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
2007 adjust_glyphs (f);
2011 /* Set the foreground color for scroll bars on frame F to VALUE.
2012 VALUE should be a string, a color name. If it isn't a string or
2013 isn't a valid color name, do nothing. OLDVAL is the old value of
2014 the frame parameter. */
2016 void
2017 x_set_scroll_bar_foreground (f, value, oldval)
2018 struct frame *f;
2019 Lisp_Object value, oldval;
2021 unsigned long pixel;
2023 if (STRINGP (value))
2024 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2025 else
2026 pixel = -1;
2028 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2029 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2031 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2032 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2034 /* Remove all scroll bars because they have wrong colors. */
2035 if (condemn_scroll_bars_hook)
2036 (*condemn_scroll_bars_hook) (f);
2037 if (judge_scroll_bars_hook)
2038 (*judge_scroll_bars_hook) (f);
2040 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2041 redraw_frame (f);
2046 /* Set the background color for scroll bars on frame F to VALUE VALUE
2047 should be a string, a color name. If it isn't a string or isn't a
2048 valid color name, do nothing. OLDVAL is the old value of the frame
2049 parameter. */
2051 void
2052 x_set_scroll_bar_background (f, value, oldval)
2053 struct frame *f;
2054 Lisp_Object value, oldval;
2056 unsigned long pixel;
2058 if (STRINGP (value))
2059 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2060 else
2061 pixel = -1;
2063 if (f->output_data.x->scroll_bar_background_pixel != -1)
2064 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2066 f->output_data.x->scroll_bar_background_pixel = pixel;
2067 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2069 /* Remove all scroll bars because they have wrong colors. */
2070 if (condemn_scroll_bars_hook)
2071 (*condemn_scroll_bars_hook) (f);
2072 if (judge_scroll_bars_hook)
2073 (*judge_scroll_bars_hook) (f);
2075 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2076 redraw_frame (f);
2081 /* Encode Lisp string STRING as a text in a format appropriate for
2082 XICCC (X Inter Client Communication Conventions).
2084 If STRING contains only ASCII characters, do no conversion and
2085 return the string data of STRING. Otherwise, encode the text by
2086 CODING_SYSTEM, and return a newly allocated memory area which
2087 should be freed by `xfree' by a caller.
2089 Store the byte length of resulting text in *TEXT_BYTES.
2091 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2092 which means that the `encoding' of the result can be `STRING'.
2093 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2094 the result should be `COMPOUND_TEXT'. */
2096 unsigned char *
2097 x_encode_text (string, coding_system, text_bytes, stringp)
2098 Lisp_Object string, coding_system;
2099 int *text_bytes, *stringp;
2101 unsigned char *str = XSTRING (string)->data;
2102 int chars = XSTRING (string)->size;
2103 int bytes = STRING_BYTES (XSTRING (string));
2104 int charset_info;
2105 int bufsize;
2106 unsigned char *buf;
2107 struct coding_system coding;
2109 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2110 if (charset_info == 0)
2112 /* No multibyte character in OBJ. We need not encode it. */
2113 *text_bytes = bytes;
2114 *stringp = 1;
2115 return str;
2118 setup_coding_system (coding_system, &coding);
2119 coding.src_multibyte = 1;
2120 coding.dst_multibyte = 0;
2121 coding.mode |= CODING_MODE_LAST_BLOCK;
2122 if (coding.type == coding_type_iso2022)
2123 coding.flags |= CODING_FLAG_ISO_SAFE;
2124 bufsize = encoding_buffer_size (&coding, bytes);
2125 buf = (unsigned char *) xmalloc (bufsize);
2126 encode_coding (&coding, str, buf, bytes, bufsize);
2127 *text_bytes = coding.produced;
2128 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2129 return buf;
2133 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2134 x_id_name.
2136 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2137 name; if NAME is a string, set F's name to NAME and set
2138 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2140 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2141 suggesting a new name, which lisp code should override; if
2142 F->explicit_name is set, ignore the new name; otherwise, set it. */
2144 void
2145 x_set_name (f, name, explicit)
2146 struct frame *f;
2147 Lisp_Object name;
2148 int explicit;
2150 /* Make sure that requests from lisp code override requests from
2151 Emacs redisplay code. */
2152 if (explicit)
2154 /* If we're switching from explicit to implicit, we had better
2155 update the mode lines and thereby update the title. */
2156 if (f->explicit_name && NILP (name))
2157 update_mode_lines = 1;
2159 f->explicit_name = ! NILP (name);
2161 else if (f->explicit_name)
2162 return;
2164 /* If NAME is nil, set the name to the x_id_name. */
2165 if (NILP (name))
2167 /* Check for no change needed in this very common case
2168 before we do any consing. */
2169 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2170 XSTRING (f->name)->data))
2171 return;
2172 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2174 else
2175 CHECK_STRING (name, 0);
2177 /* Don't change the name if it's already NAME. */
2178 if (! NILP (Fstring_equal (name, f->name)))
2179 return;
2181 f->name = name;
2183 /* For setting the frame title, the title parameter should override
2184 the name parameter. */
2185 if (! NILP (f->title))
2186 name = f->title;
2188 if (FRAME_X_WINDOW (f))
2190 BLOCK_INPUT;
2191 #ifdef HAVE_X11R4
2193 XTextProperty text, icon;
2194 int bytes, stringp;
2195 Lisp_Object coding_system;
2197 coding_system = Vlocale_coding_system;
2198 if (NILP (coding_system))
2199 coding_system = Qcompound_text;
2200 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2201 text.encoding = (stringp ? XA_STRING
2202 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2203 text.format = 8;
2204 text.nitems = bytes;
2206 if (NILP (f->icon_name))
2208 icon = text;
2210 else
2212 icon.value = x_encode_text (f->icon_name, coding_system,
2213 &bytes, &stringp);
2214 icon.encoding = (stringp ? XA_STRING
2215 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2216 icon.format = 8;
2217 icon.nitems = bytes;
2219 #ifdef USE_X_TOOLKIT
2220 XSetWMName (FRAME_X_DISPLAY (f),
2221 XtWindow (f->output_data.x->widget), &text);
2222 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2223 &icon);
2224 #else /* not USE_X_TOOLKIT */
2225 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2226 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2227 #endif /* not USE_X_TOOLKIT */
2228 if (!NILP (f->icon_name)
2229 && icon.value != XSTRING (f->icon_name)->data)
2230 xfree (icon.value);
2231 if (text.value != XSTRING (name)->data)
2232 xfree (text.value);
2234 #else /* not HAVE_X11R4 */
2235 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2236 XSTRING (name)->data);
2237 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2238 XSTRING (name)->data);
2239 #endif /* not HAVE_X11R4 */
2240 UNBLOCK_INPUT;
2244 /* This function should be called when the user's lisp code has
2245 specified a name for the frame; the name will override any set by the
2246 redisplay code. */
2247 void
2248 x_explicitly_set_name (f, arg, oldval)
2249 FRAME_PTR f;
2250 Lisp_Object arg, oldval;
2252 x_set_name (f, arg, 1);
2255 /* This function should be called by Emacs redisplay code to set the
2256 name; names set this way will never override names set by the user's
2257 lisp code. */
2258 void
2259 x_implicitly_set_name (f, arg, oldval)
2260 FRAME_PTR f;
2261 Lisp_Object arg, oldval;
2263 x_set_name (f, arg, 0);
2266 /* Change the title of frame F to NAME.
2267 If NAME is nil, use the frame name as the title.
2269 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2270 name; if NAME is a string, set F's name to NAME and set
2271 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2273 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2274 suggesting a new name, which lisp code should override; if
2275 F->explicit_name is set, ignore the new name; otherwise, set it. */
2277 void
2278 x_set_title (f, name, old_name)
2279 struct frame *f;
2280 Lisp_Object name, old_name;
2282 /* Don't change the title if it's already NAME. */
2283 if (EQ (name, f->title))
2284 return;
2286 update_mode_lines = 1;
2288 f->title = name;
2290 if (NILP (name))
2291 name = f->name;
2292 else
2293 CHECK_STRING (name, 0);
2295 if (FRAME_X_WINDOW (f))
2297 BLOCK_INPUT;
2298 #ifdef HAVE_X11R4
2300 XTextProperty text, icon;
2301 int bytes, stringp;
2302 Lisp_Object coding_system;
2304 coding_system = Vlocale_coding_system;
2305 if (NILP (coding_system))
2306 coding_system = Qcompound_text;
2307 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2308 text.encoding = (stringp ? XA_STRING
2309 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2310 text.format = 8;
2311 text.nitems = bytes;
2313 if (NILP (f->icon_name))
2315 icon = text;
2317 else
2319 icon.value = x_encode_text (f->icon_name, coding_system,
2320 &bytes, &stringp);
2321 icon.encoding = (stringp ? XA_STRING
2322 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2323 icon.format = 8;
2324 icon.nitems = bytes;
2326 #ifdef USE_X_TOOLKIT
2327 XSetWMName (FRAME_X_DISPLAY (f),
2328 XtWindow (f->output_data.x->widget), &text);
2329 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2330 &icon);
2331 #else /* not USE_X_TOOLKIT */
2332 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2333 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2334 #endif /* not USE_X_TOOLKIT */
2335 if (!NILP (f->icon_name)
2336 && icon.value != XSTRING (f->icon_name)->data)
2337 xfree (icon.value);
2338 if (text.value != XSTRING (name)->data)
2339 xfree (text.value);
2341 #else /* not HAVE_X11R4 */
2342 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2343 XSTRING (name)->data);
2344 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2345 XSTRING (name)->data);
2346 #endif /* not HAVE_X11R4 */
2347 UNBLOCK_INPUT;
2351 void
2352 x_set_autoraise (f, arg, oldval)
2353 struct frame *f;
2354 Lisp_Object arg, oldval;
2356 f->auto_raise = !EQ (Qnil, arg);
2359 void
2360 x_set_autolower (f, arg, oldval)
2361 struct frame *f;
2362 Lisp_Object arg, oldval;
2364 f->auto_lower = !EQ (Qnil, arg);
2367 void
2368 x_set_unsplittable (f, arg, oldval)
2369 struct frame *f;
2370 Lisp_Object arg, oldval;
2372 f->no_split = !NILP (arg);
2375 void
2376 x_set_vertical_scroll_bars (f, arg, oldval)
2377 struct frame *f;
2378 Lisp_Object arg, oldval;
2380 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2381 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2382 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2383 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2385 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2386 = (NILP (arg)
2387 ? vertical_scroll_bar_none
2388 : EQ (Qright, arg)
2389 ? vertical_scroll_bar_right
2390 : vertical_scroll_bar_left);
2392 /* We set this parameter before creating the X window for the
2393 frame, so we can get the geometry right from the start.
2394 However, if the window hasn't been created yet, we shouldn't
2395 call x_set_window_size. */
2396 if (FRAME_X_WINDOW (f))
2397 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2398 do_pending_window_change (0);
2402 void
2403 x_set_scroll_bar_width (f, arg, oldval)
2404 struct frame *f;
2405 Lisp_Object arg, oldval;
2407 int wid = FONT_WIDTH (f->output_data.x->font);
2409 if (NILP (arg))
2411 #ifdef USE_TOOLKIT_SCROLL_BARS
2412 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2413 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2414 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2415 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2416 #else
2417 /* Make the actual width at least 14 pixels and a multiple of a
2418 character width. */
2419 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2421 /* Use all of that space (aside from required margins) for the
2422 scroll bar. */
2423 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2424 #endif
2426 if (FRAME_X_WINDOW (f))
2427 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2428 do_pending_window_change (0);
2430 else if (INTEGERP (arg) && XINT (arg) > 0
2431 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2433 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2434 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2436 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2437 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2438 if (FRAME_X_WINDOW (f))
2439 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2442 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2443 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2444 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2449 /* Subroutines of creating an X frame. */
2451 /* Make sure that Vx_resource_name is set to a reasonable value.
2452 Fix it up, or set it to `emacs' if it is too hopeless. */
2454 static void
2455 validate_x_resource_name ()
2457 int len = 0;
2458 /* Number of valid characters in the resource name. */
2459 int good_count = 0;
2460 /* Number of invalid characters in the resource name. */
2461 int bad_count = 0;
2462 Lisp_Object new;
2463 int i;
2465 if (!STRINGP (Vx_resource_class))
2466 Vx_resource_class = build_string (EMACS_CLASS);
2468 if (STRINGP (Vx_resource_name))
2470 unsigned char *p = XSTRING (Vx_resource_name)->data;
2471 int i;
2473 len = STRING_BYTES (XSTRING (Vx_resource_name));
2475 /* Only letters, digits, - and _ are valid in resource names.
2476 Count the valid characters and count the invalid ones. */
2477 for (i = 0; i < len; i++)
2479 int c = p[i];
2480 if (! ((c >= 'a' && c <= 'z')
2481 || (c >= 'A' && c <= 'Z')
2482 || (c >= '0' && c <= '9')
2483 || c == '-' || c == '_'))
2484 bad_count++;
2485 else
2486 good_count++;
2489 else
2490 /* Not a string => completely invalid. */
2491 bad_count = 5, good_count = 0;
2493 /* If name is valid already, return. */
2494 if (bad_count == 0)
2495 return;
2497 /* If name is entirely invalid, or nearly so, use `emacs'. */
2498 if (good_count == 0
2499 || (good_count == 1 && bad_count > 0))
2501 Vx_resource_name = build_string ("emacs");
2502 return;
2505 /* Name is partly valid. Copy it and replace the invalid characters
2506 with underscores. */
2508 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2510 for (i = 0; i < len; i++)
2512 int c = XSTRING (new)->data[i];
2513 if (! ((c >= 'a' && c <= 'z')
2514 || (c >= 'A' && c <= 'Z')
2515 || (c >= '0' && c <= '9')
2516 || c == '-' || c == '_'))
2517 XSTRING (new)->data[i] = '_';
2522 extern char *x_get_string_resource ();
2524 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2525 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2526 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2527 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2528 the name specified by the `-name' or `-rn' command-line arguments.\n\
2530 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2531 class, respectively. You must specify both of them or neither.\n\
2532 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2533 and the class is `Emacs.CLASS.SUBCLASS'.")
2534 (attribute, class, component, subclass)
2535 Lisp_Object attribute, class, component, subclass;
2537 register char *value;
2538 char *name_key;
2539 char *class_key;
2541 check_x ();
2543 CHECK_STRING (attribute, 0);
2544 CHECK_STRING (class, 0);
2546 if (!NILP (component))
2547 CHECK_STRING (component, 1);
2548 if (!NILP (subclass))
2549 CHECK_STRING (subclass, 2);
2550 if (NILP (component) != NILP (subclass))
2551 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2553 validate_x_resource_name ();
2555 /* Allocate space for the components, the dots which separate them,
2556 and the final '\0'. Make them big enough for the worst case. */
2557 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2558 + (STRINGP (component)
2559 ? STRING_BYTES (XSTRING (component)) : 0)
2560 + STRING_BYTES (XSTRING (attribute))
2561 + 3);
2563 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2564 + STRING_BYTES (XSTRING (class))
2565 + (STRINGP (subclass)
2566 ? STRING_BYTES (XSTRING (subclass)) : 0)
2567 + 3);
2569 /* Start with emacs.FRAMENAME for the name (the specific one)
2570 and with `Emacs' for the class key (the general one). */
2571 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2572 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2574 strcat (class_key, ".");
2575 strcat (class_key, XSTRING (class)->data);
2577 if (!NILP (component))
2579 strcat (class_key, ".");
2580 strcat (class_key, XSTRING (subclass)->data);
2582 strcat (name_key, ".");
2583 strcat (name_key, XSTRING (component)->data);
2586 strcat (name_key, ".");
2587 strcat (name_key, XSTRING (attribute)->data);
2589 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2590 name_key, class_key);
2592 if (value != (char *) 0)
2593 return build_string (value);
2594 else
2595 return Qnil;
2598 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2600 Lisp_Object
2601 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2602 struct x_display_info *dpyinfo;
2603 Lisp_Object attribute, class, component, subclass;
2605 register char *value;
2606 char *name_key;
2607 char *class_key;
2609 CHECK_STRING (attribute, 0);
2610 CHECK_STRING (class, 0);
2612 if (!NILP (component))
2613 CHECK_STRING (component, 1);
2614 if (!NILP (subclass))
2615 CHECK_STRING (subclass, 2);
2616 if (NILP (component) != NILP (subclass))
2617 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2619 validate_x_resource_name ();
2621 /* Allocate space for the components, the dots which separate them,
2622 and the final '\0'. Make them big enough for the worst case. */
2623 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2624 + (STRINGP (component)
2625 ? STRING_BYTES (XSTRING (component)) : 0)
2626 + STRING_BYTES (XSTRING (attribute))
2627 + 3);
2629 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2630 + STRING_BYTES (XSTRING (class))
2631 + (STRINGP (subclass)
2632 ? STRING_BYTES (XSTRING (subclass)) : 0)
2633 + 3);
2635 /* Start with emacs.FRAMENAME for the name (the specific one)
2636 and with `Emacs' for the class key (the general one). */
2637 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2638 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2640 strcat (class_key, ".");
2641 strcat (class_key, XSTRING (class)->data);
2643 if (!NILP (component))
2645 strcat (class_key, ".");
2646 strcat (class_key, XSTRING (subclass)->data);
2648 strcat (name_key, ".");
2649 strcat (name_key, XSTRING (component)->data);
2652 strcat (name_key, ".");
2653 strcat (name_key, XSTRING (attribute)->data);
2655 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2657 if (value != (char *) 0)
2658 return build_string (value);
2659 else
2660 return Qnil;
2663 /* Used when C code wants a resource value. */
2665 char *
2666 x_get_resource_string (attribute, class)
2667 char *attribute, *class;
2669 char *name_key;
2670 char *class_key;
2671 struct frame *sf = SELECTED_FRAME ();
2673 /* Allocate space for the components, the dots which separate them,
2674 and the final '\0'. */
2675 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2676 + strlen (attribute) + 2);
2677 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2678 + strlen (class) + 2);
2680 sprintf (name_key, "%s.%s",
2681 XSTRING (Vinvocation_name)->data,
2682 attribute);
2683 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2685 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2686 name_key, class_key);
2689 /* Types we might convert a resource string into. */
2690 enum resource_types
2692 RES_TYPE_NUMBER,
2693 RES_TYPE_FLOAT,
2694 RES_TYPE_BOOLEAN,
2695 RES_TYPE_STRING,
2696 RES_TYPE_SYMBOL
2699 /* Return the value of parameter PARAM.
2701 First search ALIST, then Vdefault_frame_alist, then the X defaults
2702 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2704 Convert the resource to the type specified by desired_type.
2706 If no default is specified, return Qunbound. If you call
2707 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2708 and don't let it get stored in any Lisp-visible variables! */
2710 static Lisp_Object
2711 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2712 struct x_display_info *dpyinfo;
2713 Lisp_Object alist, param;
2714 char *attribute;
2715 char *class;
2716 enum resource_types type;
2718 register Lisp_Object tem;
2720 tem = Fassq (param, alist);
2721 if (EQ (tem, Qnil))
2722 tem = Fassq (param, Vdefault_frame_alist);
2723 if (EQ (tem, Qnil))
2726 if (attribute)
2728 tem = display_x_get_resource (dpyinfo,
2729 build_string (attribute),
2730 build_string (class),
2731 Qnil, Qnil);
2733 if (NILP (tem))
2734 return Qunbound;
2736 switch (type)
2738 case RES_TYPE_NUMBER:
2739 return make_number (atoi (XSTRING (tem)->data));
2741 case RES_TYPE_FLOAT:
2742 return make_float (atof (XSTRING (tem)->data));
2744 case RES_TYPE_BOOLEAN:
2745 tem = Fdowncase (tem);
2746 if (!strcmp (XSTRING (tem)->data, "on")
2747 || !strcmp (XSTRING (tem)->data, "true"))
2748 return Qt;
2749 else
2750 return Qnil;
2752 case RES_TYPE_STRING:
2753 return tem;
2755 case RES_TYPE_SYMBOL:
2756 /* As a special case, we map the values `true' and `on'
2757 to Qt, and `false' and `off' to Qnil. */
2759 Lisp_Object lower;
2760 lower = Fdowncase (tem);
2761 if (!strcmp (XSTRING (lower)->data, "on")
2762 || !strcmp (XSTRING (lower)->data, "true"))
2763 return Qt;
2764 else if (!strcmp (XSTRING (lower)->data, "off")
2765 || !strcmp (XSTRING (lower)->data, "false"))
2766 return Qnil;
2767 else
2768 return Fintern (tem, Qnil);
2771 default:
2772 abort ();
2775 else
2776 return Qunbound;
2778 return Fcdr (tem);
2781 /* Like x_get_arg, but also record the value in f->param_alist. */
2783 static Lisp_Object
2784 x_get_and_record_arg (f, alist, param, attribute, class, type)
2785 struct frame *f;
2786 Lisp_Object alist, param;
2787 char *attribute;
2788 char *class;
2789 enum resource_types type;
2791 Lisp_Object value;
2793 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2794 attribute, class, type);
2795 if (! NILP (value))
2796 store_frame_param (f, param, value);
2798 return value;
2801 /* Record in frame F the specified or default value according to ALIST
2802 of the parameter named PROP (a Lisp symbol).
2803 If no value is specified for PROP, look for an X default for XPROP
2804 on the frame named NAME.
2805 If that is not found either, use the value DEFLT. */
2807 static Lisp_Object
2808 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2809 struct frame *f;
2810 Lisp_Object alist;
2811 Lisp_Object prop;
2812 Lisp_Object deflt;
2813 char *xprop;
2814 char *xclass;
2815 enum resource_types type;
2817 Lisp_Object tem;
2819 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2820 if (EQ (tem, Qunbound))
2821 tem = deflt;
2822 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2823 return tem;
2827 /* Record in frame F the specified or default value according to ALIST
2828 of the parameter named PROP (a Lisp symbol). If no value is
2829 specified for PROP, look for an X default for XPROP on the frame
2830 named NAME. If that is not found either, use the value DEFLT. */
2832 static Lisp_Object
2833 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2834 foreground_p)
2835 struct frame *f;
2836 Lisp_Object alist;
2837 Lisp_Object prop;
2838 char *xprop;
2839 char *xclass;
2840 int foreground_p;
2842 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2843 Lisp_Object tem;
2845 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2846 if (EQ (tem, Qunbound))
2848 #ifdef USE_TOOLKIT_SCROLL_BARS
2850 /* See if an X resource for the scroll bar color has been
2851 specified. */
2852 tem = display_x_get_resource (dpyinfo,
2853 build_string (foreground_p
2854 ? "foreground"
2855 : "background"),
2856 build_string (""),
2857 build_string ("verticalScrollBar"),
2858 build_string (""));
2859 if (!STRINGP (tem))
2861 /* If nothing has been specified, scroll bars will use a
2862 toolkit-dependent default. Because these defaults are
2863 difficult to get at without actually creating a scroll
2864 bar, use nil to indicate that no color has been
2865 specified. */
2866 tem = Qnil;
2869 #else /* not USE_TOOLKIT_SCROLL_BARS */
2871 tem = Qnil;
2873 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2876 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2877 return tem;
2882 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2883 "Parse an X-style geometry string STRING.\n\
2884 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2885 The properties returned may include `top', `left', `height', and `width'.\n\
2886 The value of `left' or `top' may be an integer,\n\
2887 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2888 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2889 (string)
2890 Lisp_Object string;
2892 int geometry, x, y;
2893 unsigned int width, height;
2894 Lisp_Object result;
2896 CHECK_STRING (string, 0);
2898 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2899 &x, &y, &width, &height);
2901 #if 0
2902 if (!!(geometry & XValue) != !!(geometry & YValue))
2903 error ("Must specify both x and y position, or neither");
2904 #endif
2906 result = Qnil;
2907 if (geometry & XValue)
2909 Lisp_Object element;
2911 if (x >= 0 && (geometry & XNegative))
2912 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2913 else if (x < 0 && ! (geometry & XNegative))
2914 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2915 else
2916 element = Fcons (Qleft, make_number (x));
2917 result = Fcons (element, result);
2920 if (geometry & YValue)
2922 Lisp_Object element;
2924 if (y >= 0 && (geometry & YNegative))
2925 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2926 else if (y < 0 && ! (geometry & YNegative))
2927 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2928 else
2929 element = Fcons (Qtop, make_number (y));
2930 result = Fcons (element, result);
2933 if (geometry & WidthValue)
2934 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2935 if (geometry & HeightValue)
2936 result = Fcons (Fcons (Qheight, make_number (height)), result);
2938 return result;
2941 /* Calculate the desired size and position of this window,
2942 and return the flags saying which aspects were specified.
2944 This function does not make the coordinates positive. */
2946 #define DEFAULT_ROWS 40
2947 #define DEFAULT_COLS 80
2949 static int
2950 x_figure_window_size (f, parms)
2951 struct frame *f;
2952 Lisp_Object parms;
2954 register Lisp_Object tem0, tem1, tem2;
2955 long window_prompting = 0;
2956 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2958 /* Default values if we fall through.
2959 Actually, if that happens we should get
2960 window manager prompting. */
2961 SET_FRAME_WIDTH (f, DEFAULT_COLS);
2962 f->height = DEFAULT_ROWS;
2963 /* Window managers expect that if program-specified
2964 positions are not (0,0), they're intentional, not defaults. */
2965 f->output_data.x->top_pos = 0;
2966 f->output_data.x->left_pos = 0;
2968 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
2969 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
2970 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
2971 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2973 if (!EQ (tem0, Qunbound))
2975 CHECK_NUMBER (tem0, 0);
2976 f->height = XINT (tem0);
2978 if (!EQ (tem1, Qunbound))
2980 CHECK_NUMBER (tem1, 0);
2981 SET_FRAME_WIDTH (f, XINT (tem1));
2983 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2984 window_prompting |= USSize;
2985 else
2986 window_prompting |= PSize;
2989 f->output_data.x->vertical_scroll_bar_extra
2990 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2992 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2993 f->output_data.x->flags_areas_extra
2994 = FRAME_FLAGS_AREA_WIDTH (f);
2995 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2996 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2998 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
2999 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3000 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3001 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3003 if (EQ (tem0, Qminus))
3005 f->output_data.x->top_pos = 0;
3006 window_prompting |= YNegative;
3008 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3009 && CONSP (XCDR (tem0))
3010 && INTEGERP (XCAR (XCDR (tem0))))
3012 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3013 window_prompting |= YNegative;
3015 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3016 && CONSP (XCDR (tem0))
3017 && INTEGERP (XCAR (XCDR (tem0))))
3019 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3021 else if (EQ (tem0, Qunbound))
3022 f->output_data.x->top_pos = 0;
3023 else
3025 CHECK_NUMBER (tem0, 0);
3026 f->output_data.x->top_pos = XINT (tem0);
3027 if (f->output_data.x->top_pos < 0)
3028 window_prompting |= YNegative;
3031 if (EQ (tem1, Qminus))
3033 f->output_data.x->left_pos = 0;
3034 window_prompting |= XNegative;
3036 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3037 && CONSP (XCDR (tem1))
3038 && INTEGERP (XCAR (XCDR (tem1))))
3040 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3041 window_prompting |= XNegative;
3043 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3044 && CONSP (XCDR (tem1))
3045 && INTEGERP (XCAR (XCDR (tem1))))
3047 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3049 else if (EQ (tem1, Qunbound))
3050 f->output_data.x->left_pos = 0;
3051 else
3053 CHECK_NUMBER (tem1, 0);
3054 f->output_data.x->left_pos = XINT (tem1);
3055 if (f->output_data.x->left_pos < 0)
3056 window_prompting |= XNegative;
3059 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3060 window_prompting |= USPosition;
3061 else
3062 window_prompting |= PPosition;
3065 return window_prompting;
3068 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3070 Status
3071 XSetWMProtocols (dpy, w, protocols, count)
3072 Display *dpy;
3073 Window w;
3074 Atom *protocols;
3075 int count;
3077 Atom prop;
3078 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3079 if (prop == None) return False;
3080 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3081 (unsigned char *) protocols, count);
3082 return True;
3084 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3086 #ifdef USE_X_TOOLKIT
3088 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3089 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3090 already be present because of the toolkit (Motif adds some of them,
3091 for example, but Xt doesn't). */
3093 static void
3094 hack_wm_protocols (f, widget)
3095 FRAME_PTR f;
3096 Widget widget;
3098 Display *dpy = XtDisplay (widget);
3099 Window w = XtWindow (widget);
3100 int need_delete = 1;
3101 int need_focus = 1;
3102 int need_save = 1;
3104 BLOCK_INPUT;
3106 Atom type, *atoms = 0;
3107 int format = 0;
3108 unsigned long nitems = 0;
3109 unsigned long bytes_after;
3111 if ((XGetWindowProperty (dpy, w,
3112 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3113 (long)0, (long)100, False, XA_ATOM,
3114 &type, &format, &nitems, &bytes_after,
3115 (unsigned char **) &atoms)
3116 == Success)
3117 && format == 32 && type == XA_ATOM)
3118 while (nitems > 0)
3120 nitems--;
3121 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3122 need_delete = 0;
3123 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3124 need_focus = 0;
3125 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3126 need_save = 0;
3128 if (atoms) XFree ((char *) atoms);
3131 Atom props [10];
3132 int count = 0;
3133 if (need_delete)
3134 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3135 if (need_focus)
3136 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3137 if (need_save)
3138 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3139 if (count)
3140 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3141 XA_ATOM, 32, PropModeAppend,
3142 (unsigned char *) props, count);
3144 UNBLOCK_INPUT;
3146 #endif
3150 /* Support routines for XIC (X Input Context). */
3152 #ifdef HAVE_X_I18N
3154 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3155 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3158 /* Supported XIM styles, ordered by preferenc. */
3160 static XIMStyle supported_xim_styles[] =
3162 XIMPreeditPosition | XIMStatusArea,
3163 XIMPreeditPosition | XIMStatusNothing,
3164 XIMPreeditPosition | XIMStatusNone,
3165 XIMPreeditNothing | XIMStatusArea,
3166 XIMPreeditNothing | XIMStatusNothing,
3167 XIMPreeditNothing | XIMStatusNone,
3168 XIMPreeditNone | XIMStatusArea,
3169 XIMPreeditNone | XIMStatusNothing,
3170 XIMPreeditNone | XIMStatusNone,
3175 /* Create an X fontset on frame F with base font name
3176 BASE_FONTNAME.. */
3178 static XFontSet
3179 xic_create_xfontset (f, base_fontname)
3180 struct frame *f;
3181 char *base_fontname;
3183 XFontSet xfs;
3184 char **missing_list;
3185 int missing_count;
3186 char *def_string;
3188 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3189 base_fontname, &missing_list,
3190 &missing_count, &def_string);
3191 if (missing_list)
3192 XFreeStringList (missing_list);
3194 /* No need to free def_string. */
3195 return xfs;
3199 /* Value is the best input style, given user preferences USER (already
3200 checked to be supported by Emacs), and styles supported by the
3201 input method XIM. */
3203 static XIMStyle
3204 best_xim_style (user, xim)
3205 XIMStyles *user;
3206 XIMStyles *xim;
3208 int i, j;
3210 for (i = 0; i < user->count_styles; ++i)
3211 for (j = 0; j < xim->count_styles; ++j)
3212 if (user->supported_styles[i] == xim->supported_styles[j])
3213 return user->supported_styles[i];
3215 /* Return the default style. */
3216 return XIMPreeditNothing | XIMStatusNothing;
3219 /* Create XIC for frame F. */
3221 void
3222 create_frame_xic (f)
3223 struct frame *f;
3225 XIM xim;
3226 XIC xic = NULL;
3227 XFontSet xfs = NULL;
3228 static XIMStyle xic_style;
3230 if (FRAME_XIC (f))
3231 return;
3233 xim = FRAME_X_XIM (f);
3234 if (xim)
3236 XRectangle s_area;
3237 XPoint spot;
3238 XVaNestedList preedit_attr;
3239 XVaNestedList status_attr;
3240 char *base_fontname;
3241 int fontset;
3243 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3244 spot.x = 0; spot.y = 1;
3245 /* Create X fontset. */
3246 fontset = FRAME_FONTSET (f);
3247 if (fontset < 0)
3248 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3249 else
3251 /* Determine the base fontname from the ASCII font name of
3252 FONTSET. */
3253 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3254 char *p = ascii_font;
3255 int i;
3257 for (i = 0; *p; p++)
3258 if (*p == '-') i++;
3259 if (i != 14)
3260 /* As the font name doesn't conform to XLFD, we can't
3261 modify it to get a suitable base fontname for the
3262 frame. */
3263 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3264 else
3266 int len = strlen (ascii_font) + 1;
3267 char *p1;
3269 for (i = 0, p = ascii_font; i < 8; p++)
3271 if (*p == '-')
3273 i++;
3274 if (i == 3)
3275 p1 = p + 1;
3278 base_fontname = (char *) alloca (len);
3279 bzero (base_fontname, len);
3280 strcpy (base_fontname, "-*-*-");
3281 bcopy (p1, base_fontname + 5, p - p1);
3282 strcat (base_fontname, "*-*-*-*-*-*-*");
3285 xfs = xic_create_xfontset (f, base_fontname);
3287 /* Determine XIC style. */
3288 if (xic_style == 0)
3290 XIMStyles supported_list;
3291 supported_list.count_styles = (sizeof supported_xim_styles
3292 / sizeof supported_xim_styles[0]);
3293 supported_list.supported_styles = supported_xim_styles;
3294 xic_style = best_xim_style (&supported_list,
3295 FRAME_X_XIM_STYLES (f));
3298 preedit_attr = XVaCreateNestedList (0,
3299 XNFontSet, xfs,
3300 XNForeground,
3301 FRAME_FOREGROUND_PIXEL (f),
3302 XNBackground,
3303 FRAME_BACKGROUND_PIXEL (f),
3304 (xic_style & XIMPreeditPosition
3305 ? XNSpotLocation
3306 : NULL),
3307 &spot,
3308 NULL);
3309 status_attr = XVaCreateNestedList (0,
3310 XNArea,
3311 &s_area,
3312 XNFontSet,
3313 xfs,
3314 XNForeground,
3315 FRAME_FOREGROUND_PIXEL (f),
3316 XNBackground,
3317 FRAME_BACKGROUND_PIXEL (f),
3318 NULL);
3320 xic = XCreateIC (xim,
3321 XNInputStyle, xic_style,
3322 XNClientWindow, FRAME_X_WINDOW(f),
3323 XNFocusWindow, FRAME_X_WINDOW(f),
3324 XNStatusAttributes, status_attr,
3325 XNPreeditAttributes, preedit_attr,
3326 NULL);
3327 XFree (preedit_attr);
3328 XFree (status_attr);
3331 FRAME_XIC (f) = xic;
3332 FRAME_XIC_STYLE (f) = xic_style;
3333 FRAME_XIC_FONTSET (f) = xfs;
3337 /* Destroy XIC and free XIC fontset of frame F, if any. */
3339 void
3340 free_frame_xic (f)
3341 struct frame *f;
3343 if (FRAME_XIC (f) == NULL)
3344 return;
3346 XDestroyIC (FRAME_XIC (f));
3347 if (FRAME_XIC_FONTSET (f))
3348 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3350 FRAME_XIC (f) = NULL;
3351 FRAME_XIC_FONTSET (f) = NULL;
3355 /* Place preedit area for XIC of window W's frame to specified
3356 pixel position X/Y. X and Y are relative to window W. */
3358 void
3359 xic_set_preeditarea (w, x, y)
3360 struct window *w;
3361 int x, y;
3363 struct frame *f = XFRAME (w->frame);
3364 XVaNestedList attr;
3365 XPoint spot;
3367 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3368 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3369 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3370 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3371 XFree (attr);
3375 /* Place status area for XIC in bottom right corner of frame F.. */
3377 void
3378 xic_set_statusarea (f)
3379 struct frame *f;
3381 XIC xic = FRAME_XIC (f);
3382 XVaNestedList attr;
3383 XRectangle area;
3384 XRectangle *needed;
3386 /* Negotiate geometry of status area. If input method has existing
3387 status area, use its current size. */
3388 area.x = area.y = area.width = area.height = 0;
3389 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3390 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3391 XFree (attr);
3393 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3394 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3395 XFree (attr);
3397 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3399 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3400 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3401 XFree (attr);
3404 area.width = needed->width;
3405 area.height = needed->height;
3406 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3407 area.y = (PIXEL_HEIGHT (f) - area.height
3408 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3409 XFree (needed);
3411 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3412 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3413 XFree (attr);
3417 /* Set X fontset for XIC of frame F, using base font name
3418 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3420 void
3421 xic_set_xfontset (f, base_fontname)
3422 struct frame *f;
3423 char *base_fontname;
3425 XVaNestedList attr;
3426 XFontSet xfs;
3428 xfs = xic_create_xfontset (f, base_fontname);
3430 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3431 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3432 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3433 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3434 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3435 XFree (attr);
3437 if (FRAME_XIC_FONTSET (f))
3438 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3439 FRAME_XIC_FONTSET (f) = xfs;
3442 #endif /* HAVE_X_I18N */
3446 #ifdef USE_X_TOOLKIT
3448 /* Create and set up the X widget for frame F. */
3450 static void
3451 x_window (f, window_prompting, minibuffer_only)
3452 struct frame *f;
3453 long window_prompting;
3454 int minibuffer_only;
3456 XClassHint class_hints;
3457 XSetWindowAttributes attributes;
3458 unsigned long attribute_mask;
3459 Widget shell_widget;
3460 Widget pane_widget;
3461 Widget frame_widget;
3462 Arg al [25];
3463 int ac;
3465 BLOCK_INPUT;
3467 /* Use the resource name as the top-level widget name
3468 for looking up resources. Make a non-Lisp copy
3469 for the window manager, so GC relocation won't bother it.
3471 Elsewhere we specify the window name for the window manager. */
3474 char *str = (char *) XSTRING (Vx_resource_name)->data;
3475 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3476 strcpy (f->namebuf, str);
3479 ac = 0;
3480 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3481 XtSetArg (al[ac], XtNinput, 1); ac++;
3482 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3483 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3484 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3485 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3486 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3487 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3488 applicationShellWidgetClass,
3489 FRAME_X_DISPLAY (f), al, ac);
3491 f->output_data.x->widget = shell_widget;
3492 /* maybe_set_screen_title_format (shell_widget); */
3494 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3495 (widget_value *) NULL,
3496 shell_widget, False,
3497 (lw_callback) NULL,
3498 (lw_callback) NULL,
3499 (lw_callback) NULL,
3500 (lw_callback) NULL);
3502 ac = 0;
3503 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3504 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3505 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3506 XtSetValues (pane_widget, al, ac);
3507 f->output_data.x->column_widget = pane_widget;
3509 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3510 the emacs screen when changing menubar. This reduces flickering. */
3512 ac = 0;
3513 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3514 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3515 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3516 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3517 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3518 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3519 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3520 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3521 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3522 al, ac);
3524 f->output_data.x->edit_widget = frame_widget;
3526 XtManageChild (frame_widget);
3528 /* Do some needed geometry management. */
3530 int len;
3531 char *tem, shell_position[32];
3532 Arg al[2];
3533 int ac = 0;
3534 int extra_borders = 0;
3535 int menubar_size
3536 = (f->output_data.x->menubar_widget
3537 ? (f->output_data.x->menubar_widget->core.height
3538 + f->output_data.x->menubar_widget->core.border_width)
3539 : 0);
3541 #if 0 /* Experimentally, we now get the right results
3542 for -geometry -0-0 without this. 24 Aug 96, rms. */
3543 if (FRAME_EXTERNAL_MENU_BAR (f))
3545 Dimension ibw = 0;
3546 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3547 menubar_size += ibw;
3549 #endif
3551 f->output_data.x->menubar_height = menubar_size;
3553 #ifndef USE_LUCID
3554 /* Motif seems to need this amount added to the sizes
3555 specified for the shell widget. The Athena/Lucid widgets don't.
3556 Both conclusions reached experimentally. -- rms. */
3557 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3558 &extra_borders, NULL);
3559 extra_borders *= 2;
3560 #endif
3562 /* Convert our geometry parameters into a geometry string
3563 and specify it.
3564 Note that we do not specify here whether the position
3565 is a user-specified or program-specified one.
3566 We pass that information later, in x_wm_set_size_hints. */
3568 int left = f->output_data.x->left_pos;
3569 int xneg = window_prompting & XNegative;
3570 int top = f->output_data.x->top_pos;
3571 int yneg = window_prompting & YNegative;
3572 if (xneg)
3573 left = -left;
3574 if (yneg)
3575 top = -top;
3577 if (window_prompting & USPosition)
3578 sprintf (shell_position, "=%dx%d%c%d%c%d",
3579 PIXEL_WIDTH (f) + extra_borders,
3580 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3581 (xneg ? '-' : '+'), left,
3582 (yneg ? '-' : '+'), top);
3583 else
3584 sprintf (shell_position, "=%dx%d",
3585 PIXEL_WIDTH (f) + extra_borders,
3586 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3589 len = strlen (shell_position) + 1;
3590 /* We don't free this because we don't know whether
3591 it is safe to free it while the frame exists.
3592 It isn't worth the trouble of arranging to free it
3593 when the frame is deleted. */
3594 tem = (char *) xmalloc (len);
3595 strncpy (tem, shell_position, len);
3596 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3597 XtSetValues (shell_widget, al, ac);
3600 XtManageChild (pane_widget);
3601 XtRealizeWidget (shell_widget);
3603 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3605 validate_x_resource_name ();
3607 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3608 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3609 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3611 #ifdef HAVE_X_I18N
3612 FRAME_XIC (f) = NULL;
3613 #ifdef USE_XIM
3614 create_frame_xic (f);
3615 #endif
3616 #endif
3618 f->output_data.x->wm_hints.input = True;
3619 f->output_data.x->wm_hints.flags |= InputHint;
3620 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3621 &f->output_data.x->wm_hints);
3623 hack_wm_protocols (f, shell_widget);
3625 #ifdef HACK_EDITRES
3626 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3627 #endif
3629 /* Do a stupid property change to force the server to generate a
3630 PropertyNotify event so that the event_stream server timestamp will
3631 be initialized to something relevant to the time we created the window.
3633 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3634 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3635 XA_ATOM, 32, PropModeAppend,
3636 (unsigned char*) NULL, 0);
3638 /* Make all the standard events reach the Emacs frame. */
3639 attributes.event_mask = STANDARD_EVENT_SET;
3641 #ifdef HAVE_X_I18N
3642 if (FRAME_XIC (f))
3644 /* XIM server might require some X events. */
3645 unsigned long fevent = NoEventMask;
3646 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3647 attributes.event_mask |= fevent;
3649 #endif /* HAVE_X_I18N */
3651 attribute_mask = CWEventMask;
3652 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3653 attribute_mask, &attributes);
3655 XtMapWidget (frame_widget);
3657 /* x_set_name normally ignores requests to set the name if the
3658 requested name is the same as the current name. This is the one
3659 place where that assumption isn't correct; f->name is set, but
3660 the X server hasn't been told. */
3662 Lisp_Object name;
3663 int explicit = f->explicit_name;
3665 f->explicit_name = 0;
3666 name = f->name;
3667 f->name = Qnil;
3668 x_set_name (f, name, explicit);
3671 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3672 f->output_data.x->text_cursor);
3674 UNBLOCK_INPUT;
3676 /* This is a no-op, except under Motif. Make sure main areas are
3677 set to something reasonable, in case we get an error later. */
3678 lw_set_main_areas (pane_widget, 0, frame_widget);
3681 #else /* not USE_X_TOOLKIT */
3683 /* Create and set up the X window for frame F. */
3685 void
3686 x_window (f)
3687 struct frame *f;
3690 XClassHint class_hints;
3691 XSetWindowAttributes attributes;
3692 unsigned long attribute_mask;
3694 attributes.background_pixel = f->output_data.x->background_pixel;
3695 attributes.border_pixel = f->output_data.x->border_pixel;
3696 attributes.bit_gravity = StaticGravity;
3697 attributes.backing_store = NotUseful;
3698 attributes.save_under = True;
3699 attributes.event_mask = STANDARD_EVENT_SET;
3700 attributes.colormap = FRAME_X_COLORMAP (f);
3701 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3702 | CWColormap);
3704 BLOCK_INPUT;
3705 FRAME_X_WINDOW (f)
3706 = XCreateWindow (FRAME_X_DISPLAY (f),
3707 f->output_data.x->parent_desc,
3708 f->output_data.x->left_pos,
3709 f->output_data.x->top_pos,
3710 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3711 f->output_data.x->border_width,
3712 CopyFromParent, /* depth */
3713 InputOutput, /* class */
3714 FRAME_X_VISUAL (f),
3715 attribute_mask, &attributes);
3717 #ifdef HAVE_X_I18N
3718 #ifdef USE_XIM
3719 create_frame_xic (f);
3720 if (FRAME_XIC (f))
3722 /* XIM server might require some X events. */
3723 unsigned long fevent = NoEventMask;
3724 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3725 attributes.event_mask |= fevent;
3726 attribute_mask = CWEventMask;
3727 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3728 attribute_mask, &attributes);
3730 #endif
3731 #endif /* HAVE_X_I18N */
3733 validate_x_resource_name ();
3735 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3736 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3737 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3739 /* The menubar is part of the ordinary display;
3740 it does not count in addition to the height of the window. */
3741 f->output_data.x->menubar_height = 0;
3743 /* This indicates that we use the "Passive Input" input model.
3744 Unless we do this, we don't get the Focus{In,Out} events that we
3745 need to draw the cursor correctly. Accursed bureaucrats.
3746 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3748 f->output_data.x->wm_hints.input = True;
3749 f->output_data.x->wm_hints.flags |= InputHint;
3750 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3751 &f->output_data.x->wm_hints);
3752 f->output_data.x->wm_hints.icon_pixmap = None;
3754 /* Request "save yourself" and "delete window" commands from wm. */
3756 Atom protocols[2];
3757 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3758 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3759 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3762 /* x_set_name normally ignores requests to set the name if the
3763 requested name is the same as the current name. This is the one
3764 place where that assumption isn't correct; f->name is set, but
3765 the X server hasn't been told. */
3767 Lisp_Object name;
3768 int explicit = f->explicit_name;
3770 f->explicit_name = 0;
3771 name = f->name;
3772 f->name = Qnil;
3773 x_set_name (f, name, explicit);
3776 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3777 f->output_data.x->text_cursor);
3779 UNBLOCK_INPUT;
3781 if (FRAME_X_WINDOW (f) == 0)
3782 error ("Unable to create window");
3785 #endif /* not USE_X_TOOLKIT */
3787 /* Handle the icon stuff for this window. Perhaps later we might
3788 want an x_set_icon_position which can be called interactively as
3789 well. */
3791 static void
3792 x_icon (f, parms)
3793 struct frame *f;
3794 Lisp_Object parms;
3796 Lisp_Object icon_x, icon_y;
3797 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3799 /* Set the position of the icon. Note that twm groups all
3800 icons in an icon window. */
3801 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3802 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3803 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3805 CHECK_NUMBER (icon_x, 0);
3806 CHECK_NUMBER (icon_y, 0);
3808 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3809 error ("Both left and top icon corners of icon must be specified");
3811 BLOCK_INPUT;
3813 if (! EQ (icon_x, Qunbound))
3814 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3816 /* Start up iconic or window? */
3817 x_wm_set_window_state
3818 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3819 Qicon)
3820 ? IconicState
3821 : NormalState));
3823 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3824 ? f->icon_name
3825 : f->name))->data);
3827 UNBLOCK_INPUT;
3830 /* Make the GC's needed for this window, setting the
3831 background, border and mouse colors; also create the
3832 mouse cursor and the gray border tile. */
3834 static char cursor_bits[] =
3836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3842 static void
3843 x_make_gc (f)
3844 struct frame *f;
3846 XGCValues gc_values;
3848 BLOCK_INPUT;
3850 /* Create the GC's of this frame.
3851 Note that many default values are used. */
3853 /* Normal video */
3854 gc_values.font = f->output_data.x->font->fid;
3855 gc_values.foreground = f->output_data.x->foreground_pixel;
3856 gc_values.background = f->output_data.x->background_pixel;
3857 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3858 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
3859 FRAME_X_WINDOW (f),
3860 GCLineWidth | GCFont
3861 | GCForeground | GCBackground,
3862 &gc_values);
3864 /* Reverse video style. */
3865 gc_values.foreground = f->output_data.x->background_pixel;
3866 gc_values.background = f->output_data.x->foreground_pixel;
3867 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
3868 FRAME_X_WINDOW (f),
3869 GCFont | GCForeground | GCBackground
3870 | GCLineWidth,
3871 &gc_values);
3873 /* Cursor has cursor-color background, background-color foreground. */
3874 gc_values.foreground = f->output_data.x->background_pixel;
3875 gc_values.background = f->output_data.x->cursor_pixel;
3876 gc_values.fill_style = FillOpaqueStippled;
3877 gc_values.stipple
3878 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3879 FRAME_X_DISPLAY_INFO (f)->root_window,
3880 cursor_bits, 16, 16);
3881 f->output_data.x->cursor_gc
3882 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3883 (GCFont | GCForeground | GCBackground
3884 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3885 &gc_values);
3887 /* Reliefs. */
3888 f->output_data.x->white_relief.gc = 0;
3889 f->output_data.x->black_relief.gc = 0;
3891 /* Create the gray border tile used when the pointer is not in
3892 the frame. Since this depends on the frame's pixel values,
3893 this must be done on a per-frame basis. */
3894 f->output_data.x->border_tile
3895 = (XCreatePixmapFromBitmapData
3896 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3897 gray_bits, gray_width, gray_height,
3898 f->output_data.x->foreground_pixel,
3899 f->output_data.x->background_pixel,
3900 DefaultDepth (FRAME_X_DISPLAY (f),
3901 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3903 UNBLOCK_INPUT;
3906 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3907 1, 1, 0,
3908 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3909 Returns an Emacs frame object.\n\
3910 ALIST is an alist of frame parameters.\n\
3911 If the parameters specify that the frame should not have a minibuffer,\n\
3912 and do not specify a specific minibuffer window to use,\n\
3913 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3914 be shared by the new frame.\n\
3916 This function is an internal primitive--use `make-frame' instead.")
3917 (parms)
3918 Lisp_Object parms;
3920 struct frame *f;
3921 Lisp_Object frame, tem;
3922 Lisp_Object name;
3923 int minibuffer_only = 0;
3924 long window_prompting = 0;
3925 int width, height;
3926 int count = specpdl_ptr - specpdl;
3927 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3928 Lisp_Object display;
3929 struct x_display_info *dpyinfo = NULL;
3930 Lisp_Object parent;
3931 struct kboard *kb;
3933 check_x ();
3935 /* Use this general default value to start with
3936 until we know if this frame has a specified name. */
3937 Vx_resource_name = Vinvocation_name;
3939 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3940 if (EQ (display, Qunbound))
3941 display = Qnil;
3942 dpyinfo = check_x_display_info (display);
3943 #ifdef MULTI_KBOARD
3944 kb = dpyinfo->kboard;
3945 #else
3946 kb = &the_only_kboard;
3947 #endif
3949 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3950 if (!STRINGP (name)
3951 && ! EQ (name, Qunbound)
3952 && ! NILP (name))
3953 error ("Invalid frame name--not a string or nil");
3955 if (STRINGP (name))
3956 Vx_resource_name = name;
3958 /* See if parent window is specified. */
3959 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3960 if (EQ (parent, Qunbound))
3961 parent = Qnil;
3962 if (! NILP (parent))
3963 CHECK_NUMBER (parent, 0);
3965 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3966 /* No need to protect DISPLAY because that's not used after passing
3967 it to make_frame_without_minibuffer. */
3968 frame = Qnil;
3969 GCPRO4 (parms, parent, name, frame);
3970 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3971 RES_TYPE_SYMBOL);
3972 if (EQ (tem, Qnone) || NILP (tem))
3973 f = make_frame_without_minibuffer (Qnil, kb, display);
3974 else if (EQ (tem, Qonly))
3976 f = make_minibuffer_frame ();
3977 minibuffer_only = 1;
3979 else if (WINDOWP (tem))
3980 f = make_frame_without_minibuffer (tem, kb, display);
3981 else
3982 f = make_frame (1);
3984 XSETFRAME (frame, f);
3986 /* Note that X Windows does support scroll bars. */
3987 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3989 f->output_method = output_x_window;
3990 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3991 bzero (f->output_data.x, sizeof (struct x_output));
3992 f->output_data.x->icon_bitmap = -1;
3993 f->output_data.x->fontset = -1;
3994 f->output_data.x->scroll_bar_foreground_pixel = -1;
3995 f->output_data.x->scroll_bar_background_pixel = -1;
3997 f->icon_name
3998 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3999 RES_TYPE_STRING);
4000 if (! STRINGP (f->icon_name))
4001 f->icon_name = Qnil;
4003 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4004 #ifdef MULTI_KBOARD
4005 FRAME_KBOARD (f) = kb;
4006 #endif
4008 /* These colors will be set anyway later, but it's important
4009 to get the color reference counts right, so initialize them! */
4011 Lisp_Object black;
4012 struct gcpro gcpro1;
4014 black = build_string ("black");
4015 GCPRO1 (black);
4016 f->output_data.x->foreground_pixel
4017 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4018 f->output_data.x->background_pixel
4019 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4020 f->output_data.x->cursor_pixel
4021 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4022 f->output_data.x->cursor_foreground_pixel
4023 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4024 f->output_data.x->border_pixel
4025 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4026 f->output_data.x->mouse_pixel
4027 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4028 UNGCPRO;
4031 /* Specify the parent under which to make this X window. */
4033 if (!NILP (parent))
4035 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4036 f->output_data.x->explicit_parent = 1;
4038 else
4040 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4041 f->output_data.x->explicit_parent = 0;
4044 /* Set the name; the functions to which we pass f expect the name to
4045 be set. */
4046 if (EQ (name, Qunbound) || NILP (name))
4048 f->name = build_string (dpyinfo->x_id_name);
4049 f->explicit_name = 0;
4051 else
4053 f->name = name;
4054 f->explicit_name = 1;
4055 /* use the frame's title when getting resources for this frame. */
4056 specbind (Qx_resource_name, name);
4059 /* Extract the window parameters from the supplied values
4060 that are needed to determine window geometry. */
4062 Lisp_Object font;
4064 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4066 BLOCK_INPUT;
4067 /* First, try whatever font the caller has specified. */
4068 if (STRINGP (font))
4070 tem = Fquery_fontset (font, Qnil);
4071 if (STRINGP (tem))
4072 font = x_new_fontset (f, XSTRING (tem)->data);
4073 else
4074 font = x_new_font (f, XSTRING (font)->data);
4077 /* Try out a font which we hope has bold and italic variations. */
4078 if (!STRINGP (font))
4079 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4080 if (!STRINGP (font))
4081 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4082 if (! STRINGP (font))
4083 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4084 if (! STRINGP (font))
4085 /* This was formerly the first thing tried, but it finds too many fonts
4086 and takes too long. */
4087 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4088 /* If those didn't work, look for something which will at least work. */
4089 if (! STRINGP (font))
4090 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4091 UNBLOCK_INPUT;
4092 if (! STRINGP (font))
4093 font = build_string ("fixed");
4095 x_default_parameter (f, parms, Qfont, font,
4096 "font", "Font", RES_TYPE_STRING);
4099 #ifdef USE_LUCID
4100 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4101 whereby it fails to get any font. */
4102 xlwmenu_default_font = f->output_data.x->font;
4103 #endif
4105 x_default_parameter (f, parms, Qborder_width, make_number (2),
4106 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4108 /* This defaults to 2 in order to match xterm. We recognize either
4109 internalBorderWidth or internalBorder (which is what xterm calls
4110 it). */
4111 if (NILP (Fassq (Qinternal_border_width, parms)))
4113 Lisp_Object value;
4115 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4116 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4117 if (! EQ (value, Qunbound))
4118 parms = Fcons (Fcons (Qinternal_border_width, value),
4119 parms);
4121 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4122 "internalBorderWidth", "internalBorderWidth",
4123 RES_TYPE_NUMBER);
4124 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4125 "verticalScrollBars", "ScrollBars",
4126 RES_TYPE_SYMBOL);
4128 /* Also do the stuff which must be set before the window exists. */
4129 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4130 "foreground", "Foreground", RES_TYPE_STRING);
4131 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4132 "background", "Background", RES_TYPE_STRING);
4133 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4134 "pointerColor", "Foreground", RES_TYPE_STRING);
4135 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4136 "cursorColor", "Foreground", RES_TYPE_STRING);
4137 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4138 "borderColor", "BorderColor", RES_TYPE_STRING);
4139 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4140 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4141 x_default_parameter (f, parms, Qline_spacing, Qnil,
4142 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4144 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4145 "scrollBarForeground",
4146 "ScrollBarForeground", 1);
4147 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4148 "scrollBarBackground",
4149 "ScrollBarBackground", 0);
4151 /* Init faces before x_default_parameter is called for scroll-bar
4152 parameters because that function calls x_set_scroll_bar_width,
4153 which calls change_frame_size, which calls Fset_window_buffer,
4154 which runs hooks, which call Fvertical_motion. At the end, we
4155 end up in init_iterator with a null face cache, which should not
4156 happen. */
4157 init_frame_faces (f);
4159 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4160 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4161 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
4162 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4163 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4164 "bufferPredicate", "BufferPredicate",
4165 RES_TYPE_SYMBOL);
4166 x_default_parameter (f, parms, Qtitle, Qnil,
4167 "title", "Title", RES_TYPE_STRING);
4169 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4170 window_prompting = x_figure_window_size (f, parms);
4172 if (window_prompting & XNegative)
4174 if (window_prompting & YNegative)
4175 f->output_data.x->win_gravity = SouthEastGravity;
4176 else
4177 f->output_data.x->win_gravity = NorthEastGravity;
4179 else
4181 if (window_prompting & YNegative)
4182 f->output_data.x->win_gravity = SouthWestGravity;
4183 else
4184 f->output_data.x->win_gravity = NorthWestGravity;
4187 f->output_data.x->size_hint_flags = window_prompting;
4189 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4190 f->no_split = minibuffer_only || EQ (tem, Qt);
4192 /* Create the X widget or window. Add the tool-bar height to the
4193 initial frame height so that the user gets a text display area of
4194 the size he specified with -g or via .Xdefaults. Later changes
4195 of the tool-bar height don't change the frame size. This is done
4196 so that users can create tall Emacs frames without having to
4197 guess how tall the tool-bar will get. */
4198 f->height += FRAME_TOOL_BAR_LINES (f);
4200 #ifdef USE_X_TOOLKIT
4201 x_window (f, window_prompting, minibuffer_only);
4202 #else
4203 x_window (f);
4204 #endif
4206 x_icon (f, parms);
4207 x_make_gc (f);
4209 /* Now consider the frame official. */
4210 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4211 Vframe_list = Fcons (frame, Vframe_list);
4213 /* We need to do this after creating the X window, so that the
4214 icon-creation functions can say whose icon they're describing. */
4215 x_default_parameter (f, parms, Qicon_type, Qnil,
4216 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4218 x_default_parameter (f, parms, Qauto_raise, Qnil,
4219 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4220 x_default_parameter (f, parms, Qauto_lower, Qnil,
4221 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4222 x_default_parameter (f, parms, Qcursor_type, Qbox,
4223 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4224 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4225 "scrollBarWidth", "ScrollBarWidth",
4226 RES_TYPE_NUMBER);
4228 /* Dimensions, especially f->height, must be done via change_frame_size.
4229 Change will not be effected unless different from the current
4230 f->height. */
4231 width = f->width;
4232 height = f->height;
4233 f->height = 0;
4234 SET_FRAME_WIDTH (f, 0);
4235 change_frame_size (f, height, width, 1, 0, 0);
4237 /* Set up faces after all frame parameters are known. */
4238 call1 (Qface_set_after_frame_default, frame);
4240 #ifdef USE_X_TOOLKIT
4241 /* Create the menu bar. */
4242 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4244 /* If this signals an error, we haven't set size hints for the
4245 frame and we didn't make it visible. */
4246 initialize_frame_menubar (f);
4248 /* This is a no-op, except under Motif where it arranges the
4249 main window for the widgets on it. */
4250 lw_set_main_areas (f->output_data.x->column_widget,
4251 f->output_data.x->menubar_widget,
4252 f->output_data.x->edit_widget);
4254 #endif /* USE_X_TOOLKIT */
4256 /* Tell the server what size and position, etc, we want, and how
4257 badly we want them. This should be done after we have the menu
4258 bar so that its size can be taken into account. */
4259 BLOCK_INPUT;
4260 x_wm_set_size_hint (f, window_prompting, 0);
4261 UNBLOCK_INPUT;
4263 /* Make the window appear on the frame and enable display, unless
4264 the caller says not to. However, with explicit parent, Emacs
4265 cannot control visibility, so don't try. */
4266 if (! f->output_data.x->explicit_parent)
4268 Lisp_Object visibility;
4270 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4271 RES_TYPE_SYMBOL);
4272 if (EQ (visibility, Qunbound))
4273 visibility = Qt;
4275 if (EQ (visibility, Qicon))
4276 x_iconify_frame (f);
4277 else if (! NILP (visibility))
4278 x_make_frame_visible (f);
4279 else
4280 /* Must have been Qnil. */
4284 UNGCPRO;
4285 return unbind_to (count, frame);
4288 /* FRAME is used only to get a handle on the X display. We don't pass the
4289 display info directly because we're called from frame.c, which doesn't
4290 know about that structure. */
4292 Lisp_Object
4293 x_get_focus_frame (frame)
4294 struct frame *frame;
4296 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4297 Lisp_Object xfocus;
4298 if (! dpyinfo->x_focus_frame)
4299 return Qnil;
4301 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4302 return xfocus;
4306 /* In certain situations, when the window manager follows a
4307 click-to-focus policy, there seems to be no way around calling
4308 XSetInputFocus to give another frame the input focus .
4310 In an ideal world, XSetInputFocus should generally be avoided so
4311 that applications don't interfere with the window manager's focus
4312 policy. But I think it's okay to use when it's clearly done
4313 following a user-command. */
4315 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4316 "Set the input focus to FRAME.\n\
4317 FRAME nil means use the selected frame.")
4318 (frame)
4319 Lisp_Object frame;
4321 struct frame *f = check_x_frame (frame);
4322 Display *dpy = FRAME_X_DISPLAY (f);
4323 int count;
4325 BLOCK_INPUT;
4326 count = x_catch_errors (dpy);
4327 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4328 RevertToParent, CurrentTime);
4329 x_uncatch_errors (dpy, count);
4330 UNBLOCK_INPUT;
4332 return Qnil;
4336 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4337 "Internal function called by `color-defined-p', which see.")
4338 (color, frame)
4339 Lisp_Object color, frame;
4341 XColor foo;
4342 FRAME_PTR f = check_x_frame (frame);
4344 CHECK_STRING (color, 1);
4346 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4347 return Qt;
4348 else
4349 return Qnil;
4352 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4353 "Internal function called by `color-values', which see.")
4354 (color, frame)
4355 Lisp_Object color, frame;
4357 XColor foo;
4358 FRAME_PTR f = check_x_frame (frame);
4360 CHECK_STRING (color, 1);
4362 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4364 Lisp_Object rgb[3];
4366 rgb[0] = make_number (foo.red);
4367 rgb[1] = make_number (foo.green);
4368 rgb[2] = make_number (foo.blue);
4369 return Flist (3, rgb);
4371 else
4372 return Qnil;
4375 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4376 "Internal function called by `display-color-p', which see.")
4377 (display)
4378 Lisp_Object display;
4380 struct x_display_info *dpyinfo = check_x_display_info (display);
4382 if (dpyinfo->n_planes <= 2)
4383 return Qnil;
4385 switch (dpyinfo->visual->class)
4387 case StaticColor:
4388 case PseudoColor:
4389 case TrueColor:
4390 case DirectColor:
4391 return Qt;
4393 default:
4394 return Qnil;
4398 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4399 0, 1, 0,
4400 "Return t if the X display supports shades of gray.\n\
4401 Note that color displays do support shades of gray.\n\
4402 The optional argument DISPLAY specifies which display to ask about.\n\
4403 DISPLAY should be either a frame or a display name (a string).\n\
4404 If omitted or nil, that stands for the selected frame's display.")
4405 (display)
4406 Lisp_Object display;
4408 struct x_display_info *dpyinfo = check_x_display_info (display);
4410 if (dpyinfo->n_planes <= 1)
4411 return Qnil;
4413 switch (dpyinfo->visual->class)
4415 case StaticColor:
4416 case PseudoColor:
4417 case TrueColor:
4418 case DirectColor:
4419 case StaticGray:
4420 case GrayScale:
4421 return Qt;
4423 default:
4424 return Qnil;
4428 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4429 0, 1, 0,
4430 "Returns the width in pixels of the X display DISPLAY.\n\
4431 The optional argument DISPLAY specifies which display to ask about.\n\
4432 DISPLAY should be either a frame or a display name (a string).\n\
4433 If omitted or nil, that stands for the selected frame's display.")
4434 (display)
4435 Lisp_Object display;
4437 struct x_display_info *dpyinfo = check_x_display_info (display);
4439 return make_number (dpyinfo->width);
4442 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4443 Sx_display_pixel_height, 0, 1, 0,
4444 "Returns the height in pixels of the X display DISPLAY.\n\
4445 The optional argument DISPLAY specifies which display to ask about.\n\
4446 DISPLAY should be either a frame or a display name (a string).\n\
4447 If omitted or nil, that stands for the selected frame's display.")
4448 (display)
4449 Lisp_Object display;
4451 struct x_display_info *dpyinfo = check_x_display_info (display);
4453 return make_number (dpyinfo->height);
4456 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4457 0, 1, 0,
4458 "Returns the number of bitplanes of the X display DISPLAY.\n\
4459 The optional argument DISPLAY specifies which display to ask about.\n\
4460 DISPLAY should be either a frame or a display name (a string).\n\
4461 If omitted or nil, that stands for the selected frame's display.")
4462 (display)
4463 Lisp_Object display;
4465 struct x_display_info *dpyinfo = check_x_display_info (display);
4467 return make_number (dpyinfo->n_planes);
4470 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4471 0, 1, 0,
4472 "Returns the number of color cells of the X display DISPLAY.\n\
4473 The optional argument DISPLAY specifies which display to ask about.\n\
4474 DISPLAY should be either a frame or a display name (a string).\n\
4475 If omitted or nil, that stands for the selected frame's display.")
4476 (display)
4477 Lisp_Object display;
4479 struct x_display_info *dpyinfo = check_x_display_info (display);
4481 return make_number (DisplayCells (dpyinfo->display,
4482 XScreenNumberOfScreen (dpyinfo->screen)));
4485 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4486 Sx_server_max_request_size,
4487 0, 1, 0,
4488 "Returns the maximum request size of the X server of display DISPLAY.\n\
4489 The optional argument DISPLAY specifies which display to ask about.\n\
4490 DISPLAY should be either a frame or a display name (a string).\n\
4491 If omitted or nil, that stands for the selected frame's display.")
4492 (display)
4493 Lisp_Object display;
4495 struct x_display_info *dpyinfo = check_x_display_info (display);
4497 return make_number (MAXREQUEST (dpyinfo->display));
4500 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4501 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4502 The optional argument DISPLAY specifies which display to ask about.\n\
4503 DISPLAY should be either a frame or a display name (a string).\n\
4504 If omitted or nil, that stands for the selected frame's display.")
4505 (display)
4506 Lisp_Object display;
4508 struct x_display_info *dpyinfo = check_x_display_info (display);
4509 char *vendor = ServerVendor (dpyinfo->display);
4511 if (! vendor) vendor = "";
4512 return build_string (vendor);
4515 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4516 "Returns the version numbers of the X server of display DISPLAY.\n\
4517 The value is a list of three integers: the major and minor\n\
4518 version numbers of the X Protocol in use, and the vendor-specific release\n\
4519 number. See also the function `x-server-vendor'.\n\n\
4520 The optional argument DISPLAY specifies which display to ask about.\n\
4521 DISPLAY should be either a frame or a display name (a string).\n\
4522 If omitted or nil, that stands for the selected frame's display.")
4523 (display)
4524 Lisp_Object display;
4526 struct x_display_info *dpyinfo = check_x_display_info (display);
4527 Display *dpy = dpyinfo->display;
4529 return Fcons (make_number (ProtocolVersion (dpy)),
4530 Fcons (make_number (ProtocolRevision (dpy)),
4531 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4534 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4535 "Returns the number of screens on the X server of display DISPLAY.\n\
4536 The optional argument DISPLAY specifies which display to ask about.\n\
4537 DISPLAY should be either a frame or a display name (a string).\n\
4538 If omitted or nil, that stands for the selected frame's display.")
4539 (display)
4540 Lisp_Object display;
4542 struct x_display_info *dpyinfo = check_x_display_info (display);
4544 return make_number (ScreenCount (dpyinfo->display));
4547 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4548 "Returns the height in millimeters of the X display DISPLAY.\n\
4549 The optional argument DISPLAY specifies which display to ask about.\n\
4550 DISPLAY should be either a frame or a display name (a string).\n\
4551 If omitted or nil, that stands for the selected frame's display.")
4552 (display)
4553 Lisp_Object display;
4555 struct x_display_info *dpyinfo = check_x_display_info (display);
4557 return make_number (HeightMMOfScreen (dpyinfo->screen));
4560 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4561 "Returns the width in millimeters of the X display DISPLAY.\n\
4562 The optional argument DISPLAY specifies which display to ask about.\n\
4563 DISPLAY should be either a frame or a display name (a string).\n\
4564 If omitted or nil, that stands for the selected frame's display.")
4565 (display)
4566 Lisp_Object display;
4568 struct x_display_info *dpyinfo = check_x_display_info (display);
4570 return make_number (WidthMMOfScreen (dpyinfo->screen));
4573 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4574 Sx_display_backing_store, 0, 1, 0,
4575 "Returns an indication of whether X display DISPLAY does backing store.\n\
4576 The value may be `always', `when-mapped', or `not-useful'.\n\
4577 The optional argument DISPLAY specifies which display to ask about.\n\
4578 DISPLAY should be either a frame or a display name (a string).\n\
4579 If omitted or nil, that stands for the selected frame's display.")
4580 (display)
4581 Lisp_Object display;
4583 struct x_display_info *dpyinfo = check_x_display_info (display);
4585 switch (DoesBackingStore (dpyinfo->screen))
4587 case Always:
4588 return intern ("always");
4590 case WhenMapped:
4591 return intern ("when-mapped");
4593 case NotUseful:
4594 return intern ("not-useful");
4596 default:
4597 error ("Strange value for BackingStore parameter of screen");
4601 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4602 Sx_display_visual_class, 0, 1, 0,
4603 "Returns the visual class of the X display DISPLAY.\n\
4604 The value is one of the symbols `static-gray', `gray-scale',\n\
4605 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4606 The optional argument DISPLAY specifies which display to ask about.\n\
4607 DISPLAY should be either a frame or a display name (a string).\n\
4608 If omitted or nil, that stands for the selected frame's display.")
4609 (display)
4610 Lisp_Object display;
4612 struct x_display_info *dpyinfo = check_x_display_info (display);
4614 switch (dpyinfo->visual->class)
4616 case StaticGray: return (intern ("static-gray"));
4617 case GrayScale: return (intern ("gray-scale"));
4618 case StaticColor: return (intern ("static-color"));
4619 case PseudoColor: return (intern ("pseudo-color"));
4620 case TrueColor: return (intern ("true-color"));
4621 case DirectColor: return (intern ("direct-color"));
4622 default:
4623 error ("Display has an unknown visual class");
4627 DEFUN ("x-display-save-under", Fx_display_save_under,
4628 Sx_display_save_under, 0, 1, 0,
4629 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4630 The optional argument DISPLAY specifies which display to ask about.\n\
4631 DISPLAY should be either a frame or a display name (a string).\n\
4632 If omitted or nil, that stands for the selected frame's display.")
4633 (display)
4634 Lisp_Object display;
4636 struct x_display_info *dpyinfo = check_x_display_info (display);
4638 if (DoesSaveUnders (dpyinfo->screen) == True)
4639 return Qt;
4640 else
4641 return Qnil;
4645 x_pixel_width (f)
4646 register struct frame *f;
4648 return PIXEL_WIDTH (f);
4652 x_pixel_height (f)
4653 register struct frame *f;
4655 return PIXEL_HEIGHT (f);
4659 x_char_width (f)
4660 register struct frame *f;
4662 return FONT_WIDTH (f->output_data.x->font);
4666 x_char_height (f)
4667 register struct frame *f;
4669 return f->output_data.x->line_height;
4673 x_screen_planes (f)
4674 register struct frame *f;
4676 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4681 /************************************************************************
4682 X Displays
4683 ************************************************************************/
4686 /* Mapping visual names to visuals. */
4688 static struct visual_class
4690 char *name;
4691 int class;
4693 visual_classes[] =
4695 {"StaticGray", StaticGray},
4696 {"GrayScale", GrayScale},
4697 {"StaticColor", StaticColor},
4698 {"PseudoColor", PseudoColor},
4699 {"TrueColor", TrueColor},
4700 {"DirectColor", DirectColor},
4701 NULL
4705 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4707 /* Value is the screen number of screen SCR. This is a substitute for
4708 the X function with the same name when that doesn't exist. */
4711 XScreenNumberOfScreen (scr)
4712 register Screen *scr;
4714 Display *dpy = scr->display;
4715 int i;
4717 for (i = 0; i < dpy->nscreens; ++i)
4718 if (scr == dpy->screens[i])
4719 break;
4721 return i;
4724 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4727 /* Select the visual that should be used on display DPYINFO. Set
4728 members of DPYINFO appropriately. Called from x_term_init. */
4730 void
4731 select_visual (dpyinfo)
4732 struct x_display_info *dpyinfo;
4734 Display *dpy = dpyinfo->display;
4735 Screen *screen = dpyinfo->screen;
4736 Lisp_Object value;
4738 /* See if a visual is specified. */
4739 value = display_x_get_resource (dpyinfo,
4740 build_string ("visualClass"),
4741 build_string ("VisualClass"),
4742 Qnil, Qnil);
4743 if (STRINGP (value))
4745 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4746 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4747 depth, a decimal number. NAME is compared with case ignored. */
4748 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
4749 char *dash;
4750 int i, class = -1;
4751 XVisualInfo vinfo;
4753 strcpy (s, XSTRING (value)->data);
4754 dash = index (s, '-');
4755 if (dash)
4757 dpyinfo->n_planes = atoi (dash + 1);
4758 *dash = '\0';
4760 else
4761 /* We won't find a matching visual with depth 0, so that
4762 an error will be printed below. */
4763 dpyinfo->n_planes = 0;
4765 /* Determine the visual class. */
4766 for (i = 0; visual_classes[i].name; ++i)
4767 if (xstricmp (s, visual_classes[i].name) == 0)
4769 class = visual_classes[i].class;
4770 break;
4773 /* Look up a matching visual for the specified class. */
4774 if (class == -1
4775 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4776 dpyinfo->n_planes, class, &vinfo))
4777 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
4779 dpyinfo->visual = vinfo.visual;
4781 else
4783 int n_visuals;
4784 XVisualInfo *vinfo, vinfo_template;
4786 dpyinfo->visual = DefaultVisualOfScreen (screen);
4788 #ifdef HAVE_X11R4
4789 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
4790 #else
4791 vinfo_template.visualid = dpyinfo->visual->visualid;
4792 #endif
4793 vinfo_template.screen = XScreenNumberOfScreen (screen);
4794 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
4795 &vinfo_template, &n_visuals);
4796 if (n_visuals != 1)
4797 fatal ("Can't get proper X visual info");
4799 dpyinfo->n_planes = vinfo->depth;
4800 XFree ((char *) vinfo);
4805 /* Return the X display structure for the display named NAME.
4806 Open a new connection if necessary. */
4808 struct x_display_info *
4809 x_display_info_for_name (name)
4810 Lisp_Object name;
4812 Lisp_Object names;
4813 struct x_display_info *dpyinfo;
4815 CHECK_STRING (name, 0);
4817 if (! EQ (Vwindow_system, intern ("x")))
4818 error ("Not using X Windows");
4820 for (dpyinfo = x_display_list, names = x_display_name_list;
4821 dpyinfo;
4822 dpyinfo = dpyinfo->next, names = XCDR (names))
4824 Lisp_Object tem;
4825 tem = Fstring_equal (XCAR (XCAR (names)), name);
4826 if (!NILP (tem))
4827 return dpyinfo;
4830 /* Use this general default value to start with. */
4831 Vx_resource_name = Vinvocation_name;
4833 validate_x_resource_name ();
4835 dpyinfo = x_term_init (name, (unsigned char *)0,
4836 (char *) XSTRING (Vx_resource_name)->data);
4838 if (dpyinfo == 0)
4839 error ("Cannot connect to X server %s", XSTRING (name)->data);
4841 x_in_use = 1;
4842 XSETFASTINT (Vwindow_system_version, 11);
4844 return dpyinfo;
4848 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4849 1, 3, 0, "Open a connection to an X server.\n\
4850 DISPLAY is the name of the display to connect to.\n\
4851 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4852 If the optional third arg MUST-SUCCEED is non-nil,\n\
4853 terminate Emacs if we can't open the connection.")
4854 (display, xrm_string, must_succeed)
4855 Lisp_Object display, xrm_string, must_succeed;
4857 unsigned char *xrm_option;
4858 struct x_display_info *dpyinfo;
4860 CHECK_STRING (display, 0);
4861 if (! NILP (xrm_string))
4862 CHECK_STRING (xrm_string, 1);
4864 if (! EQ (Vwindow_system, intern ("x")))
4865 error ("Not using X Windows");
4867 if (! NILP (xrm_string))
4868 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4869 else
4870 xrm_option = (unsigned char *) 0;
4872 validate_x_resource_name ();
4874 /* This is what opens the connection and sets x_current_display.
4875 This also initializes many symbols, such as those used for input. */
4876 dpyinfo = x_term_init (display, xrm_option,
4877 (char *) XSTRING (Vx_resource_name)->data);
4879 if (dpyinfo == 0)
4881 if (!NILP (must_succeed))
4882 fatal ("Cannot connect to X server %s.\n\
4883 Check the DISPLAY environment variable or use `-d'.\n\
4884 Also use the `xhost' program to verify that it is set to permit\n\
4885 connections from your machine.\n",
4886 XSTRING (display)->data);
4887 else
4888 error ("Cannot connect to X server %s", XSTRING (display)->data);
4891 x_in_use = 1;
4893 XSETFASTINT (Vwindow_system_version, 11);
4894 return Qnil;
4897 DEFUN ("x-close-connection", Fx_close_connection,
4898 Sx_close_connection, 1, 1, 0,
4899 "Close the connection to DISPLAY's X server.\n\
4900 For DISPLAY, specify either a frame or a display name (a string).\n\
4901 If DISPLAY is nil, that stands for the selected frame's display.")
4902 (display)
4903 Lisp_Object display;
4905 struct x_display_info *dpyinfo = check_x_display_info (display);
4906 int i;
4908 if (dpyinfo->reference_count > 0)
4909 error ("Display still has frames on it");
4911 BLOCK_INPUT;
4912 /* Free the fonts in the font table. */
4913 for (i = 0; i < dpyinfo->n_fonts; i++)
4914 if (dpyinfo->font_table[i].name)
4916 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4917 xfree (dpyinfo->font_table[i].full_name);
4918 xfree (dpyinfo->font_table[i].name);
4919 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4922 x_destroy_all_bitmaps (dpyinfo);
4923 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4925 #ifdef USE_X_TOOLKIT
4926 XtCloseDisplay (dpyinfo->display);
4927 #else
4928 XCloseDisplay (dpyinfo->display);
4929 #endif
4931 x_delete_display (dpyinfo);
4932 UNBLOCK_INPUT;
4934 return Qnil;
4937 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4938 "Return the list of display names that Emacs has connections to.")
4941 Lisp_Object tail, result;
4943 result = Qnil;
4944 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4945 result = Fcons (XCAR (XCAR (tail)), result);
4947 return result;
4950 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4951 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
4952 If ON is nil, allow buffering of requests.\n\
4953 Turning on synchronization prohibits the Xlib routines from buffering\n\
4954 requests and seriously degrades performance, but makes debugging much\n\
4955 easier.\n\
4956 The optional second argument DISPLAY specifies which display to act on.\n\
4957 DISPLAY should be either a frame or a display name (a string).\n\
4958 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
4959 (on, display)
4960 Lisp_Object display, on;
4962 struct x_display_info *dpyinfo = check_x_display_info (display);
4964 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
4966 return Qnil;
4969 /* Wait for responses to all X commands issued so far for frame F. */
4971 void
4972 x_sync (f)
4973 FRAME_PTR f;
4975 BLOCK_INPUT;
4976 XSync (FRAME_X_DISPLAY (f), False);
4977 UNBLOCK_INPUT;
4981 /***********************************************************************
4982 Image types
4983 ***********************************************************************/
4985 /* Value is the number of elements of vector VECTOR. */
4987 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4989 /* List of supported image types. Use define_image_type to add new
4990 types. Use lookup_image_type to find a type for a given symbol. */
4992 static struct image_type *image_types;
4994 /* The symbol `image' which is the car of the lists used to represent
4995 images in Lisp. */
4997 extern Lisp_Object Qimage;
4999 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5001 Lisp_Object Qxbm;
5003 /* Keywords. */
5005 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5006 extern Lisp_Object QCdata;
5007 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
5008 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
5009 Lisp_Object QCindex;
5011 /* Other symbols. */
5013 Lisp_Object Qlaplace;
5015 /* Time in seconds after which images should be removed from the cache
5016 if not displayed. */
5018 Lisp_Object Vimage_cache_eviction_delay;
5020 /* Function prototypes. */
5022 static void define_image_type P_ ((struct image_type *type));
5023 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5024 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5025 static void x_laplace P_ ((struct frame *, struct image *));
5026 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5027 Lisp_Object));
5030 /* Define a new image type from TYPE. This adds a copy of TYPE to
5031 image_types and adds the symbol *TYPE->type to Vimage_types. */
5033 static void
5034 define_image_type (type)
5035 struct image_type *type;
5037 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5038 The initialized data segment is read-only. */
5039 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5040 bcopy (type, p, sizeof *p);
5041 p->next = image_types;
5042 image_types = p;
5043 Vimage_types = Fcons (*p->type, Vimage_types);
5047 /* Look up image type SYMBOL, and return a pointer to its image_type
5048 structure. Value is null if SYMBOL is not a known image type. */
5050 static INLINE struct image_type *
5051 lookup_image_type (symbol)
5052 Lisp_Object symbol;
5054 struct image_type *type;
5056 for (type = image_types; type; type = type->next)
5057 if (EQ (symbol, *type->type))
5058 break;
5060 return type;
5064 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5065 valid image specification is a list whose car is the symbol
5066 `image', and whose rest is a property list. The property list must
5067 contain a value for key `:type'. That value must be the name of a
5068 supported image type. The rest of the property list depends on the
5069 image type. */
5072 valid_image_p (object)
5073 Lisp_Object object;
5075 int valid_p = 0;
5077 if (CONSP (object) && EQ (XCAR (object), Qimage))
5079 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
5080 struct image_type *type = lookup_image_type (symbol);
5082 if (type)
5083 valid_p = type->valid_p (object);
5086 return valid_p;
5090 /* Log error message with format string FORMAT and argument ARG.
5091 Signaling an error, e.g. when an image cannot be loaded, is not a
5092 good idea because this would interrupt redisplay, and the error
5093 message display would lead to another redisplay. This function
5094 therefore simply displays a message. */
5096 static void
5097 image_error (format, arg1, arg2)
5098 char *format;
5099 Lisp_Object arg1, arg2;
5101 add_to_log (format, arg1, arg2);
5106 /***********************************************************************
5107 Image specifications
5108 ***********************************************************************/
5110 enum image_value_type
5112 IMAGE_DONT_CHECK_VALUE_TYPE,
5113 IMAGE_STRING_VALUE,
5114 IMAGE_SYMBOL_VALUE,
5115 IMAGE_POSITIVE_INTEGER_VALUE,
5116 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5117 IMAGE_ASCENT_VALUE,
5118 IMAGE_INTEGER_VALUE,
5119 IMAGE_FUNCTION_VALUE,
5120 IMAGE_NUMBER_VALUE,
5121 IMAGE_BOOL_VALUE
5124 /* Structure used when parsing image specifications. */
5126 struct image_keyword
5128 /* Name of keyword. */
5129 char *name;
5131 /* The type of value allowed. */
5132 enum image_value_type type;
5134 /* Non-zero means key must be present. */
5135 int mandatory_p;
5137 /* Used to recognize duplicate keywords in a property list. */
5138 int count;
5140 /* The value that was found. */
5141 Lisp_Object value;
5145 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5146 int, Lisp_Object));
5147 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5150 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5151 has the format (image KEYWORD VALUE ...). One of the keyword/
5152 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5153 image_keywords structures of size NKEYWORDS describing other
5154 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5156 static int
5157 parse_image_spec (spec, keywords, nkeywords, type)
5158 Lisp_Object spec;
5159 struct image_keyword *keywords;
5160 int nkeywords;
5161 Lisp_Object type;
5163 int i;
5164 Lisp_Object plist;
5166 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5167 return 0;
5169 plist = XCDR (spec);
5170 while (CONSP (plist))
5172 Lisp_Object key, value;
5174 /* First element of a pair must be a symbol. */
5175 key = XCAR (plist);
5176 plist = XCDR (plist);
5177 if (!SYMBOLP (key))
5178 return 0;
5180 /* There must follow a value. */
5181 if (!CONSP (plist))
5182 return 0;
5183 value = XCAR (plist);
5184 plist = XCDR (plist);
5186 /* Find key in KEYWORDS. Error if not found. */
5187 for (i = 0; i < nkeywords; ++i)
5188 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5189 break;
5191 if (i == nkeywords)
5192 continue;
5194 /* Record that we recognized the keyword. If a keywords
5195 was found more than once, it's an error. */
5196 keywords[i].value = value;
5197 ++keywords[i].count;
5199 if (keywords[i].count > 1)
5200 return 0;
5202 /* Check type of value against allowed type. */
5203 switch (keywords[i].type)
5205 case IMAGE_STRING_VALUE:
5206 if (!STRINGP (value))
5207 return 0;
5208 break;
5210 case IMAGE_SYMBOL_VALUE:
5211 if (!SYMBOLP (value))
5212 return 0;
5213 break;
5215 case IMAGE_POSITIVE_INTEGER_VALUE:
5216 if (!INTEGERP (value) || XINT (value) <= 0)
5217 return 0;
5218 break;
5220 case IMAGE_ASCENT_VALUE:
5221 if (SYMBOLP (value) && EQ (value, Qcenter))
5222 break;
5223 else if (INTEGERP (value)
5224 && XINT (value) >= 0
5225 && XINT (value) <= 100)
5226 break;
5227 return 0;
5229 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5230 if (!INTEGERP (value) || XINT (value) < 0)
5231 return 0;
5232 break;
5234 case IMAGE_DONT_CHECK_VALUE_TYPE:
5235 break;
5237 case IMAGE_FUNCTION_VALUE:
5238 value = indirect_function (value);
5239 if (SUBRP (value)
5240 || COMPILEDP (value)
5241 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5242 break;
5243 return 0;
5245 case IMAGE_NUMBER_VALUE:
5246 if (!INTEGERP (value) && !FLOATP (value))
5247 return 0;
5248 break;
5250 case IMAGE_INTEGER_VALUE:
5251 if (!INTEGERP (value))
5252 return 0;
5253 break;
5255 case IMAGE_BOOL_VALUE:
5256 if (!NILP (value) && !EQ (value, Qt))
5257 return 0;
5258 break;
5260 default:
5261 abort ();
5262 break;
5265 if (EQ (key, QCtype) && !EQ (type, value))
5266 return 0;
5269 /* Check that all mandatory fields are present. */
5270 for (i = 0; i < nkeywords; ++i)
5271 if (keywords[i].mandatory_p && keywords[i].count == 0)
5272 return 0;
5274 return NILP (plist);
5278 /* Return the value of KEY in image specification SPEC. Value is nil
5279 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5280 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5282 static Lisp_Object
5283 image_spec_value (spec, key, found)
5284 Lisp_Object spec, key;
5285 int *found;
5287 Lisp_Object tail;
5289 xassert (valid_image_p (spec));
5291 for (tail = XCDR (spec);
5292 CONSP (tail) && CONSP (XCDR (tail));
5293 tail = XCDR (XCDR (tail)))
5295 if (EQ (XCAR (tail), key))
5297 if (found)
5298 *found = 1;
5299 return XCAR (XCDR (tail));
5303 if (found)
5304 *found = 0;
5305 return Qnil;
5309 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5310 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5311 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5312 size in canonical character units.\n\
5313 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5314 or omitted means use the selected frame.")
5315 (spec, pixels, frame)
5316 Lisp_Object spec, pixels, frame;
5318 Lisp_Object size;
5320 size = Qnil;
5321 if (valid_image_p (spec))
5323 struct frame *f = check_x_frame (frame);
5324 int id = lookup_image (f, spec);
5325 struct image *img = IMAGE_FROM_ID (f, id);
5326 int width = img->width + 2 * img->margin;
5327 int height = img->height + 2 * img->margin;
5329 if (NILP (pixels))
5330 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5331 make_float ((double) height / CANON_Y_UNIT (f)));
5332 else
5333 size = Fcons (make_number (width), make_number (height));
5335 else
5336 error ("Invalid image specification");
5338 return size;
5343 /***********************************************************************
5344 Image type independent image structures
5345 ***********************************************************************/
5347 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5348 static void free_image P_ ((struct frame *f, struct image *img));
5351 /* Allocate and return a new image structure for image specification
5352 SPEC. SPEC has a hash value of HASH. */
5354 static struct image *
5355 make_image (spec, hash)
5356 Lisp_Object spec;
5357 unsigned hash;
5359 struct image *img = (struct image *) xmalloc (sizeof *img);
5361 xassert (valid_image_p (spec));
5362 bzero (img, sizeof *img);
5363 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5364 xassert (img->type != NULL);
5365 img->spec = spec;
5366 img->data.lisp_val = Qnil;
5367 img->ascent = DEFAULT_IMAGE_ASCENT;
5368 img->hash = hash;
5369 return img;
5373 /* Free image IMG which was used on frame F, including its resources. */
5375 static void
5376 free_image (f, img)
5377 struct frame *f;
5378 struct image *img;
5380 if (img)
5382 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5384 /* Remove IMG from the hash table of its cache. */
5385 if (img->prev)
5386 img->prev->next = img->next;
5387 else
5388 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5390 if (img->next)
5391 img->next->prev = img->prev;
5393 c->images[img->id] = NULL;
5395 /* Free resources, then free IMG. */
5396 img->type->free (f, img);
5397 xfree (img);
5402 /* Prepare image IMG for display on frame F. Must be called before
5403 drawing an image. */
5405 void
5406 prepare_image_for_display (f, img)
5407 struct frame *f;
5408 struct image *img;
5410 EMACS_TIME t;
5412 /* We're about to display IMG, so set its timestamp to `now'. */
5413 EMACS_GET_TIME (t);
5414 img->timestamp = EMACS_SECS (t);
5416 /* If IMG doesn't have a pixmap yet, load it now, using the image
5417 type dependent loader function. */
5418 if (img->pixmap == 0 && !img->load_failed_p)
5419 img->load_failed_p = img->type->load (f, img) == 0;
5423 /* Value is the number of pixels for the ascent of image IMG when
5424 drawn in face FACE. */
5427 image_ascent (img, face)
5428 struct image *img;
5429 struct face *face;
5431 int height = img->height + img->margin;
5432 int ascent;
5434 if (img->ascent == CENTERED_IMAGE_ASCENT)
5436 if (face->font)
5437 ascent = height / 2 - (face->font->descent - face->font->ascent) / 2;
5438 else
5439 ascent = height / 2;
5441 else
5442 ascent = height * img->ascent / 100.0;
5444 return ascent;
5449 /***********************************************************************
5450 Helper functions for X image types
5451 ***********************************************************************/
5453 static void x_clear_image P_ ((struct frame *f, struct image *img));
5454 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5455 struct image *img,
5456 Lisp_Object color_name,
5457 unsigned long dflt));
5459 /* Free X resources of image IMG which is used on frame F. */
5461 static void
5462 x_clear_image (f, img)
5463 struct frame *f;
5464 struct image *img;
5466 if (img->pixmap)
5468 BLOCK_INPUT;
5469 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5470 img->pixmap = 0;
5471 UNBLOCK_INPUT;
5474 if (img->ncolors)
5476 BLOCK_INPUT;
5477 x_free_colors (f, img->colors, img->ncolors);
5478 UNBLOCK_INPUT;
5480 xfree (img->colors);
5481 img->colors = NULL;
5482 img->ncolors = 0;
5487 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5488 cannot be allocated, use DFLT. Add a newly allocated color to
5489 IMG->colors, so that it can be freed again. Value is the pixel
5490 color. */
5492 static unsigned long
5493 x_alloc_image_color (f, img, color_name, dflt)
5494 struct frame *f;
5495 struct image *img;
5496 Lisp_Object color_name;
5497 unsigned long dflt;
5499 XColor color;
5500 unsigned long result;
5502 xassert (STRINGP (color_name));
5504 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5506 /* This isn't called frequently so we get away with simply
5507 reallocating the color vector to the needed size, here. */
5508 ++img->ncolors;
5509 img->colors =
5510 (unsigned long *) xrealloc (img->colors,
5511 img->ncolors * sizeof *img->colors);
5512 img->colors[img->ncolors - 1] = color.pixel;
5513 result = color.pixel;
5515 else
5516 result = dflt;
5518 return result;
5523 /***********************************************************************
5524 Image Cache
5525 ***********************************************************************/
5527 static void cache_image P_ ((struct frame *f, struct image *img));
5530 /* Return a new, initialized image cache that is allocated from the
5531 heap. Call free_image_cache to free an image cache. */
5533 struct image_cache *
5534 make_image_cache ()
5536 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5537 int size;
5539 bzero (c, sizeof *c);
5540 c->size = 50;
5541 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5542 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5543 c->buckets = (struct image **) xmalloc (size);
5544 bzero (c->buckets, size);
5545 return c;
5549 /* Free image cache of frame F. Be aware that X frames share images
5550 caches. */
5552 void
5553 free_image_cache (f)
5554 struct frame *f;
5556 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5557 if (c)
5559 int i;
5561 /* Cache should not be referenced by any frame when freed. */
5562 xassert (c->refcount == 0);
5564 for (i = 0; i < c->used; ++i)
5565 free_image (f, c->images[i]);
5566 xfree (c->images);
5567 xfree (c->buckets);
5568 xfree (c);
5569 FRAME_X_IMAGE_CACHE (f) = NULL;
5574 /* Clear image cache of frame F. FORCE_P non-zero means free all
5575 images. FORCE_P zero means clear only images that haven't been
5576 displayed for some time. Should be called from time to time to
5577 reduce the number of loaded images. If image-eviction-seconds is
5578 non-nil, this frees images in the cache which weren't displayed for
5579 at least that many seconds. */
5581 void
5582 clear_image_cache (f, force_p)
5583 struct frame *f;
5584 int force_p;
5586 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5588 if (c && INTEGERP (Vimage_cache_eviction_delay))
5590 EMACS_TIME t;
5591 unsigned long old;
5592 int i, any_freed_p = 0;
5594 EMACS_GET_TIME (t);
5595 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5597 for (i = 0; i < c->used; ++i)
5599 struct image *img = c->images[i];
5600 if (img != NULL
5601 && (force_p
5602 || (img->timestamp > old)))
5604 free_image (f, img);
5605 any_freed_p = 1;
5609 /* We may be clearing the image cache because, for example,
5610 Emacs was iconified for a longer period of time. In that
5611 case, current matrices may still contain references to
5612 images freed above. So, clear these matrices. */
5613 if (any_freed_p)
5615 clear_current_matrices (f);
5616 ++windows_or_buffers_changed;
5622 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5623 0, 1, 0,
5624 "Clear the image cache of FRAME.\n\
5625 FRAME nil or omitted means use the selected frame.\n\
5626 FRAME t means clear the image caches of all frames.")
5627 (frame)
5628 Lisp_Object frame;
5630 if (EQ (frame, Qt))
5632 Lisp_Object tail;
5634 FOR_EACH_FRAME (tail, frame)
5635 if (FRAME_X_P (XFRAME (frame)))
5636 clear_image_cache (XFRAME (frame), 1);
5638 else
5639 clear_image_cache (check_x_frame (frame), 1);
5641 return Qnil;
5645 /* Return the id of image with Lisp specification SPEC on frame F.
5646 SPEC must be a valid Lisp image specification (see valid_image_p). */
5649 lookup_image (f, spec)
5650 struct frame *f;
5651 Lisp_Object spec;
5653 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5654 struct image *img;
5655 int i;
5656 unsigned hash;
5657 struct gcpro gcpro1;
5658 EMACS_TIME now;
5660 /* F must be a window-system frame, and SPEC must be a valid image
5661 specification. */
5662 xassert (FRAME_WINDOW_P (f));
5663 xassert (valid_image_p (spec));
5665 GCPRO1 (spec);
5667 /* Look up SPEC in the hash table of the image cache. */
5668 hash = sxhash (spec, 0);
5669 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5671 for (img = c->buckets[i]; img; img = img->next)
5672 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5673 break;
5675 /* If not found, create a new image and cache it. */
5676 if (img == NULL)
5678 img = make_image (spec, hash);
5679 cache_image (f, img);
5680 img->load_failed_p = img->type->load (f, img) == 0;
5681 xassert (!interrupt_input_blocked);
5683 /* If we can't load the image, and we don't have a width and
5684 height, use some arbitrary width and height so that we can
5685 draw a rectangle for it. */
5686 if (img->load_failed_p)
5688 Lisp_Object value;
5690 value = image_spec_value (spec, QCwidth, NULL);
5691 img->width = (INTEGERP (value)
5692 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5693 value = image_spec_value (spec, QCheight, NULL);
5694 img->height = (INTEGERP (value)
5695 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5697 else
5699 /* Handle image type independent image attributes
5700 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
5701 Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
5702 Lisp_Object file;
5704 ascent = image_spec_value (spec, QCascent, NULL);
5705 if (INTEGERP (ascent))
5706 img->ascent = XFASTINT (ascent);
5707 else if (EQ (ascent, Qcenter))
5708 img->ascent = CENTERED_IMAGE_ASCENT;
5710 margin = image_spec_value (spec, QCmargin, NULL);
5711 if (INTEGERP (margin) && XINT (margin) >= 0)
5712 img->margin = XFASTINT (margin);
5714 relief = image_spec_value (spec, QCrelief, NULL);
5715 if (INTEGERP (relief))
5717 img->relief = XINT (relief);
5718 img->margin += abs (img->relief);
5721 /* Should we apply a Laplace edge-detection algorithm? */
5722 algorithm = image_spec_value (spec, QCalgorithm, NULL);
5723 if (img->pixmap && EQ (algorithm, Qlaplace))
5724 x_laplace (f, img);
5726 /* Should we built a mask heuristically? */
5727 heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
5728 if (img->pixmap && !img->mask && !NILP (heuristic_mask))
5729 x_build_heuristic_mask (f, img, heuristic_mask);
5733 /* We're using IMG, so set its timestamp to `now'. */
5734 EMACS_GET_TIME (now);
5735 img->timestamp = EMACS_SECS (now);
5737 UNGCPRO;
5739 /* Value is the image id. */
5740 return img->id;
5744 /* Cache image IMG in the image cache of frame F. */
5746 static void
5747 cache_image (f, img)
5748 struct frame *f;
5749 struct image *img;
5751 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5752 int i;
5754 /* Find a free slot in c->images. */
5755 for (i = 0; i < c->used; ++i)
5756 if (c->images[i] == NULL)
5757 break;
5759 /* If no free slot found, maybe enlarge c->images. */
5760 if (i == c->used && c->used == c->size)
5762 c->size *= 2;
5763 c->images = (struct image **) xrealloc (c->images,
5764 c->size * sizeof *c->images);
5767 /* Add IMG to c->images, and assign IMG an id. */
5768 c->images[i] = img;
5769 img->id = i;
5770 if (i == c->used)
5771 ++c->used;
5773 /* Add IMG to the cache's hash table. */
5774 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5775 img->next = c->buckets[i];
5776 if (img->next)
5777 img->next->prev = img;
5778 img->prev = NULL;
5779 c->buckets[i] = img;
5783 /* Call FN on every image in the image cache of frame F. Used to mark
5784 Lisp Objects in the image cache. */
5786 void
5787 forall_images_in_image_cache (f, fn)
5788 struct frame *f;
5789 void (*fn) P_ ((struct image *img));
5791 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
5793 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5794 if (c)
5796 int i;
5797 for (i = 0; i < c->used; ++i)
5798 if (c->images[i])
5799 fn (c->images[i]);
5806 /***********************************************************************
5807 X support code
5808 ***********************************************************************/
5810 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
5811 XImage **, Pixmap *));
5812 static void x_destroy_x_image P_ ((XImage *));
5813 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
5816 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5817 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5818 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5819 via xmalloc. Print error messages via image_error if an error
5820 occurs. Value is non-zero if successful. */
5822 static int
5823 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
5824 struct frame *f;
5825 int width, height, depth;
5826 XImage **ximg;
5827 Pixmap *pixmap;
5829 Display *display = FRAME_X_DISPLAY (f);
5830 Screen *screen = FRAME_X_SCREEN (f);
5831 Window window = FRAME_X_WINDOW (f);
5833 xassert (interrupt_input_blocked);
5835 if (depth <= 0)
5836 depth = DefaultDepthOfScreen (screen);
5837 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
5838 depth, ZPixmap, 0, NULL, width, height,
5839 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
5840 if (*ximg == NULL)
5842 image_error ("Unable to allocate X image", Qnil, Qnil);
5843 return 0;
5846 /* Allocate image raster. */
5847 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
5849 /* Allocate a pixmap of the same size. */
5850 *pixmap = XCreatePixmap (display, window, width, height, depth);
5851 if (*pixmap == 0)
5853 x_destroy_x_image (*ximg);
5854 *ximg = NULL;
5855 image_error ("Unable to create X pixmap", Qnil, Qnil);
5856 return 0;
5859 return 1;
5863 /* Destroy XImage XIMG. Free XIMG->data. */
5865 static void
5866 x_destroy_x_image (ximg)
5867 XImage *ximg;
5869 xassert (interrupt_input_blocked);
5870 if (ximg)
5872 xfree (ximg->data);
5873 ximg->data = NULL;
5874 XDestroyImage (ximg);
5879 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5880 are width and height of both the image and pixmap. */
5882 static void
5883 x_put_x_image (f, ximg, pixmap, width, height)
5884 struct frame *f;
5885 XImage *ximg;
5886 Pixmap pixmap;
5888 GC gc;
5890 xassert (interrupt_input_blocked);
5891 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
5892 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
5893 XFreeGC (FRAME_X_DISPLAY (f), gc);
5898 /***********************************************************************
5899 File Handling
5900 ***********************************************************************/
5902 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
5903 static char *slurp_file P_ ((char *, int *));
5906 /* Find image file FILE. Look in data-directory, then
5907 x-bitmap-file-path. Value is the full name of the file found, or
5908 nil if not found. */
5910 static Lisp_Object
5911 x_find_image_file (file)
5912 Lisp_Object file;
5914 Lisp_Object file_found, search_path;
5915 struct gcpro gcpro1, gcpro2;
5916 int fd;
5918 file_found = Qnil;
5919 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
5920 GCPRO2 (file_found, search_path);
5922 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5923 fd = openp (search_path, file, "", &file_found, 0);
5925 if (fd < 0)
5926 file_found = Qnil;
5927 else
5928 close (fd);
5930 UNGCPRO;
5931 return file_found;
5935 /* Read FILE into memory. Value is a pointer to a buffer allocated
5936 with xmalloc holding FILE's contents. Value is null if an error
5937 occured. *SIZE is set to the size of the file. */
5939 static char *
5940 slurp_file (file, size)
5941 char *file;
5942 int *size;
5944 FILE *fp = NULL;
5945 char *buf = NULL;
5946 struct stat st;
5948 if (stat (file, &st) == 0
5949 && (fp = fopen (file, "r")) != NULL
5950 && (buf = (char *) xmalloc (st.st_size),
5951 fread (buf, 1, st.st_size, fp) == st.st_size))
5953 *size = st.st_size;
5954 fclose (fp);
5956 else
5958 if (fp)
5959 fclose (fp);
5960 if (buf)
5962 xfree (buf);
5963 buf = NULL;
5967 return buf;
5972 /***********************************************************************
5973 XBM images
5974 ***********************************************************************/
5976 static int xbm_scan P_ ((char **, char *, char *, int *));
5977 static int xbm_load P_ ((struct frame *f, struct image *img));
5978 static int xbm_load_image P_ ((struct frame *f, struct image *img,
5979 char *, char *));
5980 static int xbm_image_p P_ ((Lisp_Object object));
5981 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
5982 unsigned char **));
5983 static int xbm_file_p P_ ((Lisp_Object));
5986 /* Indices of image specification fields in xbm_format, below. */
5988 enum xbm_keyword_index
5990 XBM_TYPE,
5991 XBM_FILE,
5992 XBM_WIDTH,
5993 XBM_HEIGHT,
5994 XBM_DATA,
5995 XBM_FOREGROUND,
5996 XBM_BACKGROUND,
5997 XBM_ASCENT,
5998 XBM_MARGIN,
5999 XBM_RELIEF,
6000 XBM_ALGORITHM,
6001 XBM_HEURISTIC_MASK,
6002 XBM_LAST
6005 /* Vector of image_keyword structures describing the format
6006 of valid XBM image specifications. */
6008 static struct image_keyword xbm_format[XBM_LAST] =
6010 {":type", IMAGE_SYMBOL_VALUE, 1},
6011 {":file", IMAGE_STRING_VALUE, 0},
6012 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6013 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6014 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6015 {":foreground", IMAGE_STRING_VALUE, 0},
6016 {":background", IMAGE_STRING_VALUE, 0},
6017 {":ascent", IMAGE_ASCENT_VALUE, 0},
6018 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6019 {":relief", IMAGE_INTEGER_VALUE, 0},
6020 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6021 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6024 /* Structure describing the image type XBM. */
6026 static struct image_type xbm_type =
6028 &Qxbm,
6029 xbm_image_p,
6030 xbm_load,
6031 x_clear_image,
6032 NULL
6035 /* Tokens returned from xbm_scan. */
6037 enum xbm_token
6039 XBM_TK_IDENT = 256,
6040 XBM_TK_NUMBER
6044 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6045 A valid specification is a list starting with the symbol `image'
6046 The rest of the list is a property list which must contain an
6047 entry `:type xbm..
6049 If the specification specifies a file to load, it must contain
6050 an entry `:file FILENAME' where FILENAME is a string.
6052 If the specification is for a bitmap loaded from memory it must
6053 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6054 WIDTH and HEIGHT are integers > 0. DATA may be:
6056 1. a string large enough to hold the bitmap data, i.e. it must
6057 have a size >= (WIDTH + 7) / 8 * HEIGHT
6059 2. a bool-vector of size >= WIDTH * HEIGHT
6061 3. a vector of strings or bool-vectors, one for each line of the
6062 bitmap.
6064 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6065 may not be specified in this case because they are defined in the
6066 XBM file.
6068 Both the file and data forms may contain the additional entries
6069 `:background COLOR' and `:foreground COLOR'. If not present,
6070 foreground and background of the frame on which the image is
6071 displayed is used. */
6073 static int
6074 xbm_image_p (object)
6075 Lisp_Object object;
6077 struct image_keyword kw[XBM_LAST];
6079 bcopy (xbm_format, kw, sizeof kw);
6080 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6081 return 0;
6083 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6085 if (kw[XBM_FILE].count)
6087 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6088 return 0;
6090 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6092 /* In-memory XBM file. */
6093 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6094 return 0;
6096 else
6098 Lisp_Object data;
6099 int width, height;
6101 /* Entries for `:width', `:height' and `:data' must be present. */
6102 if (!kw[XBM_WIDTH].count
6103 || !kw[XBM_HEIGHT].count
6104 || !kw[XBM_DATA].count)
6105 return 0;
6107 data = kw[XBM_DATA].value;
6108 width = XFASTINT (kw[XBM_WIDTH].value);
6109 height = XFASTINT (kw[XBM_HEIGHT].value);
6111 /* Check type of data, and width and height against contents of
6112 data. */
6113 if (VECTORP (data))
6115 int i;
6117 /* Number of elements of the vector must be >= height. */
6118 if (XVECTOR (data)->size < height)
6119 return 0;
6121 /* Each string or bool-vector in data must be large enough
6122 for one line of the image. */
6123 for (i = 0; i < height; ++i)
6125 Lisp_Object elt = XVECTOR (data)->contents[i];
6127 if (STRINGP (elt))
6129 if (XSTRING (elt)->size
6130 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6131 return 0;
6133 else if (BOOL_VECTOR_P (elt))
6135 if (XBOOL_VECTOR (elt)->size < width)
6136 return 0;
6138 else
6139 return 0;
6142 else if (STRINGP (data))
6144 if (XSTRING (data)->size
6145 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6146 return 0;
6148 else if (BOOL_VECTOR_P (data))
6150 if (XBOOL_VECTOR (data)->size < width * height)
6151 return 0;
6153 else
6154 return 0;
6157 return 1;
6161 /* Scan a bitmap file. FP is the stream to read from. Value is
6162 either an enumerator from enum xbm_token, or a character for a
6163 single-character token, or 0 at end of file. If scanning an
6164 identifier, store the lexeme of the identifier in SVAL. If
6165 scanning a number, store its value in *IVAL. */
6167 static int
6168 xbm_scan (s, end, sval, ival)
6169 char **s, *end;
6170 char *sval;
6171 int *ival;
6173 int c;
6175 /* Skip white space. */
6176 while (*s < end && (c = *(*s)++, isspace (c)))
6179 if (*s >= end)
6180 c = 0;
6181 else if (isdigit (c))
6183 int value = 0, digit;
6185 if (c == '0' && *s < end)
6187 c = *(*s)++;
6188 if (c == 'x' || c == 'X')
6190 while (*s < end)
6192 c = *(*s)++;
6193 if (isdigit (c))
6194 digit = c - '0';
6195 else if (c >= 'a' && c <= 'f')
6196 digit = c - 'a' + 10;
6197 else if (c >= 'A' && c <= 'F')
6198 digit = c - 'A' + 10;
6199 else
6200 break;
6201 value = 16 * value + digit;
6204 else if (isdigit (c))
6206 value = c - '0';
6207 while (*s < end
6208 && (c = *(*s)++, isdigit (c)))
6209 value = 8 * value + c - '0';
6212 else
6214 value = c - '0';
6215 while (*s < end
6216 && (c = *(*s)++, isdigit (c)))
6217 value = 10 * value + c - '0';
6220 if (*s < end)
6221 *s = *s - 1;
6222 *ival = value;
6223 c = XBM_TK_NUMBER;
6225 else if (isalpha (c) || c == '_')
6227 *sval++ = c;
6228 while (*s < end
6229 && (c = *(*s)++, (isalnum (c) || c == '_')))
6230 *sval++ = c;
6231 *sval = 0;
6232 if (*s < end)
6233 *s = *s - 1;
6234 c = XBM_TK_IDENT;
6237 return c;
6241 /* Replacement for XReadBitmapFileData which isn't available under old
6242 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6243 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6244 the image. Return in *DATA the bitmap data allocated with xmalloc.
6245 Value is non-zero if successful. DATA null means just test if
6246 CONTENTS looks like an im-memory XBM file. */
6248 static int
6249 xbm_read_bitmap_data (contents, end, width, height, data)
6250 char *contents, *end;
6251 int *width, *height;
6252 unsigned char **data;
6254 char *s = contents;
6255 char buffer[BUFSIZ];
6256 int padding_p = 0;
6257 int v10 = 0;
6258 int bytes_per_line, i, nbytes;
6259 unsigned char *p;
6260 int value;
6261 int LA1;
6263 #define match() \
6264 LA1 = xbm_scan (&s, end, buffer, &value)
6266 #define expect(TOKEN) \
6267 if (LA1 != (TOKEN)) \
6268 goto failure; \
6269 else \
6270 match ()
6272 #define expect_ident(IDENT) \
6273 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6274 match (); \
6275 else \
6276 goto failure
6278 *width = *height = -1;
6279 if (data)
6280 *data = NULL;
6281 LA1 = xbm_scan (&s, end, buffer, &value);
6283 /* Parse defines for width, height and hot-spots. */
6284 while (LA1 == '#')
6286 match ();
6287 expect_ident ("define");
6288 expect (XBM_TK_IDENT);
6290 if (LA1 == XBM_TK_NUMBER);
6292 char *p = strrchr (buffer, '_');
6293 p = p ? p + 1 : buffer;
6294 if (strcmp (p, "width") == 0)
6295 *width = value;
6296 else if (strcmp (p, "height") == 0)
6297 *height = value;
6299 expect (XBM_TK_NUMBER);
6302 if (*width < 0 || *height < 0)
6303 goto failure;
6304 else if (data == NULL)
6305 goto success;
6307 /* Parse bits. Must start with `static'. */
6308 expect_ident ("static");
6309 if (LA1 == XBM_TK_IDENT)
6311 if (strcmp (buffer, "unsigned") == 0)
6313 match ();
6314 expect_ident ("char");
6316 else if (strcmp (buffer, "short") == 0)
6318 match ();
6319 v10 = 1;
6320 if (*width % 16 && *width % 16 < 9)
6321 padding_p = 1;
6323 else if (strcmp (buffer, "char") == 0)
6324 match ();
6325 else
6326 goto failure;
6328 else
6329 goto failure;
6331 expect (XBM_TK_IDENT);
6332 expect ('[');
6333 expect (']');
6334 expect ('=');
6335 expect ('{');
6337 bytes_per_line = (*width + 7) / 8 + padding_p;
6338 nbytes = bytes_per_line * *height;
6339 p = *data = (char *) xmalloc (nbytes);
6341 if (v10)
6343 for (i = 0; i < nbytes; i += 2)
6345 int val = value;
6346 expect (XBM_TK_NUMBER);
6348 *p++ = val;
6349 if (!padding_p || ((i + 2) % bytes_per_line))
6350 *p++ = value >> 8;
6352 if (LA1 == ',' || LA1 == '}')
6353 match ();
6354 else
6355 goto failure;
6358 else
6360 for (i = 0; i < nbytes; ++i)
6362 int val = value;
6363 expect (XBM_TK_NUMBER);
6365 *p++ = val;
6367 if (LA1 == ',' || LA1 == '}')
6368 match ();
6369 else
6370 goto failure;
6374 success:
6375 return 1;
6377 failure:
6379 if (data && *data)
6381 xfree (*data);
6382 *data = NULL;
6384 return 0;
6386 #undef match
6387 #undef expect
6388 #undef expect_ident
6392 /* Load XBM image IMG which will be displayed on frame F from buffer
6393 CONTENTS. END is the end of the buffer. Value is non-zero if
6394 successful. */
6396 static int
6397 xbm_load_image (f, img, contents, end)
6398 struct frame *f;
6399 struct image *img;
6400 char *contents, *end;
6402 int rc;
6403 unsigned char *data;
6404 int success_p = 0;
6406 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
6407 if (rc)
6409 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6410 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6411 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6412 Lisp_Object value;
6414 xassert (img->width > 0 && img->height > 0);
6416 /* Get foreground and background colors, maybe allocate colors. */
6417 value = image_spec_value (img->spec, QCforeground, NULL);
6418 if (!NILP (value))
6419 foreground = x_alloc_image_color (f, img, value, foreground);
6421 value = image_spec_value (img->spec, QCbackground, NULL);
6422 if (!NILP (value))
6423 background = x_alloc_image_color (f, img, value, background);
6425 BLOCK_INPUT;
6426 img->pixmap
6427 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6428 FRAME_X_WINDOW (f),
6429 data,
6430 img->width, img->height,
6431 foreground, background,
6432 depth);
6433 xfree (data);
6435 if (img->pixmap == 0)
6437 x_clear_image (f, img);
6438 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6440 else
6441 success_p = 1;
6443 UNBLOCK_INPUT;
6445 else
6446 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6448 return success_p;
6452 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6454 static int
6455 xbm_file_p (data)
6456 Lisp_Object data;
6458 int w, h;
6459 return (STRINGP (data)
6460 && xbm_read_bitmap_data (XSTRING (data)->data,
6461 (XSTRING (data)->data
6462 + STRING_BYTES (XSTRING (data))),
6463 &w, &h, NULL));
6467 /* Fill image IMG which is used on frame F with pixmap data. Value is
6468 non-zero if successful. */
6470 static int
6471 xbm_load (f, img)
6472 struct frame *f;
6473 struct image *img;
6475 int success_p = 0;
6476 Lisp_Object file_name;
6478 xassert (xbm_image_p (img->spec));
6480 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6481 file_name = image_spec_value (img->spec, QCfile, NULL);
6482 if (STRINGP (file_name))
6484 Lisp_Object file;
6485 char *contents;
6486 int size;
6487 struct gcpro gcpro1;
6489 file = x_find_image_file (file_name);
6490 GCPRO1 (file);
6491 if (!STRINGP (file))
6493 image_error ("Cannot find image file `%s'", file_name, Qnil);
6494 UNGCPRO;
6495 return 0;
6498 contents = slurp_file (XSTRING (file)->data, &size);
6499 if (contents == NULL)
6501 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6502 UNGCPRO;
6503 return 0;
6506 success_p = xbm_load_image (f, img, contents, contents + size);
6507 UNGCPRO;
6509 else
6511 struct image_keyword fmt[XBM_LAST];
6512 Lisp_Object data;
6513 unsigned char *bitmap_data;
6514 int depth;
6515 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6516 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6517 char *bits;
6518 int parsed_p, height, width;
6519 int in_memory_file_p = 0;
6521 /* See if data looks like an in-memory XBM file. */
6522 data = image_spec_value (img->spec, QCdata, NULL);
6523 in_memory_file_p = xbm_file_p (data);
6525 /* Parse the image specification. */
6526 bcopy (xbm_format, fmt, sizeof fmt);
6527 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6528 xassert (parsed_p);
6530 /* Get specified width, and height. */
6531 if (!in_memory_file_p)
6533 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6534 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6535 xassert (img->width > 0 && img->height > 0);
6538 BLOCK_INPUT;
6540 /* Get foreground and background colors, maybe allocate colors. */
6541 if (fmt[XBM_FOREGROUND].count)
6542 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6543 foreground);
6544 if (fmt[XBM_BACKGROUND].count)
6545 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6546 background);
6548 if (in_memory_file_p)
6549 success_p = xbm_load_image (f, img, XSTRING (data)->data,
6550 (XSTRING (data)->data
6551 + STRING_BYTES (XSTRING (data))));
6552 else
6554 if (VECTORP (data))
6556 int i;
6557 char *p;
6558 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6560 p = bits = (char *) alloca (nbytes * img->height);
6561 for (i = 0; i < img->height; ++i, p += nbytes)
6563 Lisp_Object line = XVECTOR (data)->contents[i];
6564 if (STRINGP (line))
6565 bcopy (XSTRING (line)->data, p, nbytes);
6566 else
6567 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6570 else if (STRINGP (data))
6571 bits = XSTRING (data)->data;
6572 else
6573 bits = XBOOL_VECTOR (data)->data;
6575 /* Create the pixmap. */
6576 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6577 img->pixmap
6578 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6579 FRAME_X_WINDOW (f),
6580 bits,
6581 img->width, img->height,
6582 foreground, background,
6583 depth);
6584 if (img->pixmap)
6585 success_p = 1;
6586 else
6588 image_error ("Unable to create pixmap for XBM image `%s'",
6589 img->spec, Qnil);
6590 x_clear_image (f, img);
6594 UNBLOCK_INPUT;
6597 return success_p;
6602 /***********************************************************************
6603 XPM images
6604 ***********************************************************************/
6606 #if HAVE_XPM
6608 static int xpm_image_p P_ ((Lisp_Object object));
6609 static int xpm_load P_ ((struct frame *f, struct image *img));
6610 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6612 #include "X11/xpm.h"
6614 /* The symbol `xpm' identifying XPM-format images. */
6616 Lisp_Object Qxpm;
6618 /* Indices of image specification fields in xpm_format, below. */
6620 enum xpm_keyword_index
6622 XPM_TYPE,
6623 XPM_FILE,
6624 XPM_DATA,
6625 XPM_ASCENT,
6626 XPM_MARGIN,
6627 XPM_RELIEF,
6628 XPM_ALGORITHM,
6629 XPM_HEURISTIC_MASK,
6630 XPM_COLOR_SYMBOLS,
6631 XPM_LAST
6634 /* Vector of image_keyword structures describing the format
6635 of valid XPM image specifications. */
6637 static struct image_keyword xpm_format[XPM_LAST] =
6639 {":type", IMAGE_SYMBOL_VALUE, 1},
6640 {":file", IMAGE_STRING_VALUE, 0},
6641 {":data", IMAGE_STRING_VALUE, 0},
6642 {":ascent", IMAGE_ASCENT_VALUE, 0},
6643 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6644 {":relief", IMAGE_INTEGER_VALUE, 0},
6645 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6646 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6647 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6650 /* Structure describing the image type XBM. */
6652 static struct image_type xpm_type =
6654 &Qxpm,
6655 xpm_image_p,
6656 xpm_load,
6657 x_clear_image,
6658 NULL
6662 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6663 for XPM images. Such a list must consist of conses whose car and
6664 cdr are strings. */
6666 static int
6667 xpm_valid_color_symbols_p (color_symbols)
6668 Lisp_Object color_symbols;
6670 while (CONSP (color_symbols))
6672 Lisp_Object sym = XCAR (color_symbols);
6673 if (!CONSP (sym)
6674 || !STRINGP (XCAR (sym))
6675 || !STRINGP (XCDR (sym)))
6676 break;
6677 color_symbols = XCDR (color_symbols);
6680 return NILP (color_symbols);
6684 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6686 static int
6687 xpm_image_p (object)
6688 Lisp_Object object;
6690 struct image_keyword fmt[XPM_LAST];
6691 bcopy (xpm_format, fmt, sizeof fmt);
6692 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
6693 /* Either `:file' or `:data' must be present. */
6694 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
6695 /* Either no `:color-symbols' or it's a list of conses
6696 whose car and cdr are strings. */
6697 && (fmt[XPM_COLOR_SYMBOLS].count == 0
6698 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
6702 /* Load image IMG which will be displayed on frame F. Value is
6703 non-zero if successful. */
6705 static int
6706 xpm_load (f, img)
6707 struct frame *f;
6708 struct image *img;
6710 int rc, i;
6711 XpmAttributes attrs;
6712 Lisp_Object specified_file, color_symbols;
6714 /* Configure the XPM lib. Use the visual of frame F. Allocate
6715 close colors. Return colors allocated. */
6716 bzero (&attrs, sizeof attrs);
6717 attrs.visual = FRAME_X_VISUAL (f);
6718 attrs.colormap = FRAME_X_COLORMAP (f);
6719 attrs.valuemask |= XpmVisual;
6720 attrs.valuemask |= XpmColormap;
6721 attrs.valuemask |= XpmReturnAllocPixels;
6722 #ifdef XpmAllocCloseColors
6723 attrs.alloc_close_colors = 1;
6724 attrs.valuemask |= XpmAllocCloseColors;
6725 #else
6726 attrs.closeness = 600;
6727 attrs.valuemask |= XpmCloseness;
6728 #endif
6730 /* If image specification contains symbolic color definitions, add
6731 these to `attrs'. */
6732 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
6733 if (CONSP (color_symbols))
6735 Lisp_Object tail;
6736 XpmColorSymbol *xpm_syms;
6737 int i, size;
6739 attrs.valuemask |= XpmColorSymbols;
6741 /* Count number of symbols. */
6742 attrs.numsymbols = 0;
6743 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
6744 ++attrs.numsymbols;
6746 /* Allocate an XpmColorSymbol array. */
6747 size = attrs.numsymbols * sizeof *xpm_syms;
6748 xpm_syms = (XpmColorSymbol *) alloca (size);
6749 bzero (xpm_syms, size);
6750 attrs.colorsymbols = xpm_syms;
6752 /* Fill the color symbol array. */
6753 for (tail = color_symbols, i = 0;
6754 CONSP (tail);
6755 ++i, tail = XCDR (tail))
6757 Lisp_Object name = XCAR (XCAR (tail));
6758 Lisp_Object color = XCDR (XCAR (tail));
6759 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
6760 strcpy (xpm_syms[i].name, XSTRING (name)->data);
6761 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
6762 strcpy (xpm_syms[i].value, XSTRING (color)->data);
6766 /* Create a pixmap for the image, either from a file, or from a
6767 string buffer containing data in the same format as an XPM file. */
6768 BLOCK_INPUT;
6769 specified_file = image_spec_value (img->spec, QCfile, NULL);
6770 if (STRINGP (specified_file))
6772 Lisp_Object file = x_find_image_file (specified_file);
6773 if (!STRINGP (file))
6775 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6776 UNBLOCK_INPUT;
6777 return 0;
6780 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6781 XSTRING (file)->data, &img->pixmap, &img->mask,
6782 &attrs);
6784 else
6786 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
6787 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6788 XSTRING (buffer)->data,
6789 &img->pixmap, &img->mask,
6790 &attrs);
6792 UNBLOCK_INPUT;
6794 if (rc == XpmSuccess)
6796 /* Remember allocated colors. */
6797 img->ncolors = attrs.nalloc_pixels;
6798 img->colors = (unsigned long *) xmalloc (img->ncolors
6799 * sizeof *img->colors);
6800 for (i = 0; i < attrs.nalloc_pixels; ++i)
6802 img->colors[i] = attrs.alloc_pixels[i];
6803 #ifdef DEBUG_X_COLORS
6804 register_color (img->colors[i]);
6805 #endif
6808 img->width = attrs.width;
6809 img->height = attrs.height;
6810 xassert (img->width > 0 && img->height > 0);
6812 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6813 BLOCK_INPUT;
6814 XpmFreeAttributes (&attrs);
6815 UNBLOCK_INPUT;
6817 else
6819 switch (rc)
6821 case XpmOpenFailed:
6822 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
6823 break;
6825 case XpmFileInvalid:
6826 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
6827 break;
6829 case XpmNoMemory:
6830 image_error ("Out of memory (%s)", img->spec, Qnil);
6831 break;
6833 case XpmColorFailed:
6834 image_error ("Color allocation error (%s)", img->spec, Qnil);
6835 break;
6837 default:
6838 image_error ("Unknown error (%s)", img->spec, Qnil);
6839 break;
6843 return rc == XpmSuccess;
6846 #endif /* HAVE_XPM != 0 */
6849 /***********************************************************************
6850 Color table
6851 ***********************************************************************/
6853 /* An entry in the color table mapping an RGB color to a pixel color. */
6855 struct ct_color
6857 int r, g, b;
6858 unsigned long pixel;
6860 /* Next in color table collision list. */
6861 struct ct_color *next;
6864 /* The bucket vector size to use. Must be prime. */
6866 #define CT_SIZE 101
6868 /* Value is a hash of the RGB color given by R, G, and B. */
6870 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6872 /* The color hash table. */
6874 struct ct_color **ct_table;
6876 /* Number of entries in the color table. */
6878 int ct_colors_allocated;
6880 /* Function prototypes. */
6882 static void init_color_table P_ ((void));
6883 static void free_color_table P_ ((void));
6884 static unsigned long *colors_in_color_table P_ ((int *n));
6885 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
6886 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
6889 /* Initialize the color table. */
6891 static void
6892 init_color_table ()
6894 int size = CT_SIZE * sizeof (*ct_table);
6895 ct_table = (struct ct_color **) xmalloc (size);
6896 bzero (ct_table, size);
6897 ct_colors_allocated = 0;
6901 /* Free memory associated with the color table. */
6903 static void
6904 free_color_table ()
6906 int i;
6907 struct ct_color *p, *next;
6909 for (i = 0; i < CT_SIZE; ++i)
6910 for (p = ct_table[i]; p; p = next)
6912 next = p->next;
6913 xfree (p);
6916 xfree (ct_table);
6917 ct_table = NULL;
6921 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6922 entry for that color already is in the color table, return the
6923 pixel color of that entry. Otherwise, allocate a new color for R,
6924 G, B, and make an entry in the color table. */
6926 static unsigned long
6927 lookup_rgb_color (f, r, g, b)
6928 struct frame *f;
6929 int r, g, b;
6931 unsigned hash = CT_HASH_RGB (r, g, b);
6932 int i = hash % CT_SIZE;
6933 struct ct_color *p;
6935 for (p = ct_table[i]; p; p = p->next)
6936 if (p->r == r && p->g == g && p->b == b)
6937 break;
6939 if (p == NULL)
6941 XColor color;
6942 Colormap cmap;
6943 int rc;
6945 color.red = r;
6946 color.green = g;
6947 color.blue = b;
6949 BLOCK_INPUT;
6950 cmap = FRAME_X_COLORMAP (f);
6951 rc = x_alloc_nearest_color (f, cmap, &color);
6952 UNBLOCK_INPUT;
6954 if (rc)
6956 ++ct_colors_allocated;
6958 p = (struct ct_color *) xmalloc (sizeof *p);
6959 p->r = r;
6960 p->g = g;
6961 p->b = b;
6962 p->pixel = color.pixel;
6963 p->next = ct_table[i];
6964 ct_table[i] = p;
6966 else
6967 return FRAME_FOREGROUND_PIXEL (f);
6970 return p->pixel;
6974 /* Look up pixel color PIXEL which is used on frame F in the color
6975 table. If not already present, allocate it. Value is PIXEL. */
6977 static unsigned long
6978 lookup_pixel_color (f, pixel)
6979 struct frame *f;
6980 unsigned long pixel;
6982 int i = pixel % CT_SIZE;
6983 struct ct_color *p;
6985 for (p = ct_table[i]; p; p = p->next)
6986 if (p->pixel == pixel)
6987 break;
6989 if (p == NULL)
6991 XColor color;
6992 Colormap cmap;
6993 int rc;
6995 BLOCK_INPUT;
6997 cmap = FRAME_X_COLORMAP (f);
6998 color.pixel = pixel;
6999 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
7000 rc = x_alloc_nearest_color (f, cmap, &color);
7001 UNBLOCK_INPUT;
7003 if (rc)
7005 ++ct_colors_allocated;
7007 p = (struct ct_color *) xmalloc (sizeof *p);
7008 p->r = color.red;
7009 p->g = color.green;
7010 p->b = color.blue;
7011 p->pixel = pixel;
7012 p->next = ct_table[i];
7013 ct_table[i] = p;
7015 else
7016 return FRAME_FOREGROUND_PIXEL (f);
7019 return p->pixel;
7023 /* Value is a vector of all pixel colors contained in the color table,
7024 allocated via xmalloc. Set *N to the number of colors. */
7026 static unsigned long *
7027 colors_in_color_table (n)
7028 int *n;
7030 int i, j;
7031 struct ct_color *p;
7032 unsigned long *colors;
7034 if (ct_colors_allocated == 0)
7036 *n = 0;
7037 colors = NULL;
7039 else
7041 colors = (unsigned long *) xmalloc (ct_colors_allocated
7042 * sizeof *colors);
7043 *n = ct_colors_allocated;
7045 for (i = j = 0; i < CT_SIZE; ++i)
7046 for (p = ct_table[i]; p; p = p->next)
7047 colors[j++] = p->pixel;
7050 return colors;
7055 /***********************************************************************
7056 Algorithms
7057 ***********************************************************************/
7059 static void x_laplace_write_row P_ ((struct frame *, long *,
7060 int, XImage *, int));
7061 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7062 XColor *, int, XImage *, int));
7065 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
7066 frame we operate on, CMAP is the color-map in effect, and WIDTH is
7067 the width of one row in the image. */
7069 static void
7070 x_laplace_read_row (f, cmap, colors, width, ximg, y)
7071 struct frame *f;
7072 Colormap cmap;
7073 XColor *colors;
7074 int width;
7075 XImage *ximg;
7076 int y;
7078 int x;
7080 for (x = 0; x < width; ++x)
7081 colors[x].pixel = XGetPixel (ximg, x, y);
7083 XQueryColors (FRAME_X_DISPLAY (f), cmap, colors, width);
7087 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
7088 containing the pixel colors to write. F is the frame we are
7089 working on. */
7091 static void
7092 x_laplace_write_row (f, pixels, width, ximg, y)
7093 struct frame *f;
7094 long *pixels;
7095 int width;
7096 XImage *ximg;
7097 int y;
7099 int x;
7101 for (x = 0; x < width; ++x)
7102 XPutPixel (ximg, x, y, pixels[x]);
7106 /* Transform image IMG which is used on frame F with a Laplace
7107 edge-detection algorithm. The result is an image that can be used
7108 to draw disabled buttons, for example. */
7110 static void
7111 x_laplace (f, img)
7112 struct frame *f;
7113 struct image *img;
7115 Colormap cmap = FRAME_X_COLORMAP (f);
7116 XImage *ximg, *oimg;
7117 XColor *in[3];
7118 long *out;
7119 Pixmap pixmap;
7120 int x, y, i;
7121 long pixel;
7122 int in_y, out_y, rc;
7123 int mv2 = 45000;
7125 BLOCK_INPUT;
7127 /* Get the X image IMG->pixmap. */
7128 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7129 0, 0, img->width, img->height, ~0, ZPixmap);
7131 /* Allocate 3 input rows, and one output row of colors. */
7132 for (i = 0; i < 3; ++i)
7133 in[i] = (XColor *) alloca (img->width * sizeof (XColor));
7134 out = (long *) alloca (img->width * sizeof (long));
7136 /* Create an X image for output. */
7137 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7138 &oimg, &pixmap);
7140 /* Fill first two rows. */
7141 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
7142 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
7143 in_y = 2;
7145 /* Write first row, all zeros. */
7146 init_color_table ();
7147 pixel = lookup_rgb_color (f, 0, 0, 0);
7148 for (x = 0; x < img->width; ++x)
7149 out[x] = pixel;
7150 x_laplace_write_row (f, out, img->width, oimg, 0);
7151 out_y = 1;
7153 for (y = 2; y < img->height; ++y)
7155 int rowa = y % 3;
7156 int rowb = (y + 2) % 3;
7158 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
7160 for (x = 0; x < img->width - 2; ++x)
7162 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
7163 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
7164 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
7166 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
7167 b & 0xffff);
7170 x_laplace_write_row (f, out, img->width, oimg, out_y++);
7173 /* Write last line, all zeros. */
7174 for (x = 0; x < img->width; ++x)
7175 out[x] = pixel;
7176 x_laplace_write_row (f, out, img->width, oimg, out_y);
7178 /* Free the input image, and free resources of IMG. */
7179 XDestroyImage (ximg);
7180 x_clear_image (f, img);
7182 /* Put the output image into pixmap, and destroy it. */
7183 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7184 x_destroy_x_image (oimg);
7186 /* Remember new pixmap and colors in IMG. */
7187 img->pixmap = pixmap;
7188 img->colors = colors_in_color_table (&img->ncolors);
7189 free_color_table ();
7191 UNBLOCK_INPUT;
7195 /* Build a mask for image IMG which is used on frame F. FILE is the
7196 name of an image file, for error messages. HOW determines how to
7197 determine the background color of IMG. If it is a list '(R G B)',
7198 with R, G, and B being integers >= 0, take that as the color of the
7199 background. Otherwise, determine the background color of IMG
7200 heuristically. Value is non-zero if successful. */
7202 static int
7203 x_build_heuristic_mask (f, img, how)
7204 struct frame *f;
7205 struct image *img;
7206 Lisp_Object how;
7208 Display *dpy = FRAME_X_DISPLAY (f);
7209 XImage *ximg, *mask_img;
7210 int x, y, rc, look_at_corners_p;
7211 unsigned long bg;
7213 BLOCK_INPUT;
7215 /* Create an image and pixmap serving as mask. */
7216 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7217 &mask_img, &img->mask);
7218 if (!rc)
7220 UNBLOCK_INPUT;
7221 return 0;
7224 /* Get the X image of IMG->pixmap. */
7225 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7226 ~0, ZPixmap);
7228 /* Determine the background color of ximg. If HOW is `(R G B)'
7229 take that as color. Otherwise, try to determine the color
7230 heuristically. */
7231 look_at_corners_p = 1;
7233 if (CONSP (how))
7235 int rgb[3], i = 0;
7237 while (i < 3
7238 && CONSP (how)
7239 && NATNUMP (XCAR (how)))
7241 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
7242 how = XCDR (how);
7245 if (i == 3 && NILP (how))
7247 char color_name[30];
7248 XColor exact, color;
7249 Colormap cmap;
7251 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
7253 cmap = FRAME_X_COLORMAP (f);
7254 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
7256 bg = color.pixel;
7257 look_at_corners_p = 0;
7262 if (look_at_corners_p)
7264 unsigned long corners[4];
7265 int i, best_count;
7267 /* Get the colors at the corners of ximg. */
7268 corners[0] = XGetPixel (ximg, 0, 0);
7269 corners[1] = XGetPixel (ximg, img->width - 1, 0);
7270 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
7271 corners[3] = XGetPixel (ximg, 0, img->height - 1);
7273 /* Choose the most frequently found color as background. */
7274 for (i = best_count = 0; i < 4; ++i)
7276 int j, n;
7278 for (j = n = 0; j < 4; ++j)
7279 if (corners[i] == corners[j])
7280 ++n;
7282 if (n > best_count)
7283 bg = corners[i], best_count = n;
7287 /* Set all bits in mask_img to 1 whose color in ximg is different
7288 from the background color bg. */
7289 for (y = 0; y < img->height; ++y)
7290 for (x = 0; x < img->width; ++x)
7291 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7293 /* Put mask_img into img->mask. */
7294 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7295 x_destroy_x_image (mask_img);
7296 XDestroyImage (ximg);
7298 UNBLOCK_INPUT;
7299 return 1;
7304 /***********************************************************************
7305 PBM (mono, gray, color)
7306 ***********************************************************************/
7308 static int pbm_image_p P_ ((Lisp_Object object));
7309 static int pbm_load P_ ((struct frame *f, struct image *img));
7310 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7312 /* The symbol `pbm' identifying images of this type. */
7314 Lisp_Object Qpbm;
7316 /* Indices of image specification fields in gs_format, below. */
7318 enum pbm_keyword_index
7320 PBM_TYPE,
7321 PBM_FILE,
7322 PBM_DATA,
7323 PBM_ASCENT,
7324 PBM_MARGIN,
7325 PBM_RELIEF,
7326 PBM_ALGORITHM,
7327 PBM_HEURISTIC_MASK,
7328 PBM_LAST
7331 /* Vector of image_keyword structures describing the format
7332 of valid user-defined image specifications. */
7334 static struct image_keyword pbm_format[PBM_LAST] =
7336 {":type", IMAGE_SYMBOL_VALUE, 1},
7337 {":file", IMAGE_STRING_VALUE, 0},
7338 {":data", IMAGE_STRING_VALUE, 0},
7339 {":ascent", IMAGE_ASCENT_VALUE, 0},
7340 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7341 {":relief", IMAGE_INTEGER_VALUE, 0},
7342 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7343 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7346 /* Structure describing the image type `pbm'. */
7348 static struct image_type pbm_type =
7350 &Qpbm,
7351 pbm_image_p,
7352 pbm_load,
7353 x_clear_image,
7354 NULL
7358 /* Return non-zero if OBJECT is a valid PBM image specification. */
7360 static int
7361 pbm_image_p (object)
7362 Lisp_Object object;
7364 struct image_keyword fmt[PBM_LAST];
7366 bcopy (pbm_format, fmt, sizeof fmt);
7368 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
7369 return 0;
7371 /* Must specify either :data or :file. */
7372 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7376 /* Scan a decimal number from *S and return it. Advance *S while
7377 reading the number. END is the end of the string. Value is -1 at
7378 end of input. */
7380 static int
7381 pbm_scan_number (s, end)
7382 unsigned char **s, *end;
7384 int c, val = -1;
7386 while (*s < end)
7388 /* Skip white-space. */
7389 while (*s < end && (c = *(*s)++, isspace (c)))
7392 if (c == '#')
7394 /* Skip comment to end of line. */
7395 while (*s < end && (c = *(*s)++, c != '\n'))
7398 else if (isdigit (c))
7400 /* Read decimal number. */
7401 val = c - '0';
7402 while (*s < end && (c = *(*s)++, isdigit (c)))
7403 val = 10 * val + c - '0';
7404 break;
7406 else
7407 break;
7410 return val;
7414 /* Load PBM image IMG for use on frame F. */
7416 static int
7417 pbm_load (f, img)
7418 struct frame *f;
7419 struct image *img;
7421 int raw_p, x, y;
7422 int width, height, max_color_idx = 0;
7423 XImage *ximg;
7424 Lisp_Object file, specified_file;
7425 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7426 struct gcpro gcpro1;
7427 unsigned char *contents = NULL;
7428 unsigned char *end, *p;
7429 int size;
7431 specified_file = image_spec_value (img->spec, QCfile, NULL);
7432 file = Qnil;
7433 GCPRO1 (file);
7435 if (STRINGP (specified_file))
7437 file = x_find_image_file (specified_file);
7438 if (!STRINGP (file))
7440 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7441 UNGCPRO;
7442 return 0;
7445 contents = slurp_file (XSTRING (file)->data, &size);
7446 if (contents == NULL)
7448 image_error ("Error reading `%s'", file, Qnil);
7449 UNGCPRO;
7450 return 0;
7453 p = contents;
7454 end = contents + size;
7456 else
7458 Lisp_Object data;
7459 data = image_spec_value (img->spec, QCdata, NULL);
7460 p = XSTRING (data)->data;
7461 end = p + STRING_BYTES (XSTRING (data));
7464 /* Check magic number. */
7465 if (end - p < 2 || *p++ != 'P')
7467 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7468 error:
7469 xfree (contents);
7470 UNGCPRO;
7471 return 0;
7474 switch (*p++)
7476 case '1':
7477 raw_p = 0, type = PBM_MONO;
7478 break;
7480 case '2':
7481 raw_p = 0, type = PBM_GRAY;
7482 break;
7484 case '3':
7485 raw_p = 0, type = PBM_COLOR;
7486 break;
7488 case '4':
7489 raw_p = 1, type = PBM_MONO;
7490 break;
7492 case '5':
7493 raw_p = 1, type = PBM_GRAY;
7494 break;
7496 case '6':
7497 raw_p = 1, type = PBM_COLOR;
7498 break;
7500 default:
7501 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7502 goto error;
7505 /* Read width, height, maximum color-component. Characters
7506 starting with `#' up to the end of a line are ignored. */
7507 width = pbm_scan_number (&p, end);
7508 height = pbm_scan_number (&p, end);
7510 if (type != PBM_MONO)
7512 max_color_idx = pbm_scan_number (&p, end);
7513 if (raw_p && max_color_idx > 255)
7514 max_color_idx = 255;
7517 if (width < 0
7518 || height < 0
7519 || (type != PBM_MONO && max_color_idx < 0))
7520 goto error;
7522 BLOCK_INPUT;
7523 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7524 &ximg, &img->pixmap))
7526 UNBLOCK_INPUT;
7527 goto error;
7530 /* Initialize the color hash table. */
7531 init_color_table ();
7533 if (type == PBM_MONO)
7535 int c = 0, g;
7537 for (y = 0; y < height; ++y)
7538 for (x = 0; x < width; ++x)
7540 if (raw_p)
7542 if ((x & 7) == 0)
7543 c = *p++;
7544 g = c & 0x80;
7545 c <<= 1;
7547 else
7548 g = pbm_scan_number (&p, end);
7550 XPutPixel (ximg, x, y, (g
7551 ? FRAME_FOREGROUND_PIXEL (f)
7552 : FRAME_BACKGROUND_PIXEL (f)));
7555 else
7557 for (y = 0; y < height; ++y)
7558 for (x = 0; x < width; ++x)
7560 int r, g, b;
7562 if (type == PBM_GRAY)
7563 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
7564 else if (raw_p)
7566 r = *p++;
7567 g = *p++;
7568 b = *p++;
7570 else
7572 r = pbm_scan_number (&p, end);
7573 g = pbm_scan_number (&p, end);
7574 b = pbm_scan_number (&p, end);
7577 if (r < 0 || g < 0 || b < 0)
7579 xfree (ximg->data);
7580 ximg->data = NULL;
7581 XDestroyImage (ximg);
7582 UNBLOCK_INPUT;
7583 image_error ("Invalid pixel value in image `%s'",
7584 img->spec, Qnil);
7585 goto error;
7588 /* RGB values are now in the range 0..max_color_idx.
7589 Scale this to the range 0..0xffff supported by X. */
7590 r = (double) r * 65535 / max_color_idx;
7591 g = (double) g * 65535 / max_color_idx;
7592 b = (double) b * 65535 / max_color_idx;
7593 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7597 /* Store in IMG->colors the colors allocated for the image, and
7598 free the color table. */
7599 img->colors = colors_in_color_table (&img->ncolors);
7600 free_color_table ();
7602 /* Put the image into a pixmap. */
7603 x_put_x_image (f, ximg, img->pixmap, width, height);
7604 x_destroy_x_image (ximg);
7605 UNBLOCK_INPUT;
7607 img->width = width;
7608 img->height = height;
7610 UNGCPRO;
7611 xfree (contents);
7612 return 1;
7617 /***********************************************************************
7619 ***********************************************************************/
7621 #if HAVE_PNG
7623 #include <png.h>
7625 /* Function prototypes. */
7627 static int png_image_p P_ ((Lisp_Object object));
7628 static int png_load P_ ((struct frame *f, struct image *img));
7630 /* The symbol `png' identifying images of this type. */
7632 Lisp_Object Qpng;
7634 /* Indices of image specification fields in png_format, below. */
7636 enum png_keyword_index
7638 PNG_TYPE,
7639 PNG_DATA,
7640 PNG_FILE,
7641 PNG_ASCENT,
7642 PNG_MARGIN,
7643 PNG_RELIEF,
7644 PNG_ALGORITHM,
7645 PNG_HEURISTIC_MASK,
7646 PNG_LAST
7649 /* Vector of image_keyword structures describing the format
7650 of valid user-defined image specifications. */
7652 static struct image_keyword png_format[PNG_LAST] =
7654 {":type", IMAGE_SYMBOL_VALUE, 1},
7655 {":data", IMAGE_STRING_VALUE, 0},
7656 {":file", IMAGE_STRING_VALUE, 0},
7657 {":ascent", IMAGE_ASCENT_VALUE, 0},
7658 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7659 {":relief", IMAGE_INTEGER_VALUE, 0},
7660 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7661 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7664 /* Structure describing the image type `png'. */
7666 static struct image_type png_type =
7668 &Qpng,
7669 png_image_p,
7670 png_load,
7671 x_clear_image,
7672 NULL
7676 /* Return non-zero if OBJECT is a valid PNG image specification. */
7678 static int
7679 png_image_p (object)
7680 Lisp_Object object;
7682 struct image_keyword fmt[PNG_LAST];
7683 bcopy (png_format, fmt, sizeof fmt);
7685 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
7686 return 0;
7688 /* Must specify either the :data or :file keyword. */
7689 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7693 /* Error and warning handlers installed when the PNG library
7694 is initialized. */
7696 static void
7697 my_png_error (png_ptr, msg)
7698 png_struct *png_ptr;
7699 char *msg;
7701 xassert (png_ptr != NULL);
7702 image_error ("PNG error: %s", build_string (msg), Qnil);
7703 longjmp (png_ptr->jmpbuf, 1);
7707 static void
7708 my_png_warning (png_ptr, msg)
7709 png_struct *png_ptr;
7710 char *msg;
7712 xassert (png_ptr != NULL);
7713 image_error ("PNG warning: %s", build_string (msg), Qnil);
7716 /* Memory source for PNG decoding. */
7718 struct png_memory_storage
7720 unsigned char *bytes; /* The data */
7721 size_t len; /* How big is it? */
7722 int index; /* Where are we? */
7726 /* Function set as reader function when reading PNG image from memory.
7727 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7728 bytes from the input to DATA. */
7730 static void
7731 png_read_from_memory (png_ptr, data, length)
7732 png_structp png_ptr;
7733 png_bytep data;
7734 png_size_t length;
7736 struct png_memory_storage *tbr
7737 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
7739 if (length > tbr->len - tbr->index)
7740 png_error (png_ptr, "Read error");
7742 bcopy (tbr->bytes + tbr->index, data, length);
7743 tbr->index = tbr->index + length;
7746 /* Load PNG image IMG for use on frame F. Value is non-zero if
7747 successful. */
7749 static int
7750 png_load (f, img)
7751 struct frame *f;
7752 struct image *img;
7754 Lisp_Object file, specified_file;
7755 Lisp_Object specified_data;
7756 int x, y, i;
7757 XImage *ximg, *mask_img = NULL;
7758 struct gcpro gcpro1;
7759 png_struct *png_ptr = NULL;
7760 png_info *info_ptr = NULL, *end_info = NULL;
7761 FILE *fp = NULL;
7762 png_byte sig[8];
7763 png_byte *pixels = NULL;
7764 png_byte **rows = NULL;
7765 png_uint_32 width, height;
7766 int bit_depth, color_type, interlace_type;
7767 png_byte channels;
7768 png_uint_32 row_bytes;
7769 int transparent_p;
7770 char *gamma_str;
7771 double screen_gamma, image_gamma;
7772 int intent;
7773 struct png_memory_storage tbr; /* Data to be read */
7775 /* Find out what file to load. */
7776 specified_file = image_spec_value (img->spec, QCfile, NULL);
7777 specified_data = image_spec_value (img->spec, QCdata, NULL);
7778 file = Qnil;
7779 GCPRO1 (file);
7781 if (NILP (specified_data))
7783 file = x_find_image_file (specified_file);
7784 if (!STRINGP (file))
7786 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7787 UNGCPRO;
7788 return 0;
7791 /* Open the image file. */
7792 fp = fopen (XSTRING (file)->data, "rb");
7793 if (!fp)
7795 image_error ("Cannot open image file `%s'", file, Qnil);
7796 UNGCPRO;
7797 fclose (fp);
7798 return 0;
7801 /* Check PNG signature. */
7802 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7803 || !png_check_sig (sig, sizeof sig))
7805 image_error ("Not a PNG file: `%s'", file, Qnil);
7806 UNGCPRO;
7807 fclose (fp);
7808 return 0;
7811 else
7813 /* Read from memory. */
7814 tbr.bytes = XSTRING (specified_data)->data;
7815 tbr.len = STRING_BYTES (XSTRING (specified_data));
7816 tbr.index = 0;
7818 /* Check PNG signature. */
7819 if (tbr.len < sizeof sig
7820 || !png_check_sig (tbr.bytes, sizeof sig))
7822 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
7823 UNGCPRO;
7824 return 0;
7827 /* Need to skip past the signature. */
7828 tbr.bytes += sizeof (sig);
7831 /* Initialize read and info structs for PNG lib. */
7832 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7833 my_png_error, my_png_warning);
7834 if (!png_ptr)
7836 if (fp) fclose (fp);
7837 UNGCPRO;
7838 return 0;
7841 info_ptr = png_create_info_struct (png_ptr);
7842 if (!info_ptr)
7844 png_destroy_read_struct (&png_ptr, NULL, NULL);
7845 if (fp) fclose (fp);
7846 UNGCPRO;
7847 return 0;
7850 end_info = png_create_info_struct (png_ptr);
7851 if (!end_info)
7853 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7854 if (fp) fclose (fp);
7855 UNGCPRO;
7856 return 0;
7859 /* Set error jump-back. We come back here when the PNG library
7860 detects an error. */
7861 if (setjmp (png_ptr->jmpbuf))
7863 error:
7864 if (png_ptr)
7865 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7866 xfree (pixels);
7867 xfree (rows);
7868 if (fp) fclose (fp);
7869 UNGCPRO;
7870 return 0;
7873 /* Read image info. */
7874 if (!NILP (specified_data))
7875 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
7876 else
7877 png_init_io (png_ptr, fp);
7879 png_set_sig_bytes (png_ptr, sizeof sig);
7880 png_read_info (png_ptr, info_ptr);
7881 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
7882 &interlace_type, NULL, NULL);
7884 /* If image contains simply transparency data, we prefer to
7885 construct a clipping mask. */
7886 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
7887 transparent_p = 1;
7888 else
7889 transparent_p = 0;
7891 /* This function is easier to write if we only have to handle
7892 one data format: RGB or RGBA with 8 bits per channel. Let's
7893 transform other formats into that format. */
7895 /* Strip more than 8 bits per channel. */
7896 if (bit_depth == 16)
7897 png_set_strip_16 (png_ptr);
7899 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7900 if available. */
7901 png_set_expand (png_ptr);
7903 /* Convert grayscale images to RGB. */
7904 if (color_type == PNG_COLOR_TYPE_GRAY
7905 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7906 png_set_gray_to_rgb (png_ptr);
7908 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
7909 gamma_str = getenv ("SCREEN_GAMMA");
7910 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
7912 /* Tell the PNG lib to handle gamma correction for us. */
7914 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7915 if (png_get_sRGB (png_ptr, info_ptr, &intent))
7916 /* There is a special chunk in the image specifying the gamma. */
7917 png_set_sRGB (png_ptr, info_ptr, intent);
7918 else
7919 #endif
7920 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
7921 /* Image contains gamma information. */
7922 png_set_gamma (png_ptr, screen_gamma, image_gamma);
7923 else
7924 /* Use a default of 0.5 for the image gamma. */
7925 png_set_gamma (png_ptr, screen_gamma, 0.5);
7927 /* Handle alpha channel by combining the image with a background
7928 color. Do this only if a real alpha channel is supplied. For
7929 simple transparency, we prefer a clipping mask. */
7930 if (!transparent_p)
7932 png_color_16 *image_background;
7934 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
7935 /* Image contains a background color with which to
7936 combine the image. */
7937 png_set_background (png_ptr, image_background,
7938 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
7939 else
7941 /* Image does not contain a background color with which
7942 to combine the image data via an alpha channel. Use
7943 the frame's background instead. */
7944 XColor color;
7945 Colormap cmap;
7946 png_color_16 frame_background;
7948 BLOCK_INPUT;
7949 cmap = FRAME_X_COLORMAP (f);
7950 color.pixel = FRAME_BACKGROUND_PIXEL (f);
7951 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
7952 UNBLOCK_INPUT;
7954 bzero (&frame_background, sizeof frame_background);
7955 frame_background.red = color.red;
7956 frame_background.green = color.green;
7957 frame_background.blue = color.blue;
7959 png_set_background (png_ptr, &frame_background,
7960 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7964 /* Update info structure. */
7965 png_read_update_info (png_ptr, info_ptr);
7967 /* Get number of channels. Valid values are 1 for grayscale images
7968 and images with a palette, 2 for grayscale images with transparency
7969 information (alpha channel), 3 for RGB images, and 4 for RGB
7970 images with alpha channel, i.e. RGBA. If conversions above were
7971 sufficient we should only have 3 or 4 channels here. */
7972 channels = png_get_channels (png_ptr, info_ptr);
7973 xassert (channels == 3 || channels == 4);
7975 /* Number of bytes needed for one row of the image. */
7976 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
7978 /* Allocate memory for the image. */
7979 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
7980 rows = (png_byte **) xmalloc (height * sizeof *rows);
7981 for (i = 0; i < height; ++i)
7982 rows[i] = pixels + i * row_bytes;
7984 /* Read the entire image. */
7985 png_read_image (png_ptr, rows);
7986 png_read_end (png_ptr, info_ptr);
7987 if (fp)
7989 fclose (fp);
7990 fp = NULL;
7993 BLOCK_INPUT;
7995 /* Create the X image and pixmap. */
7996 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7997 &img->pixmap))
7999 UNBLOCK_INPUT;
8000 goto error;
8003 /* Create an image and pixmap serving as mask if the PNG image
8004 contains an alpha channel. */
8005 if (channels == 4
8006 && !transparent_p
8007 && !x_create_x_image_and_pixmap (f, width, height, 1,
8008 &mask_img, &img->mask))
8010 x_destroy_x_image (ximg);
8011 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8012 img->pixmap = 0;
8013 UNBLOCK_INPUT;
8014 goto error;
8017 /* Fill the X image and mask from PNG data. */
8018 init_color_table ();
8020 for (y = 0; y < height; ++y)
8022 png_byte *p = rows[y];
8024 for (x = 0; x < width; ++x)
8026 unsigned r, g, b;
8028 r = *p++ << 8;
8029 g = *p++ << 8;
8030 b = *p++ << 8;
8031 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8033 /* An alpha channel, aka mask channel, associates variable
8034 transparency with an image. Where other image formats
8035 support binary transparency---fully transparent or fully
8036 opaque---PNG allows up to 254 levels of partial transparency.
8037 The PNG library implements partial transparency by combining
8038 the image with a specified background color.
8040 I'm not sure how to handle this here nicely: because the
8041 background on which the image is displayed may change, for
8042 real alpha channel support, it would be necessary to create
8043 a new image for each possible background.
8045 What I'm doing now is that a mask is created if we have
8046 boolean transparency information. Otherwise I'm using
8047 the frame's background color to combine the image with. */
8049 if (channels == 4)
8051 if (mask_img)
8052 XPutPixel (mask_img, x, y, *p > 0);
8053 ++p;
8058 /* Remember colors allocated for this image. */
8059 img->colors = colors_in_color_table (&img->ncolors);
8060 free_color_table ();
8062 /* Clean up. */
8063 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8064 xfree (rows);
8065 xfree (pixels);
8067 img->width = width;
8068 img->height = height;
8070 /* Put the image into the pixmap, then free the X image and its buffer. */
8071 x_put_x_image (f, ximg, img->pixmap, width, height);
8072 x_destroy_x_image (ximg);
8074 /* Same for the mask. */
8075 if (mask_img)
8077 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8078 x_destroy_x_image (mask_img);
8081 UNBLOCK_INPUT;
8082 UNGCPRO;
8083 return 1;
8086 #endif /* HAVE_PNG != 0 */
8090 /***********************************************************************
8091 JPEG
8092 ***********************************************************************/
8094 #if HAVE_JPEG
8096 /* Work around a warning about HAVE_STDLIB_H being redefined in
8097 jconfig.h. */
8098 #ifdef HAVE_STDLIB_H
8099 #define HAVE_STDLIB_H_1
8100 #undef HAVE_STDLIB_H
8101 #endif /* HAVE_STLIB_H */
8103 #include <jpeglib.h>
8104 #include <jerror.h>
8105 #include <setjmp.h>
8107 #ifdef HAVE_STLIB_H_1
8108 #define HAVE_STDLIB_H 1
8109 #endif
8111 static int jpeg_image_p P_ ((Lisp_Object object));
8112 static int jpeg_load P_ ((struct frame *f, struct image *img));
8114 /* The symbol `jpeg' identifying images of this type. */
8116 Lisp_Object Qjpeg;
8118 /* Indices of image specification fields in gs_format, below. */
8120 enum jpeg_keyword_index
8122 JPEG_TYPE,
8123 JPEG_DATA,
8124 JPEG_FILE,
8125 JPEG_ASCENT,
8126 JPEG_MARGIN,
8127 JPEG_RELIEF,
8128 JPEG_ALGORITHM,
8129 JPEG_HEURISTIC_MASK,
8130 JPEG_LAST
8133 /* Vector of image_keyword structures describing the format
8134 of valid user-defined image specifications. */
8136 static struct image_keyword jpeg_format[JPEG_LAST] =
8138 {":type", IMAGE_SYMBOL_VALUE, 1},
8139 {":data", IMAGE_STRING_VALUE, 0},
8140 {":file", IMAGE_STRING_VALUE, 0},
8141 {":ascent", IMAGE_ASCENT_VALUE, 0},
8142 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8143 {":relief", IMAGE_INTEGER_VALUE, 0},
8144 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8145 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8148 /* Structure describing the image type `jpeg'. */
8150 static struct image_type jpeg_type =
8152 &Qjpeg,
8153 jpeg_image_p,
8154 jpeg_load,
8155 x_clear_image,
8156 NULL
8160 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8162 static int
8163 jpeg_image_p (object)
8164 Lisp_Object object;
8166 struct image_keyword fmt[JPEG_LAST];
8168 bcopy (jpeg_format, fmt, sizeof fmt);
8170 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8171 return 0;
8173 /* Must specify either the :data or :file keyword. */
8174 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8178 struct my_jpeg_error_mgr
8180 struct jpeg_error_mgr pub;
8181 jmp_buf setjmp_buffer;
8185 static void
8186 my_error_exit (cinfo)
8187 j_common_ptr cinfo;
8189 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8190 longjmp (mgr->setjmp_buffer, 1);
8194 /* Init source method for JPEG data source manager. Called by
8195 jpeg_read_header() before any data is actually read. See
8196 libjpeg.doc from the JPEG lib distribution. */
8198 static void
8199 our_init_source (cinfo)
8200 j_decompress_ptr cinfo;
8205 /* Fill input buffer method for JPEG data source manager. Called
8206 whenever more data is needed. We read the whole image in one step,
8207 so this only adds a fake end of input marker at the end. */
8209 static boolean
8210 our_fill_input_buffer (cinfo)
8211 j_decompress_ptr cinfo;
8213 /* Insert a fake EOI marker. */
8214 struct jpeg_source_mgr *src = cinfo->src;
8215 static JOCTET buffer[2];
8217 buffer[0] = (JOCTET) 0xFF;
8218 buffer[1] = (JOCTET) JPEG_EOI;
8220 src->next_input_byte = buffer;
8221 src->bytes_in_buffer = 2;
8222 return TRUE;
8226 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8227 is the JPEG data source manager. */
8229 static void
8230 our_skip_input_data (cinfo, num_bytes)
8231 j_decompress_ptr cinfo;
8232 long num_bytes;
8234 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
8236 if (src)
8238 if (num_bytes > src->bytes_in_buffer)
8239 ERREXIT (cinfo, JERR_INPUT_EOF);
8241 src->bytes_in_buffer -= num_bytes;
8242 src->next_input_byte += num_bytes;
8247 /* Method to terminate data source. Called by
8248 jpeg_finish_decompress() after all data has been processed. */
8250 static void
8251 our_term_source (cinfo)
8252 j_decompress_ptr cinfo;
8257 /* Set up the JPEG lib for reading an image from DATA which contains
8258 LEN bytes. CINFO is the decompression info structure created for
8259 reading the image. */
8261 static void
8262 jpeg_memory_src (cinfo, data, len)
8263 j_decompress_ptr cinfo;
8264 JOCTET *data;
8265 unsigned int len;
8267 struct jpeg_source_mgr *src;
8269 if (cinfo->src == NULL)
8271 /* First time for this JPEG object? */
8272 cinfo->src = (struct jpeg_source_mgr *)
8273 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
8274 sizeof (struct jpeg_source_mgr));
8275 src = (struct jpeg_source_mgr *) cinfo->src;
8276 src->next_input_byte = data;
8279 src = (struct jpeg_source_mgr *) cinfo->src;
8280 src->init_source = our_init_source;
8281 src->fill_input_buffer = our_fill_input_buffer;
8282 src->skip_input_data = our_skip_input_data;
8283 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
8284 src->term_source = our_term_source;
8285 src->bytes_in_buffer = len;
8286 src->next_input_byte = data;
8290 /* Load image IMG for use on frame F. Patterned after example.c
8291 from the JPEG lib. */
8293 static int
8294 jpeg_load (f, img)
8295 struct frame *f;
8296 struct image *img;
8298 struct jpeg_decompress_struct cinfo;
8299 struct my_jpeg_error_mgr mgr;
8300 Lisp_Object file, specified_file;
8301 Lisp_Object specified_data;
8302 FILE *fp = NULL;
8303 JSAMPARRAY buffer;
8304 int row_stride, x, y;
8305 XImage *ximg = NULL;
8306 int rc;
8307 unsigned long *colors;
8308 int width, height;
8309 struct gcpro gcpro1;
8311 /* Open the JPEG file. */
8312 specified_file = image_spec_value (img->spec, QCfile, NULL);
8313 specified_data = image_spec_value (img->spec, QCdata, NULL);
8314 file = Qnil;
8315 GCPRO1 (file);
8317 if (NILP (specified_data))
8319 file = x_find_image_file (specified_file);
8320 if (!STRINGP (file))
8322 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8323 UNGCPRO;
8324 return 0;
8327 fp = fopen (XSTRING (file)->data, "r");
8328 if (fp == NULL)
8330 image_error ("Cannot open `%s'", file, Qnil);
8331 UNGCPRO;
8332 return 0;
8336 /* Customize libjpeg's error handling to call my_error_exit when an
8337 error is detected. This function will perform a longjmp. */
8338 cinfo.err = jpeg_std_error (&mgr.pub);
8339 mgr.pub.error_exit = my_error_exit;
8341 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8343 if (rc == 1)
8345 /* Called from my_error_exit. Display a JPEG error. */
8346 char buffer[JMSG_LENGTH_MAX];
8347 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8348 image_error ("Error reading JPEG image `%s': %s", img->spec,
8349 build_string (buffer));
8352 /* Close the input file and destroy the JPEG object. */
8353 if (fp)
8354 fclose (fp);
8355 jpeg_destroy_decompress (&cinfo);
8357 BLOCK_INPUT;
8359 /* If we already have an XImage, free that. */
8360 x_destroy_x_image (ximg);
8362 /* Free pixmap and colors. */
8363 x_clear_image (f, img);
8365 UNBLOCK_INPUT;
8366 UNGCPRO;
8367 return 0;
8370 /* Create the JPEG decompression object. Let it read from fp.
8371 Read the JPEG image header. */
8372 jpeg_create_decompress (&cinfo);
8374 if (NILP (specified_data))
8375 jpeg_stdio_src (&cinfo, fp);
8376 else
8377 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
8378 STRING_BYTES (XSTRING (specified_data)));
8380 jpeg_read_header (&cinfo, TRUE);
8382 /* Customize decompression so that color quantization will be used.
8383 Start decompression. */
8384 cinfo.quantize_colors = TRUE;
8385 jpeg_start_decompress (&cinfo);
8386 width = img->width = cinfo.output_width;
8387 height = img->height = cinfo.output_height;
8389 BLOCK_INPUT;
8391 /* Create X image and pixmap. */
8392 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8394 UNBLOCK_INPUT;
8395 longjmp (mgr.setjmp_buffer, 2);
8398 /* Allocate colors. When color quantization is used,
8399 cinfo.actual_number_of_colors has been set with the number of
8400 colors generated, and cinfo.colormap is a two-dimensional array
8401 of color indices in the range 0..cinfo.actual_number_of_colors.
8402 No more than 255 colors will be generated. */
8404 int i, ir, ig, ib;
8406 if (cinfo.out_color_components > 2)
8407 ir = 0, ig = 1, ib = 2;
8408 else if (cinfo.out_color_components > 1)
8409 ir = 0, ig = 1, ib = 0;
8410 else
8411 ir = 0, ig = 0, ib = 0;
8413 /* Use the color table mechanism because it handles colors that
8414 cannot be allocated nicely. Such colors will be replaced with
8415 a default color, and we don't have to care about which colors
8416 can be freed safely, and which can't. */
8417 init_color_table ();
8418 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8419 * sizeof *colors);
8421 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8423 /* Multiply RGB values with 255 because X expects RGB values
8424 in the range 0..0xffff. */
8425 int r = cinfo.colormap[ir][i] << 8;
8426 int g = cinfo.colormap[ig][i] << 8;
8427 int b = cinfo.colormap[ib][i] << 8;
8428 colors[i] = lookup_rgb_color (f, r, g, b);
8431 /* Remember those colors actually allocated. */
8432 img->colors = colors_in_color_table (&img->ncolors);
8433 free_color_table ();
8436 /* Read pixels. */
8437 row_stride = width * cinfo.output_components;
8438 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
8439 row_stride, 1);
8440 for (y = 0; y < height; ++y)
8442 jpeg_read_scanlines (&cinfo, buffer, 1);
8443 for (x = 0; x < cinfo.output_width; ++x)
8444 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
8447 /* Clean up. */
8448 jpeg_finish_decompress (&cinfo);
8449 jpeg_destroy_decompress (&cinfo);
8450 if (fp)
8451 fclose (fp);
8453 /* Put the image into the pixmap. */
8454 x_put_x_image (f, ximg, img->pixmap, width, height);
8455 x_destroy_x_image (ximg);
8456 UNBLOCK_INPUT;
8457 UNGCPRO;
8458 return 1;
8461 #endif /* HAVE_JPEG */
8465 /***********************************************************************
8466 TIFF
8467 ***********************************************************************/
8469 #if HAVE_TIFF
8471 #include <tiffio.h>
8473 static int tiff_image_p P_ ((Lisp_Object object));
8474 static int tiff_load P_ ((struct frame *f, struct image *img));
8476 /* The symbol `tiff' identifying images of this type. */
8478 Lisp_Object Qtiff;
8480 /* Indices of image specification fields in tiff_format, below. */
8482 enum tiff_keyword_index
8484 TIFF_TYPE,
8485 TIFF_DATA,
8486 TIFF_FILE,
8487 TIFF_ASCENT,
8488 TIFF_MARGIN,
8489 TIFF_RELIEF,
8490 TIFF_ALGORITHM,
8491 TIFF_HEURISTIC_MASK,
8492 TIFF_LAST
8495 /* Vector of image_keyword structures describing the format
8496 of valid user-defined image specifications. */
8498 static struct image_keyword tiff_format[TIFF_LAST] =
8500 {":type", IMAGE_SYMBOL_VALUE, 1},
8501 {":data", IMAGE_STRING_VALUE, 0},
8502 {":file", IMAGE_STRING_VALUE, 0},
8503 {":ascent", IMAGE_ASCENT_VALUE, 0},
8504 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8505 {":relief", IMAGE_INTEGER_VALUE, 0},
8506 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8507 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8510 /* Structure describing the image type `tiff'. */
8512 static struct image_type tiff_type =
8514 &Qtiff,
8515 tiff_image_p,
8516 tiff_load,
8517 x_clear_image,
8518 NULL
8522 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8524 static int
8525 tiff_image_p (object)
8526 Lisp_Object object;
8528 struct image_keyword fmt[TIFF_LAST];
8529 bcopy (tiff_format, fmt, sizeof fmt);
8531 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
8532 return 0;
8534 /* Must specify either the :data or :file keyword. */
8535 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8539 /* Reading from a memory buffer for TIFF images Based on the PNG
8540 memory source, but we have to provide a lot of extra functions.
8541 Blah.
8543 We really only need to implement read and seek, but I am not
8544 convinced that the TIFF library is smart enough not to destroy
8545 itself if we only hand it the function pointers we need to
8546 override. */
8548 typedef struct
8550 unsigned char *bytes;
8551 size_t len;
8552 int index;
8554 tiff_memory_source;
8557 static size_t
8558 tiff_read_from_memory (data, buf, size)
8559 thandle_t data;
8560 tdata_t buf;
8561 tsize_t size;
8563 tiff_memory_source *src = (tiff_memory_source *) data;
8565 if (size > src->len - src->index)
8566 return (size_t) -1;
8567 bcopy (src->bytes + src->index, buf, size);
8568 src->index += size;
8569 return size;
8573 static size_t
8574 tiff_write_from_memory (data, buf, size)
8575 thandle_t data;
8576 tdata_t buf;
8577 tsize_t size;
8579 return (size_t) -1;
8583 static toff_t
8584 tiff_seek_in_memory (data, off, whence)
8585 thandle_t data;
8586 toff_t off;
8587 int whence;
8589 tiff_memory_source *src = (tiff_memory_source *) data;
8590 int idx;
8592 switch (whence)
8594 case SEEK_SET: /* Go from beginning of source. */
8595 idx = off;
8596 break;
8598 case SEEK_END: /* Go from end of source. */
8599 idx = src->len + off;
8600 break;
8602 case SEEK_CUR: /* Go from current position. */
8603 idx = src->index + off;
8604 break;
8606 default: /* Invalid `whence'. */
8607 return -1;
8610 if (idx > src->len || idx < 0)
8611 return -1;
8613 src->index = idx;
8614 return src->index;
8618 static int
8619 tiff_close_memory (data)
8620 thandle_t data;
8622 /* NOOP */
8623 return 0;
8627 static int
8628 tiff_mmap_memory (data, pbase, psize)
8629 thandle_t data;
8630 tdata_t *pbase;
8631 toff_t *psize;
8633 /* It is already _IN_ memory. */
8634 return 0;
8638 static void
8639 tiff_unmap_memory (data, base, size)
8640 thandle_t data;
8641 tdata_t base;
8642 toff_t size;
8644 /* We don't need to do this. */
8648 static toff_t
8649 tiff_size_of_memory (data)
8650 thandle_t data;
8652 return ((tiff_memory_source *) data)->len;
8656 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8657 successful. */
8659 static int
8660 tiff_load (f, img)
8661 struct frame *f;
8662 struct image *img;
8664 Lisp_Object file, specified_file;
8665 Lisp_Object specified_data;
8666 TIFF *tiff;
8667 int width, height, x, y;
8668 uint32 *buf;
8669 int rc;
8670 XImage *ximg;
8671 struct gcpro gcpro1;
8672 tiff_memory_source memsrc;
8674 specified_file = image_spec_value (img->spec, QCfile, NULL);
8675 specified_data = image_spec_value (img->spec, QCdata, NULL);
8676 file = Qnil;
8677 GCPRO1 (file);
8679 if (NILP (specified_data))
8681 /* Read from a file */
8682 file = x_find_image_file (specified_file);
8683 if (!STRINGP (file))
8685 image_error ("Cannot find image file `%s'", file, Qnil);
8686 UNGCPRO;
8687 return 0;
8690 /* Try to open the image file. */
8691 tiff = TIFFOpen (XSTRING (file)->data, "r");
8692 if (tiff == NULL)
8694 image_error ("Cannot open `%s'", file, Qnil);
8695 UNGCPRO;
8696 return 0;
8699 else
8701 /* Memory source! */
8702 memsrc.bytes = XSTRING (specified_data)->data;
8703 memsrc.len = STRING_BYTES (XSTRING (specified_data));
8704 memsrc.index = 0;
8706 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8707 (TIFFReadWriteProc) tiff_read_from_memory,
8708 (TIFFReadWriteProc) tiff_write_from_memory,
8709 tiff_seek_in_memory,
8710 tiff_close_memory,
8711 tiff_size_of_memory,
8712 tiff_mmap_memory,
8713 tiff_unmap_memory);
8715 if (!tiff)
8717 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
8718 UNGCPRO;
8719 return 0;
8723 /* Get width and height of the image, and allocate a raster buffer
8724 of width x height 32-bit values. */
8725 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8726 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8727 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8729 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8730 TIFFClose (tiff);
8731 if (!rc)
8733 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8734 xfree (buf);
8735 UNGCPRO;
8736 return 0;
8739 BLOCK_INPUT;
8741 /* Create the X image and pixmap. */
8742 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8744 UNBLOCK_INPUT;
8745 xfree (buf);
8746 UNGCPRO;
8747 return 0;
8750 /* Initialize the color table. */
8751 init_color_table ();
8753 /* Process the pixel raster. Origin is in the lower-left corner. */
8754 for (y = 0; y < height; ++y)
8756 uint32 *row = buf + y * width;
8758 for (x = 0; x < width; ++x)
8760 uint32 abgr = row[x];
8761 int r = TIFFGetR (abgr) << 8;
8762 int g = TIFFGetG (abgr) << 8;
8763 int b = TIFFGetB (abgr) << 8;
8764 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8768 /* Remember the colors allocated for the image. Free the color table. */
8769 img->colors = colors_in_color_table (&img->ncolors);
8770 free_color_table ();
8772 /* Put the image into the pixmap, then free the X image and its buffer. */
8773 x_put_x_image (f, ximg, img->pixmap, width, height);
8774 x_destroy_x_image (ximg);
8775 xfree (buf);
8776 UNBLOCK_INPUT;
8778 img->width = width;
8779 img->height = height;
8781 UNGCPRO;
8782 return 1;
8785 #endif /* HAVE_TIFF != 0 */
8789 /***********************************************************************
8791 ***********************************************************************/
8793 #if HAVE_GIF
8795 #include <gif_lib.h>
8797 static int gif_image_p P_ ((Lisp_Object object));
8798 static int gif_load P_ ((struct frame *f, struct image *img));
8800 /* The symbol `gif' identifying images of this type. */
8802 Lisp_Object Qgif;
8804 /* Indices of image specification fields in gif_format, below. */
8806 enum gif_keyword_index
8808 GIF_TYPE,
8809 GIF_DATA,
8810 GIF_FILE,
8811 GIF_ASCENT,
8812 GIF_MARGIN,
8813 GIF_RELIEF,
8814 GIF_ALGORITHM,
8815 GIF_HEURISTIC_MASK,
8816 GIF_IMAGE,
8817 GIF_LAST
8820 /* Vector of image_keyword structures describing the format
8821 of valid user-defined image specifications. */
8823 static struct image_keyword gif_format[GIF_LAST] =
8825 {":type", IMAGE_SYMBOL_VALUE, 1},
8826 {":data", IMAGE_STRING_VALUE, 0},
8827 {":file", IMAGE_STRING_VALUE, 0},
8828 {":ascent", IMAGE_ASCENT_VALUE, 0},
8829 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8830 {":relief", IMAGE_INTEGER_VALUE, 0},
8831 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8832 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8833 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
8836 /* Structure describing the image type `gif'. */
8838 static struct image_type gif_type =
8840 &Qgif,
8841 gif_image_p,
8842 gif_load,
8843 x_clear_image,
8844 NULL
8848 /* Return non-zero if OBJECT is a valid GIF image specification. */
8850 static int
8851 gif_image_p (object)
8852 Lisp_Object object;
8854 struct image_keyword fmt[GIF_LAST];
8855 bcopy (gif_format, fmt, sizeof fmt);
8857 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8858 return 0;
8860 /* Must specify either the :data or :file keyword. */
8861 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8865 /* Reading a GIF image from memory
8866 Based on the PNG memory stuff to a certain extent. */
8868 typedef struct
8870 unsigned char *bytes;
8871 size_t len;
8872 int index;
8874 gif_memory_source;
8877 /* Make the current memory source available to gif_read_from_memory.
8878 It's done this way because not all versions of libungif support
8879 a UserData field in the GifFileType structure. */
8880 static gif_memory_source *current_gif_memory_src;
8882 static int
8883 gif_read_from_memory (file, buf, len)
8884 GifFileType *file;
8885 GifByteType *buf;
8886 int len;
8888 gif_memory_source *src = current_gif_memory_src;
8890 if (len > src->len - src->index)
8891 return -1;
8893 bcopy (src->bytes + src->index, buf, len);
8894 src->index += len;
8895 return len;
8899 /* Load GIF image IMG for use on frame F. Value is non-zero if
8900 successful. */
8902 static int
8903 gif_load (f, img)
8904 struct frame *f;
8905 struct image *img;
8907 Lisp_Object file, specified_file;
8908 Lisp_Object specified_data;
8909 int rc, width, height, x, y, i;
8910 XImage *ximg;
8911 ColorMapObject *gif_color_map;
8912 unsigned long pixel_colors[256];
8913 GifFileType *gif;
8914 struct gcpro gcpro1;
8915 Lisp_Object image;
8916 int ino, image_left, image_top, image_width, image_height;
8917 gif_memory_source memsrc;
8918 unsigned char *raster;
8920 specified_file = image_spec_value (img->spec, QCfile, NULL);
8921 specified_data = image_spec_value (img->spec, QCdata, NULL);
8922 file = Qnil;
8923 GCPRO1 (file);
8925 if (NILP (specified_data))
8927 file = x_find_image_file (specified_file);
8928 if (!STRINGP (file))
8930 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8931 UNGCPRO;
8932 return 0;
8935 /* Open the GIF file. */
8936 gif = DGifOpenFileName (XSTRING (file)->data);
8937 if (gif == NULL)
8939 image_error ("Cannot open `%s'", file, Qnil);
8940 UNGCPRO;
8941 return 0;
8944 else
8946 /* Read from memory! */
8947 current_gif_memory_src = &memsrc;
8948 memsrc.bytes = XSTRING (specified_data)->data;
8949 memsrc.len = STRING_BYTES (XSTRING (specified_data));
8950 memsrc.index = 0;
8952 gif = DGifOpen(&memsrc, gif_read_from_memory);
8953 if (!gif)
8955 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8956 UNGCPRO;
8957 return 0;
8961 /* Read entire contents. */
8962 rc = DGifSlurp (gif);
8963 if (rc == GIF_ERROR)
8965 image_error ("Error reading `%s'", img->spec, Qnil);
8966 DGifCloseFile (gif);
8967 UNGCPRO;
8968 return 0;
8971 image = image_spec_value (img->spec, QCindex, NULL);
8972 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8973 if (ino >= gif->ImageCount)
8975 image_error ("Invalid image number `%s' in image `%s'",
8976 image, img->spec);
8977 DGifCloseFile (gif);
8978 UNGCPRO;
8979 return 0;
8982 width = img->width = gif->SWidth;
8983 height = img->height = gif->SHeight;
8985 BLOCK_INPUT;
8987 /* Create the X image and pixmap. */
8988 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8990 UNBLOCK_INPUT;
8991 DGifCloseFile (gif);
8992 UNGCPRO;
8993 return 0;
8996 /* Allocate colors. */
8997 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8998 if (!gif_color_map)
8999 gif_color_map = gif->SColorMap;
9000 init_color_table ();
9001 bzero (pixel_colors, sizeof pixel_colors);
9003 for (i = 0; i < gif_color_map->ColorCount; ++i)
9005 int r = gif_color_map->Colors[i].Red << 8;
9006 int g = gif_color_map->Colors[i].Green << 8;
9007 int b = gif_color_map->Colors[i].Blue << 8;
9008 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9011 img->colors = colors_in_color_table (&img->ncolors);
9012 free_color_table ();
9014 /* Clear the part of the screen image that are not covered by
9015 the image from the GIF file. Full animated GIF support
9016 requires more than can be done here (see the gif89 spec,
9017 disposal methods). Let's simply assume that the part
9018 not covered by a sub-image is in the frame's background color. */
9019 image_top = gif->SavedImages[ino].ImageDesc.Top;
9020 image_left = gif->SavedImages[ino].ImageDesc.Left;
9021 image_width = gif->SavedImages[ino].ImageDesc.Width;
9022 image_height = gif->SavedImages[ino].ImageDesc.Height;
9024 for (y = 0; y < image_top; ++y)
9025 for (x = 0; x < width; ++x)
9026 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9028 for (y = image_top + image_height; y < height; ++y)
9029 for (x = 0; x < width; ++x)
9030 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9032 for (y = image_top; y < image_top + image_height; ++y)
9034 for (x = 0; x < image_left; ++x)
9035 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9036 for (x = image_left + image_width; x < width; ++x)
9037 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9040 /* Read the GIF image into the X image. We use a local variable
9041 `raster' here because RasterBits below is a char *, and invites
9042 problems with bytes >= 0x80. */
9043 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9045 if (gif->SavedImages[ino].ImageDesc.Interlace)
9047 static int interlace_start[] = {0, 4, 2, 1};
9048 static int interlace_increment[] = {8, 8, 4, 2};
9049 int pass, inc;
9050 int row = interlace_start[0];
9052 pass = 0;
9054 for (y = 0; y < image_height; y++)
9056 if (row >= image_height)
9058 row = interlace_start[++pass];
9059 while (row >= image_height)
9060 row = interlace_start[++pass];
9063 for (x = 0; x < image_width; x++)
9065 int i = raster[(y * image_width) + x];
9066 XPutPixel (ximg, x + image_left, row + image_top,
9067 pixel_colors[i]);
9070 row += interlace_increment[pass];
9073 else
9075 for (y = 0; y < image_height; ++y)
9076 for (x = 0; x < image_width; ++x)
9078 int i = raster[y * image_width + x];
9079 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9083 DGifCloseFile (gif);
9085 /* Put the image into the pixmap, then free the X image and its buffer. */
9086 x_put_x_image (f, ximg, img->pixmap, width, height);
9087 x_destroy_x_image (ximg);
9088 UNBLOCK_INPUT;
9090 UNGCPRO;
9091 return 1;
9094 #endif /* HAVE_GIF != 0 */
9098 /***********************************************************************
9099 Ghostscript
9100 ***********************************************************************/
9102 static int gs_image_p P_ ((Lisp_Object object));
9103 static int gs_load P_ ((struct frame *f, struct image *img));
9104 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9106 /* The symbol `postscript' identifying images of this type. */
9108 Lisp_Object Qpostscript;
9110 /* Keyword symbols. */
9112 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9114 /* Indices of image specification fields in gs_format, below. */
9116 enum gs_keyword_index
9118 GS_TYPE,
9119 GS_PT_WIDTH,
9120 GS_PT_HEIGHT,
9121 GS_FILE,
9122 GS_LOADER,
9123 GS_BOUNDING_BOX,
9124 GS_ASCENT,
9125 GS_MARGIN,
9126 GS_RELIEF,
9127 GS_ALGORITHM,
9128 GS_HEURISTIC_MASK,
9129 GS_LAST
9132 /* Vector of image_keyword structures describing the format
9133 of valid user-defined image specifications. */
9135 static struct image_keyword gs_format[GS_LAST] =
9137 {":type", IMAGE_SYMBOL_VALUE, 1},
9138 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9139 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9140 {":file", IMAGE_STRING_VALUE, 1},
9141 {":loader", IMAGE_FUNCTION_VALUE, 0},
9142 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9143 {":ascent", IMAGE_ASCENT_VALUE, 0},
9144 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9145 {":relief", IMAGE_INTEGER_VALUE, 0},
9146 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9147 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9150 /* Structure describing the image type `ghostscript'. */
9152 static struct image_type gs_type =
9154 &Qpostscript,
9155 gs_image_p,
9156 gs_load,
9157 gs_clear_image,
9158 NULL
9162 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9164 static void
9165 gs_clear_image (f, img)
9166 struct frame *f;
9167 struct image *img;
9169 /* IMG->data.ptr_val may contain a recorded colormap. */
9170 xfree (img->data.ptr_val);
9171 x_clear_image (f, img);
9175 /* Return non-zero if OBJECT is a valid Ghostscript image
9176 specification. */
9178 static int
9179 gs_image_p (object)
9180 Lisp_Object object;
9182 struct image_keyword fmt[GS_LAST];
9183 Lisp_Object tem;
9184 int i;
9186 bcopy (gs_format, fmt, sizeof fmt);
9188 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9189 return 0;
9191 /* Bounding box must be a list or vector containing 4 integers. */
9192 tem = fmt[GS_BOUNDING_BOX].value;
9193 if (CONSP (tem))
9195 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9196 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9197 return 0;
9198 if (!NILP (tem))
9199 return 0;
9201 else if (VECTORP (tem))
9203 if (XVECTOR (tem)->size != 4)
9204 return 0;
9205 for (i = 0; i < 4; ++i)
9206 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9207 return 0;
9209 else
9210 return 0;
9212 return 1;
9216 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9217 if successful. */
9219 static int
9220 gs_load (f, img)
9221 struct frame *f;
9222 struct image *img;
9224 char buffer[100];
9225 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9226 struct gcpro gcpro1, gcpro2;
9227 Lisp_Object frame;
9228 double in_width, in_height;
9229 Lisp_Object pixel_colors = Qnil;
9231 /* Compute pixel size of pixmap needed from the given size in the
9232 image specification. Sizes in the specification are in pt. 1 pt
9233 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9234 info. */
9235 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9236 in_width = XFASTINT (pt_width) / 72.0;
9237 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9238 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9239 in_height = XFASTINT (pt_height) / 72.0;
9240 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9242 /* Create the pixmap. */
9243 BLOCK_INPUT;
9244 xassert (img->pixmap == 0);
9245 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9246 img->width, img->height,
9247 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9248 UNBLOCK_INPUT;
9250 if (!img->pixmap)
9252 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9253 return 0;
9256 /* Call the loader to fill the pixmap. It returns a process object
9257 if successful. We do not record_unwind_protect here because
9258 other places in redisplay like calling window scroll functions
9259 don't either. Let the Lisp loader use `unwind-protect' instead. */
9260 GCPRO2 (window_and_pixmap_id, pixel_colors);
9262 sprintf (buffer, "%lu %lu",
9263 (unsigned long) FRAME_X_WINDOW (f),
9264 (unsigned long) img->pixmap);
9265 window_and_pixmap_id = build_string (buffer);
9267 sprintf (buffer, "%lu %lu",
9268 FRAME_FOREGROUND_PIXEL (f),
9269 FRAME_BACKGROUND_PIXEL (f));
9270 pixel_colors = build_string (buffer);
9272 XSETFRAME (frame, f);
9273 loader = image_spec_value (img->spec, QCloader, NULL);
9274 if (NILP (loader))
9275 loader = intern ("gs-load-image");
9277 img->data.lisp_val = call6 (loader, frame, img->spec,
9278 make_number (img->width),
9279 make_number (img->height),
9280 window_and_pixmap_id,
9281 pixel_colors);
9282 UNGCPRO;
9283 return PROCESSP (img->data.lisp_val);
9287 /* Kill the Ghostscript process that was started to fill PIXMAP on
9288 frame F. Called from XTread_socket when receiving an event
9289 telling Emacs that Ghostscript has finished drawing. */
9291 void
9292 x_kill_gs_process (pixmap, f)
9293 Pixmap pixmap;
9294 struct frame *f;
9296 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9297 int class, i;
9298 struct image *img;
9300 /* Find the image containing PIXMAP. */
9301 for (i = 0; i < c->used; ++i)
9302 if (c->images[i]->pixmap == pixmap)
9303 break;
9305 /* Kill the GS process. We should have found PIXMAP in the image
9306 cache and its image should contain a process object. */
9307 xassert (i < c->used);
9308 img = c->images[i];
9309 xassert (PROCESSP (img->data.lisp_val));
9310 Fkill_process (img->data.lisp_val, Qnil);
9311 img->data.lisp_val = Qnil;
9313 /* On displays with a mutable colormap, figure out the colors
9314 allocated for the image by looking at the pixels of an XImage for
9315 img->pixmap. */
9316 class = FRAME_X_VISUAL (f)->class;
9317 if (class != StaticColor && class != StaticGray && class != TrueColor)
9319 XImage *ximg;
9321 BLOCK_INPUT;
9323 /* Try to get an XImage for img->pixmep. */
9324 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9325 0, 0, img->width, img->height, ~0, ZPixmap);
9326 if (ximg)
9328 int x, y;
9330 /* Initialize the color table. */
9331 init_color_table ();
9333 /* For each pixel of the image, look its color up in the
9334 color table. After having done so, the color table will
9335 contain an entry for each color used by the image. */
9336 for (y = 0; y < img->height; ++y)
9337 for (x = 0; x < img->width; ++x)
9339 unsigned long pixel = XGetPixel (ximg, x, y);
9340 lookup_pixel_color (f, pixel);
9343 /* Record colors in the image. Free color table and XImage. */
9344 img->colors = colors_in_color_table (&img->ncolors);
9345 free_color_table ();
9346 XDestroyImage (ximg);
9348 #if 0 /* This doesn't seem to be the case. If we free the colors
9349 here, we get a BadAccess later in x_clear_image when
9350 freeing the colors. */
9351 /* We have allocated colors once, but Ghostscript has also
9352 allocated colors on behalf of us. So, to get the
9353 reference counts right, free them once. */
9354 if (img->ncolors)
9355 x_free_colors (f, img->colors, img->ncolors);
9356 #endif
9358 else
9359 image_error ("Cannot get X image of `%s'; colors will not be freed",
9360 img->spec, Qnil);
9362 UNBLOCK_INPUT;
9368 /***********************************************************************
9369 Window properties
9370 ***********************************************************************/
9372 DEFUN ("x-change-window-property", Fx_change_window_property,
9373 Sx_change_window_property, 2, 3, 0,
9374 "Change window property PROP to VALUE on the X window of FRAME.\n\
9375 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9376 selected frame. Value is VALUE.")
9377 (prop, value, frame)
9378 Lisp_Object frame, prop, value;
9380 struct frame *f = check_x_frame (frame);
9381 Atom prop_atom;
9383 CHECK_STRING (prop, 1);
9384 CHECK_STRING (value, 2);
9386 BLOCK_INPUT;
9387 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9388 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9389 prop_atom, XA_STRING, 8, PropModeReplace,
9390 XSTRING (value)->data, XSTRING (value)->size);
9392 /* Make sure the property is set when we return. */
9393 XFlush (FRAME_X_DISPLAY (f));
9394 UNBLOCK_INPUT;
9396 return value;
9400 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9401 Sx_delete_window_property, 1, 2, 0,
9402 "Remove window property PROP from X window of FRAME.\n\
9403 FRAME nil or omitted means use the selected frame. Value is PROP.")
9404 (prop, frame)
9405 Lisp_Object prop, frame;
9407 struct frame *f = check_x_frame (frame);
9408 Atom prop_atom;
9410 CHECK_STRING (prop, 1);
9411 BLOCK_INPUT;
9412 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9413 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9415 /* Make sure the property is removed when we return. */
9416 XFlush (FRAME_X_DISPLAY (f));
9417 UNBLOCK_INPUT;
9419 return prop;
9423 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9424 1, 2, 0,
9425 "Value is the value of window property PROP on FRAME.\n\
9426 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9427 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9428 value.")
9429 (prop, frame)
9430 Lisp_Object prop, frame;
9432 struct frame *f = check_x_frame (frame);
9433 Atom prop_atom;
9434 int rc;
9435 Lisp_Object prop_value = Qnil;
9436 char *tmp_data = NULL;
9437 Atom actual_type;
9438 int actual_format;
9439 unsigned long actual_size, bytes_remaining;
9441 CHECK_STRING (prop, 1);
9442 BLOCK_INPUT;
9443 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9444 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9445 prop_atom, 0, 0, False, XA_STRING,
9446 &actual_type, &actual_format, &actual_size,
9447 &bytes_remaining, (unsigned char **) &tmp_data);
9448 if (rc == Success)
9450 int size = bytes_remaining;
9452 XFree (tmp_data);
9453 tmp_data = NULL;
9455 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9456 prop_atom, 0, bytes_remaining,
9457 False, XA_STRING,
9458 &actual_type, &actual_format,
9459 &actual_size, &bytes_remaining,
9460 (unsigned char **) &tmp_data);
9461 if (rc == Success)
9462 prop_value = make_string (tmp_data, size);
9464 XFree (tmp_data);
9467 UNBLOCK_INPUT;
9468 return prop_value;
9473 /***********************************************************************
9474 Busy cursor
9475 ***********************************************************************/
9477 /* If non-null, an asynchronous timer that, when it expires, displays
9478 a busy cursor on all frames. */
9480 static struct atimer *busy_cursor_atimer;
9482 /* Non-zero means a busy cursor is currently shown. */
9484 static int busy_cursor_shown_p;
9486 /* Number of seconds to wait before displaying a busy cursor. */
9488 static Lisp_Object Vbusy_cursor_delay;
9490 /* Default number of seconds to wait before displaying a busy
9491 cursor. */
9493 #define DEFAULT_BUSY_CURSOR_DELAY 1
9495 /* Function prototypes. */
9497 static void show_busy_cursor P_ ((struct atimer *));
9498 static void hide_busy_cursor P_ ((void));
9501 /* Cancel a currently active busy-cursor timer, and start a new one. */
9503 void
9504 start_busy_cursor ()
9506 EMACS_TIME delay;
9507 int secs, usecs = 0;
9509 cancel_busy_cursor ();
9511 if (INTEGERP (Vbusy_cursor_delay)
9512 && XINT (Vbusy_cursor_delay) > 0)
9513 secs = XFASTINT (Vbusy_cursor_delay);
9514 else if (FLOATP (Vbusy_cursor_delay)
9515 && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
9517 Lisp_Object tem;
9518 tem = Ftruncate (Vbusy_cursor_delay, Qnil);
9519 secs = XFASTINT (tem);
9520 usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
9522 else
9523 secs = DEFAULT_BUSY_CURSOR_DELAY;
9525 EMACS_SET_SECS_USECS (delay, secs, usecs);
9526 busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
9527 show_busy_cursor, NULL);
9531 /* Cancel the busy cursor timer if active, hide a busy cursor if
9532 shown. */
9534 void
9535 cancel_busy_cursor ()
9537 if (busy_cursor_atimer)
9539 cancel_atimer (busy_cursor_atimer);
9540 busy_cursor_atimer = NULL;
9543 if (busy_cursor_shown_p)
9544 hide_busy_cursor ();
9548 /* Timer function of busy_cursor_atimer. TIMER is equal to
9549 busy_cursor_atimer.
9551 Display a busy cursor on all frames by mapping the frames'
9552 busy_window. Set the busy_p flag in the frames' output_data.x
9553 structure to indicate that a busy cursor is shown on the
9554 frames. */
9556 static void
9557 show_busy_cursor (timer)
9558 struct atimer *timer;
9560 /* The timer implementation will cancel this timer automatically
9561 after this function has run. Set busy_cursor_atimer to null
9562 so that we know the timer doesn't have to be canceled. */
9563 busy_cursor_atimer = NULL;
9565 if (!busy_cursor_shown_p)
9567 Lisp_Object rest, frame;
9569 BLOCK_INPUT;
9571 FOR_EACH_FRAME (rest, frame)
9572 if (FRAME_X_P (XFRAME (frame)))
9574 struct frame *f = XFRAME (frame);
9576 f->output_data.x->busy_p = 1;
9578 if (!f->output_data.x->busy_window)
9580 unsigned long mask = CWCursor;
9581 XSetWindowAttributes attrs;
9583 attrs.cursor = f->output_data.x->busy_cursor;
9585 f->output_data.x->busy_window
9586 = XCreateWindow (FRAME_X_DISPLAY (f),
9587 FRAME_OUTER_WINDOW (f),
9588 0, 0, 32000, 32000, 0, 0,
9589 InputOnly,
9590 CopyFromParent,
9591 mask, &attrs);
9594 XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
9595 XFlush (FRAME_X_DISPLAY (f));
9598 busy_cursor_shown_p = 1;
9599 UNBLOCK_INPUT;
9604 /* Hide the busy cursor on all frames, if it is currently shown. */
9606 static void
9607 hide_busy_cursor ()
9609 if (busy_cursor_shown_p)
9611 Lisp_Object rest, frame;
9613 BLOCK_INPUT;
9614 FOR_EACH_FRAME (rest, frame)
9616 struct frame *f = XFRAME (frame);
9618 if (FRAME_X_P (f)
9619 /* Watch out for newly created frames. */
9620 && f->output_data.x->busy_window)
9622 XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
9623 /* Sync here because XTread_socket looks at the busy_p flag
9624 that is reset to zero below. */
9625 XSync (FRAME_X_DISPLAY (f), False);
9626 f->output_data.x->busy_p = 0;
9630 busy_cursor_shown_p = 0;
9631 UNBLOCK_INPUT;
9637 /***********************************************************************
9638 Tool tips
9639 ***********************************************************************/
9641 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
9642 Lisp_Object));
9644 /* The frame of a currently visible tooltip, or null. */
9646 struct frame *tip_frame;
9648 /* If non-nil, a timer started that hides the last tooltip when it
9649 fires. */
9651 Lisp_Object tip_timer;
9652 Window tip_window;
9654 /* Create a frame for a tooltip on the display described by DPYINFO.
9655 PARMS is a list of frame parameters. Value is the frame. */
9657 static Lisp_Object
9658 x_create_tip_frame (dpyinfo, parms)
9659 struct x_display_info *dpyinfo;
9660 Lisp_Object parms;
9662 struct frame *f;
9663 Lisp_Object frame, tem;
9664 Lisp_Object name;
9665 long window_prompting = 0;
9666 int width, height;
9667 int count = specpdl_ptr - specpdl;
9668 struct gcpro gcpro1, gcpro2, gcpro3;
9669 struct kboard *kb;
9671 check_x ();
9673 /* Use this general default value to start with until we know if
9674 this frame has a specified name. */
9675 Vx_resource_name = Vinvocation_name;
9677 #ifdef MULTI_KBOARD
9678 kb = dpyinfo->kboard;
9679 #else
9680 kb = &the_only_kboard;
9681 #endif
9683 /* Get the name of the frame to use for resource lookup. */
9684 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
9685 if (!STRINGP (name)
9686 && !EQ (name, Qunbound)
9687 && !NILP (name))
9688 error ("Invalid frame name--not a string or nil");
9689 Vx_resource_name = name;
9691 frame = Qnil;
9692 GCPRO3 (parms, name, frame);
9693 tip_frame = f = make_frame (1);
9694 XSETFRAME (frame, f);
9695 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9697 f->output_method = output_x_window;
9698 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
9699 bzero (f->output_data.x, sizeof (struct x_output));
9700 f->output_data.x->icon_bitmap = -1;
9701 f->output_data.x->fontset = -1;
9702 f->output_data.x->scroll_bar_foreground_pixel = -1;
9703 f->output_data.x->scroll_bar_background_pixel = -1;
9704 f->icon_name = Qnil;
9705 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
9706 #ifdef MULTI_KBOARD
9707 FRAME_KBOARD (f) = kb;
9708 #endif
9709 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9710 f->output_data.x->explicit_parent = 0;
9712 /* These colors will be set anyway later, but it's important
9713 to get the color reference counts right, so initialize them! */
9715 Lisp_Object black;
9716 struct gcpro gcpro1;
9718 black = build_string ("black");
9719 GCPRO1 (black);
9720 f->output_data.x->foreground_pixel
9721 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9722 f->output_data.x->background_pixel
9723 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9724 f->output_data.x->cursor_pixel
9725 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9726 f->output_data.x->cursor_foreground_pixel
9727 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9728 f->output_data.x->border_pixel
9729 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9730 f->output_data.x->mouse_pixel
9731 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9732 UNGCPRO;
9735 /* Set the name; the functions to which we pass f expect the name to
9736 be set. */
9737 if (EQ (name, Qunbound) || NILP (name))
9739 f->name = build_string (dpyinfo->x_id_name);
9740 f->explicit_name = 0;
9742 else
9744 f->name = name;
9745 f->explicit_name = 1;
9746 /* use the frame's title when getting resources for this frame. */
9747 specbind (Qx_resource_name, name);
9750 /* Extract the window parameters from the supplied values
9751 that are needed to determine window geometry. */
9753 Lisp_Object font;
9755 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
9757 BLOCK_INPUT;
9758 /* First, try whatever font the caller has specified. */
9759 if (STRINGP (font))
9761 tem = Fquery_fontset (font, Qnil);
9762 if (STRINGP (tem))
9763 font = x_new_fontset (f, XSTRING (tem)->data);
9764 else
9765 font = x_new_font (f, XSTRING (font)->data);
9768 /* Try out a font which we hope has bold and italic variations. */
9769 if (!STRINGP (font))
9770 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9771 if (!STRINGP (font))
9772 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9773 if (! STRINGP (font))
9774 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9775 if (! STRINGP (font))
9776 /* This was formerly the first thing tried, but it finds too many fonts
9777 and takes too long. */
9778 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9779 /* If those didn't work, look for something which will at least work. */
9780 if (! STRINGP (font))
9781 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9782 UNBLOCK_INPUT;
9783 if (! STRINGP (font))
9784 font = build_string ("fixed");
9786 x_default_parameter (f, parms, Qfont, font,
9787 "font", "Font", RES_TYPE_STRING);
9790 x_default_parameter (f, parms, Qborder_width, make_number (2),
9791 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9793 /* This defaults to 2 in order to match xterm. We recognize either
9794 internalBorderWidth or internalBorder (which is what xterm calls
9795 it). */
9796 if (NILP (Fassq (Qinternal_border_width, parms)))
9798 Lisp_Object value;
9800 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
9801 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9802 if (! EQ (value, Qunbound))
9803 parms = Fcons (Fcons (Qinternal_border_width, value),
9804 parms);
9807 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9808 "internalBorderWidth", "internalBorderWidth",
9809 RES_TYPE_NUMBER);
9811 /* Also do the stuff which must be set before the window exists. */
9812 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9813 "foreground", "Foreground", RES_TYPE_STRING);
9814 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9815 "background", "Background", RES_TYPE_STRING);
9816 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9817 "pointerColor", "Foreground", RES_TYPE_STRING);
9818 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9819 "cursorColor", "Foreground", RES_TYPE_STRING);
9820 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9821 "borderColor", "BorderColor", RES_TYPE_STRING);
9823 /* Init faces before x_default_parameter is called for scroll-bar
9824 parameters because that function calls x_set_scroll_bar_width,
9825 which calls change_frame_size, which calls Fset_window_buffer,
9826 which runs hooks, which call Fvertical_motion. At the end, we
9827 end up in init_iterator with a null face cache, which should not
9828 happen. */
9829 init_frame_faces (f);
9831 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9832 window_prompting = x_figure_window_size (f, parms);
9834 if (window_prompting & XNegative)
9836 if (window_prompting & YNegative)
9837 f->output_data.x->win_gravity = SouthEastGravity;
9838 else
9839 f->output_data.x->win_gravity = NorthEastGravity;
9841 else
9843 if (window_prompting & YNegative)
9844 f->output_data.x->win_gravity = SouthWestGravity;
9845 else
9846 f->output_data.x->win_gravity = NorthWestGravity;
9849 f->output_data.x->size_hint_flags = window_prompting;
9851 XSetWindowAttributes attrs;
9852 unsigned long mask;
9854 BLOCK_INPUT;
9855 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
9856 /* Window managers look at the override-redirect flag to determine
9857 whether or net to give windows a decoration (Xlib spec, chapter
9858 3.2.8). */
9859 attrs.override_redirect = True;
9860 attrs.save_under = True;
9861 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9862 /* Arrange for getting MapNotify and UnmapNotify events. */
9863 attrs.event_mask = StructureNotifyMask;
9864 tip_window
9865 = FRAME_X_WINDOW (f)
9866 = XCreateWindow (FRAME_X_DISPLAY (f),
9867 FRAME_X_DISPLAY_INFO (f)->root_window,
9868 /* x, y, width, height */
9869 0, 0, 1, 1,
9870 /* Border. */
9872 CopyFromParent, InputOutput, CopyFromParent,
9873 mask, &attrs);
9874 UNBLOCK_INPUT;
9877 x_make_gc (f);
9879 x_default_parameter (f, parms, Qauto_raise, Qnil,
9880 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9881 x_default_parameter (f, parms, Qauto_lower, Qnil,
9882 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9883 x_default_parameter (f, parms, Qcursor_type, Qbox,
9884 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9886 /* Dimensions, especially f->height, must be done via change_frame_size.
9887 Change will not be effected unless different from the current
9888 f->height. */
9889 width = f->width;
9890 height = f->height;
9891 f->height = 0;
9892 SET_FRAME_WIDTH (f, 0);
9893 change_frame_size (f, height, width, 1, 0, 0);
9895 f->no_split = 1;
9897 UNGCPRO;
9899 /* It is now ok to make the frame official even if we get an error
9900 below. And the frame needs to be on Vframe_list or making it
9901 visible won't work. */
9902 Vframe_list = Fcons (frame, Vframe_list);
9904 /* Now that the frame is official, it counts as a reference to
9905 its display. */
9906 FRAME_X_DISPLAY_INFO (f)->reference_count++;
9908 return unbind_to (count, frame);
9912 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
9913 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
9914 A tooltip window is a small X window displaying a string.\n\
9916 FRAME nil or omitted means use the selected frame.\n\
9918 PARMS is an optional list of frame parameters which can be\n\
9919 used to change the tooltip's appearance.\n\
9921 Automatically hide the tooltip after TIMEOUT seconds.\n\
9922 TIMEOUT nil means use the default timeout of 5 seconds.\n\
9924 If the list of frame parameters PARAMS contains a `left' parameters,\n\
9925 the tooltip is displayed at that x-position. Otherwise it is\n\
9926 displayed at the mouse position, with offset DX added (default is 5 if\n\
9927 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
9928 parameter is specified, it determines the y-position of the tooltip\n\
9929 window, otherwise it is displayed at the mouse position, with offset\n\
9930 DY added (default is -5).")
9931 (string, frame, parms, timeout, dx, dy)
9932 Lisp_Object string, frame, parms, timeout, dx, dy;
9934 struct frame *f;
9935 struct window *w;
9936 Window root, child;
9937 Lisp_Object buffer, top, left;
9938 struct buffer *old_buffer;
9939 struct text_pos pos;
9940 int i, width, height;
9941 int root_x, root_y, win_x, win_y;
9942 unsigned pmask;
9943 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9944 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9945 int count = specpdl_ptr - specpdl;
9947 specbind (Qinhibit_redisplay, Qt);
9949 GCPRO4 (string, parms, frame, timeout);
9951 CHECK_STRING (string, 0);
9952 f = check_x_frame (frame);
9953 if (NILP (timeout))
9954 timeout = make_number (5);
9955 else
9956 CHECK_NATNUM (timeout, 2);
9958 if (NILP (dx))
9959 dx = make_number (5);
9960 else
9961 CHECK_NUMBER (dx, 5);
9963 if (NILP (dy))
9964 dy = make_number (-5);
9965 else
9966 CHECK_NUMBER (dy, 6);
9968 /* Hide a previous tip, if any. */
9969 Fx_hide_tip ();
9971 /* Add default values to frame parameters. */
9972 if (NILP (Fassq (Qname, parms)))
9973 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
9974 if (NILP (Fassq (Qinternal_border_width, parms)))
9975 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
9976 if (NILP (Fassq (Qborder_width, parms)))
9977 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
9978 if (NILP (Fassq (Qborder_color, parms)))
9979 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
9980 if (NILP (Fassq (Qbackground_color, parms)))
9981 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
9982 parms);
9984 /* Create a frame for the tooltip, and record it in the global
9985 variable tip_frame. */
9986 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
9987 tip_frame = f = XFRAME (frame);
9989 /* Set up the frame's root window. Currently we use a size of 80
9990 columns x 40 lines. If someone wants to show a larger tip, he
9991 will loose. I don't think this is a realistic case. */
9992 w = XWINDOW (FRAME_ROOT_WINDOW (f));
9993 w->left = w->top = make_number (0);
9994 w->width = make_number (80);
9995 w->height = make_number (40);
9996 adjust_glyphs (f);
9997 w->pseudo_window_p = 1;
9999 /* Display the tooltip text in a temporary buffer. */
10000 buffer = Fget_buffer_create (build_string (" *tip*"));
10001 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10002 old_buffer = current_buffer;
10003 set_buffer_internal_1 (XBUFFER (buffer));
10004 Ferase_buffer ();
10005 Finsert (1, &string);
10006 clear_glyph_matrix (w->desired_matrix);
10007 clear_glyph_matrix (w->current_matrix);
10008 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
10009 try_window (FRAME_ROOT_WINDOW (f), pos);
10011 /* Compute width and height of the tooltip. */
10012 width = height = 0;
10013 for (i = 0; i < w->desired_matrix->nrows; ++i)
10015 struct glyph_row *row = &w->desired_matrix->rows[i];
10016 struct glyph *last;
10017 int row_width;
10019 /* Stop at the first empty row at the end. */
10020 if (!row->enabled_p || !row->displays_text_p)
10021 break;
10023 /* Let the row go over the full width of the frame. */
10024 row->full_width_p = 1;
10026 /* There's a glyph at the end of rows that is used to place
10027 the cursor there. Don't include the width of this glyph. */
10028 if (row->used[TEXT_AREA])
10030 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
10031 row_width = row->pixel_width - last->pixel_width;
10033 else
10034 row_width = row->pixel_width;
10036 height += row->height;
10037 width = max (width, row_width);
10040 /* Add the frame's internal border to the width and height the X
10041 window should have. */
10042 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10043 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10045 /* User-specified position? */
10046 left = Fcdr (Fassq (Qleft, parms));
10047 top = Fcdr (Fassq (Qtop, parms));
10049 /* Move the tooltip window where the mouse pointer is. Resize and
10050 show it. */
10051 BLOCK_INPUT;
10052 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10053 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
10054 UNBLOCK_INPUT;
10056 root_x += XINT (dx);
10057 root_y += XINT (dy);
10059 if (INTEGERP (left))
10060 root_x = XINT (left);
10061 if (INTEGERP (top))
10062 root_y = XINT (top);
10064 BLOCK_INPUT;
10065 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10066 root_x, root_y - height, width, height);
10067 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10068 UNBLOCK_INPUT;
10070 /* Draw into the window. */
10071 w->must_be_updated_p = 1;
10072 update_single_window (w, 1);
10074 /* Restore original current buffer. */
10075 set_buffer_internal_1 (old_buffer);
10076 windows_or_buffers_changed = old_windows_or_buffers_changed;
10078 /* Let the tip disappear after timeout seconds. */
10079 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
10080 intern ("x-hide-tip"));
10082 UNGCPRO;
10083 return unbind_to (count, Qnil);
10087 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
10088 "Hide the current tooltip window, if there is any.\n\
10089 Value is t is tooltip was open, nil otherwise.")
10092 int count = specpdl_ptr - specpdl;
10093 int deleted_p = 0;
10095 specbind (Qinhibit_redisplay, Qt);
10097 if (!NILP (tip_timer))
10099 call1 (intern ("cancel-timer"), tip_timer);
10100 tip_timer = Qnil;
10103 if (tip_frame)
10105 Lisp_Object frame;
10107 XSETFRAME (frame, tip_frame);
10108 Fdelete_frame (frame, Qt);
10109 tip_frame = NULL;
10110 deleted_p = 1;
10113 return unbind_to (count, deleted_p ? Qt : Qnil);
10118 /***********************************************************************
10119 File selection dialog
10120 ***********************************************************************/
10122 #ifdef USE_MOTIF
10124 /* Callback for "OK" and "Cancel" on file selection dialog. */
10126 static void
10127 file_dialog_cb (widget, client_data, call_data)
10128 Widget widget;
10129 XtPointer call_data, client_data;
10131 int *result = (int *) client_data;
10132 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
10133 *result = cb->reason;
10137 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10138 "Read file name, prompting with PROMPT in directory DIR.\n\
10139 Use a file selection dialog.\n\
10140 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10141 specified. Don't let the user enter a file name in the file\n\
10142 selection dialog's entry field, if MUSTMATCH is non-nil.")
10143 (prompt, dir, default_filename, mustmatch)
10144 Lisp_Object prompt, dir, default_filename, mustmatch;
10146 int result;
10147 struct frame *f = SELECTED_FRAME ();
10148 Lisp_Object file = Qnil;
10149 Widget dialog, text, list, help;
10150 Arg al[10];
10151 int ac = 0;
10152 extern XtAppContext Xt_app_con;
10153 char *title;
10154 XmString dir_xmstring, pattern_xmstring;
10155 int popup_activated_flag;
10156 int count = specpdl_ptr - specpdl;
10157 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10159 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10160 CHECK_STRING (prompt, 0);
10161 CHECK_STRING (dir, 1);
10163 /* Prevent redisplay. */
10164 specbind (Qinhibit_redisplay, Qt);
10166 BLOCK_INPUT;
10168 /* Create the dialog with PROMPT as title, using DIR as initial
10169 directory and using "*" as pattern. */
10170 dir = Fexpand_file_name (dir, Qnil);
10171 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
10172 pattern_xmstring = XmStringCreateLocalized ("*");
10174 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
10175 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
10176 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
10177 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
10178 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
10179 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
10180 "fsb", al, ac);
10181 XmStringFree (dir_xmstring);
10182 XmStringFree (pattern_xmstring);
10184 /* Add callbacks for OK and Cancel. */
10185 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
10186 (XtPointer) &result);
10187 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
10188 (XtPointer) &result);
10190 /* Disable the help button since we can't display help. */
10191 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
10192 XtSetSensitive (help, False);
10194 /* Mark OK button as default. */
10195 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
10196 XmNshowAsDefault, True, NULL);
10198 /* If MUSTMATCH is non-nil, disable the file entry field of the
10199 dialog, so that the user must select a file from the files list
10200 box. We can't remove it because we wouldn't have a way to get at
10201 the result file name, then. */
10202 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
10203 if (!NILP (mustmatch))
10205 Widget label;
10206 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
10207 XtSetSensitive (text, False);
10208 XtSetSensitive (label, False);
10211 /* Manage the dialog, so that list boxes get filled. */
10212 XtManageChild (dialog);
10214 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10215 must include the path for this to work. */
10216 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
10217 if (STRINGP (default_filename))
10219 XmString default_xmstring;
10220 int item_pos;
10222 default_xmstring
10223 = XmStringCreateLocalized (XSTRING (default_filename)->data);
10225 if (!XmListItemExists (list, default_xmstring))
10227 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10228 XmListAddItem (list, default_xmstring, 0);
10229 item_pos = 0;
10231 else
10232 item_pos = XmListItemPos (list, default_xmstring);
10233 XmStringFree (default_xmstring);
10235 /* Select the item and scroll it into view. */
10236 XmListSelectPos (list, item_pos, True);
10237 XmListSetPos (list, item_pos);
10240 #ifdef HAVE_MOTIF_2_1
10242 /* Process events until the user presses Cancel or OK. */
10243 result = 0;
10244 while (result == 0 || XtAppPending (Xt_app_con))
10245 XtAppProcessEvent (Xt_app_con, XtIMAll);
10247 #else /* not HAVE_MOTIF_2_1 */
10249 /* Process all events until the user presses Cancel or OK. */
10250 for (result = 0; result == 0;)
10252 XEvent event;
10253 Widget widget, parent;
10255 XtAppNextEvent (Xt_app_con, &event);
10257 /* See if the receiver of the event is one of the widgets of
10258 the file selection dialog. If so, dispatch it. If not,
10259 discard it. */
10260 widget = XtWindowToWidget (event.xany.display, event.xany.window);
10261 parent = widget;
10262 while (parent && parent != dialog)
10263 parent = XtParent (parent);
10265 if (parent == dialog
10266 || (event.type == Expose
10267 && !process_expose_from_menu (event)))
10268 XtDispatchEvent (&event);
10271 #endif /* not HAVE_MOTIF_2_1 */
10273 /* Get the result. */
10274 if (result == XmCR_OK)
10276 XmString text;
10277 String data;
10279 XtVaGetValues (dialog, XmNtextString, &text, NULL);
10280 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
10281 XmStringFree (text);
10282 file = build_string (data);
10283 XtFree (data);
10285 else
10286 file = Qnil;
10288 /* Clean up. */
10289 XtUnmanageChild (dialog);
10290 XtDestroyWidget (dialog);
10291 UNBLOCK_INPUT;
10292 UNGCPRO;
10294 /* Make "Cancel" equivalent to C-g. */
10295 if (NILP (file))
10296 Fsignal (Qquit, Qnil);
10298 return unbind_to (count, file);
10301 #endif /* USE_MOTIF */
10305 /***********************************************************************
10306 Initialization
10307 ***********************************************************************/
10309 void
10310 syms_of_xfns ()
10312 /* This is zero if not using X windows. */
10313 x_in_use = 0;
10315 /* The section below is built by the lisp expression at the top of the file,
10316 just above where these variables are declared. */
10317 /*&&& init symbols here &&&*/
10318 Qauto_raise = intern ("auto-raise");
10319 staticpro (&Qauto_raise);
10320 Qauto_lower = intern ("auto-lower");
10321 staticpro (&Qauto_lower);
10322 Qbar = intern ("bar");
10323 staticpro (&Qbar);
10324 Qborder_color = intern ("border-color");
10325 staticpro (&Qborder_color);
10326 Qborder_width = intern ("border-width");
10327 staticpro (&Qborder_width);
10328 Qbox = intern ("box");
10329 staticpro (&Qbox);
10330 Qcursor_color = intern ("cursor-color");
10331 staticpro (&Qcursor_color);
10332 Qcursor_type = intern ("cursor-type");
10333 staticpro (&Qcursor_type);
10334 Qgeometry = intern ("geometry");
10335 staticpro (&Qgeometry);
10336 Qicon_left = intern ("icon-left");
10337 staticpro (&Qicon_left);
10338 Qicon_top = intern ("icon-top");
10339 staticpro (&Qicon_top);
10340 Qicon_type = intern ("icon-type");
10341 staticpro (&Qicon_type);
10342 Qicon_name = intern ("icon-name");
10343 staticpro (&Qicon_name);
10344 Qinternal_border_width = intern ("internal-border-width");
10345 staticpro (&Qinternal_border_width);
10346 Qleft = intern ("left");
10347 staticpro (&Qleft);
10348 Qright = intern ("right");
10349 staticpro (&Qright);
10350 Qmouse_color = intern ("mouse-color");
10351 staticpro (&Qmouse_color);
10352 Qnone = intern ("none");
10353 staticpro (&Qnone);
10354 Qparent_id = intern ("parent-id");
10355 staticpro (&Qparent_id);
10356 Qscroll_bar_width = intern ("scroll-bar-width");
10357 staticpro (&Qscroll_bar_width);
10358 Qsuppress_icon = intern ("suppress-icon");
10359 staticpro (&Qsuppress_icon);
10360 Qundefined_color = intern ("undefined-color");
10361 staticpro (&Qundefined_color);
10362 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
10363 staticpro (&Qvertical_scroll_bars);
10364 Qvisibility = intern ("visibility");
10365 staticpro (&Qvisibility);
10366 Qwindow_id = intern ("window-id");
10367 staticpro (&Qwindow_id);
10368 Qouter_window_id = intern ("outer-window-id");
10369 staticpro (&Qouter_window_id);
10370 Qx_frame_parameter = intern ("x-frame-parameter");
10371 staticpro (&Qx_frame_parameter);
10372 Qx_resource_name = intern ("x-resource-name");
10373 staticpro (&Qx_resource_name);
10374 Quser_position = intern ("user-position");
10375 staticpro (&Quser_position);
10376 Quser_size = intern ("user-size");
10377 staticpro (&Quser_size);
10378 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
10379 staticpro (&Qscroll_bar_foreground);
10380 Qscroll_bar_background = intern ("scroll-bar-background");
10381 staticpro (&Qscroll_bar_background);
10382 Qscreen_gamma = intern ("screen-gamma");
10383 staticpro (&Qscreen_gamma);
10384 Qline_spacing = intern ("line-spacing");
10385 staticpro (&Qline_spacing);
10386 Qcenter = intern ("center");
10387 staticpro (&Qcenter);
10388 Qcompound_text = intern ("compound-text");
10389 staticpro (&Qcompound_text);
10390 /* This is the end of symbol initialization. */
10392 /* Text property `display' should be nonsticky by default. */
10393 Vtext_property_default_nonsticky
10394 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10397 Qlaplace = intern ("laplace");
10398 staticpro (&Qlaplace);
10400 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10401 staticpro (&Qface_set_after_frame_default);
10403 Fput (Qundefined_color, Qerror_conditions,
10404 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10405 Fput (Qundefined_color, Qerror_message,
10406 build_string ("Undefined color"));
10408 init_x_parm_symbols ();
10410 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10411 "List of directories to search for bitmap files for X.");
10412 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
10414 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10415 "The shape of the pointer when over text.\n\
10416 Changing the value does not affect existing frames\n\
10417 unless you set the mouse color.");
10418 Vx_pointer_shape = Qnil;
10420 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
10421 "The name Emacs uses to look up X resources.\n\
10422 `x-get-resource' uses this as the first component of the instance name\n\
10423 when requesting resource values.\n\
10424 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10425 was invoked, or to the value specified with the `-name' or `-rn'\n\
10426 switches, if present.\n\
10428 It may be useful to bind this variable locally around a call\n\
10429 to `x-get-resource'. See also the variable `x-resource-class'.");
10430 Vx_resource_name = Qnil;
10432 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
10433 "The class Emacs uses to look up X resources.\n\
10434 `x-get-resource' uses this as the first component of the instance class\n\
10435 when requesting resource values.\n\
10436 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10438 Setting this variable permanently is not a reasonable thing to do,\n\
10439 but binding this variable locally around a call to `x-get-resource'\n\
10440 is a reasonable practice. See also the variable `x-resource-name'.");
10441 Vx_resource_class = build_string (EMACS_CLASS);
10443 #if 0 /* This doesn't really do anything. */
10444 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
10445 "The shape of the pointer when not over text.\n\
10446 This variable takes effect when you create a new frame\n\
10447 or when you set the mouse color.");
10448 #endif
10449 Vx_nontext_pointer_shape = Qnil;
10451 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
10452 "The shape of the pointer when Emacs is busy.\n\
10453 This variable takes effect when you create a new frame\n\
10454 or when you set the mouse color.");
10455 Vx_busy_pointer_shape = Qnil;
10457 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
10458 "Non-zero means Emacs displays a busy cursor on window systems.");
10459 display_busy_cursor_p = 1;
10461 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
10462 "*Seconds to wait before displaying a busy-cursor.\n\
10463 Value must be an integer or float.");
10464 Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
10466 #if 0 /* This doesn't really do anything. */
10467 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
10468 "The shape of the pointer when over the mode line.\n\
10469 This variable takes effect when you create a new frame\n\
10470 or when you set the mouse color.");
10471 #endif
10472 Vx_mode_pointer_shape = Qnil;
10474 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10475 &Vx_sensitive_text_pointer_shape,
10476 "The shape of the pointer when over mouse-sensitive text.\n\
10477 This variable takes effect when you create a new frame\n\
10478 or when you set the mouse color.");
10479 Vx_sensitive_text_pointer_shape = Qnil;
10481 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10482 "A string indicating the foreground color of the cursor box.");
10483 Vx_cursor_fore_pixel = Qnil;
10485 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10486 "Non-nil if no X window manager is in use.\n\
10487 Emacs doesn't try to figure this out; this is always nil\n\
10488 unless you set it to something else.");
10489 /* We don't have any way to find this out, so set it to nil
10490 and maybe the user would like to set it to t. */
10491 Vx_no_window_manager = Qnil;
10493 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10494 &Vx_pixel_size_width_font_regexp,
10495 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10497 Since Emacs gets width of a font matching with this regexp from\n\
10498 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10499 such a font. This is especially effective for such large fonts as\n\
10500 Chinese, Japanese, and Korean.");
10501 Vx_pixel_size_width_font_regexp = Qnil;
10503 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10504 "Time after which cached images are removed from the cache.\n\
10505 When an image has not been displayed this many seconds, remove it\n\
10506 from the image cache. Value must be an integer or nil with nil\n\
10507 meaning don't clear the cache.");
10508 Vimage_cache_eviction_delay = make_number (30 * 60);
10510 #ifdef USE_X_TOOLKIT
10511 Fprovide (intern ("x-toolkit"));
10512 #endif
10513 #ifdef USE_MOTIF
10514 Fprovide (intern ("motif"));
10515 #endif
10517 defsubr (&Sx_get_resource);
10519 /* X window properties. */
10520 defsubr (&Sx_change_window_property);
10521 defsubr (&Sx_delete_window_property);
10522 defsubr (&Sx_window_property);
10524 defsubr (&Sxw_display_color_p);
10525 defsubr (&Sx_display_grayscale_p);
10526 defsubr (&Sxw_color_defined_p);
10527 defsubr (&Sxw_color_values);
10528 defsubr (&Sx_server_max_request_size);
10529 defsubr (&Sx_server_vendor);
10530 defsubr (&Sx_server_version);
10531 defsubr (&Sx_display_pixel_width);
10532 defsubr (&Sx_display_pixel_height);
10533 defsubr (&Sx_display_mm_width);
10534 defsubr (&Sx_display_mm_height);
10535 defsubr (&Sx_display_screens);
10536 defsubr (&Sx_display_planes);
10537 defsubr (&Sx_display_color_cells);
10538 defsubr (&Sx_display_visual_class);
10539 defsubr (&Sx_display_backing_store);
10540 defsubr (&Sx_display_save_under);
10541 defsubr (&Sx_parse_geometry);
10542 defsubr (&Sx_create_frame);
10543 defsubr (&Sx_open_connection);
10544 defsubr (&Sx_close_connection);
10545 defsubr (&Sx_display_list);
10546 defsubr (&Sx_synchronize);
10547 defsubr (&Sx_focus_frame);
10549 /* Setting callback functions for fontset handler. */
10550 get_font_info_func = x_get_font_info;
10552 #if 0 /* This function pointer doesn't seem to be used anywhere.
10553 And the pointer assigned has the wrong type, anyway. */
10554 list_fonts_func = x_list_fonts;
10555 #endif
10557 load_font_func = x_load_font;
10558 find_ccl_program_func = x_find_ccl_program;
10559 query_font_func = x_query_font;
10560 set_frame_fontset_func = x_set_font;
10561 check_window_system_func = check_x;
10563 /* Images. */
10564 Qxbm = intern ("xbm");
10565 staticpro (&Qxbm);
10566 QCtype = intern (":type");
10567 staticpro (&QCtype);
10568 QCalgorithm = intern (":algorithm");
10569 staticpro (&QCalgorithm);
10570 QCheuristic_mask = intern (":heuristic-mask");
10571 staticpro (&QCheuristic_mask);
10572 QCcolor_symbols = intern (":color-symbols");
10573 staticpro (&QCcolor_symbols);
10574 QCascent = intern (":ascent");
10575 staticpro (&QCascent);
10576 QCmargin = intern (":margin");
10577 staticpro (&QCmargin);
10578 QCrelief = intern (":relief");
10579 staticpro (&QCrelief);
10580 Qpostscript = intern ("postscript");
10581 staticpro (&Qpostscript);
10582 QCloader = intern (":loader");
10583 staticpro (&QCloader);
10584 QCbounding_box = intern (":bounding-box");
10585 staticpro (&QCbounding_box);
10586 QCpt_width = intern (":pt-width");
10587 staticpro (&QCpt_width);
10588 QCpt_height = intern (":pt-height");
10589 staticpro (&QCpt_height);
10590 QCindex = intern (":index");
10591 staticpro (&QCindex);
10592 Qpbm = intern ("pbm");
10593 staticpro (&Qpbm);
10595 #if HAVE_XPM
10596 Qxpm = intern ("xpm");
10597 staticpro (&Qxpm);
10598 #endif
10600 #if HAVE_JPEG
10601 Qjpeg = intern ("jpeg");
10602 staticpro (&Qjpeg);
10603 #endif
10605 #if HAVE_TIFF
10606 Qtiff = intern ("tiff");
10607 staticpro (&Qtiff);
10608 #endif
10610 #if HAVE_GIF
10611 Qgif = intern ("gif");
10612 staticpro (&Qgif);
10613 #endif
10615 #if HAVE_PNG
10616 Qpng = intern ("png");
10617 staticpro (&Qpng);
10618 #endif
10620 defsubr (&Sclear_image_cache);
10621 defsubr (&Simage_size);
10623 busy_cursor_atimer = NULL;
10624 busy_cursor_shown_p = 0;
10626 defsubr (&Sx_show_tip);
10627 defsubr (&Sx_hide_tip);
10628 staticpro (&tip_timer);
10629 tip_timer = Qnil;
10631 #ifdef USE_MOTIF
10632 defsubr (&Sx_file_dialog);
10633 #endif
10637 void
10638 init_xfns ()
10640 image_types = NULL;
10641 Vimage_types = Qnil;
10643 define_image_type (&xbm_type);
10644 define_image_type (&gs_type);
10645 define_image_type (&pbm_type);
10647 #if HAVE_XPM
10648 define_image_type (&xpm_type);
10649 #endif
10651 #if HAVE_JPEG
10652 define_image_type (&jpeg_type);
10653 #endif
10655 #if HAVE_TIFF
10656 define_image_type (&tiff_type);
10657 #endif
10659 #if HAVE_GIF
10660 define_image_type (&gif_type);
10661 #endif
10663 #if HAVE_PNG
10664 define_image_type (&png_type);
10665 #endif
10668 #endif /* HAVE_X_WINDOWS */