(fill-individual-paragraphs): Calculate new
[emacs.git] / src / xfns.c
blob7b3f7f2053585819e83b2a3f7aa8273728b97842
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Image support (XBM, XPM, PBM, JPEG, TIFF, GIF, PNG, GS). tooltips,
23 toolbars, busy-cursor, file selection dialog added by Gerd
24 Moellmann <gerd@gnu.org>. */
26 /* Completely rewritten by Richard Stallman. */
28 /* Rewritten for X11 by Joseph Arceneaux */
30 #include <signal.h>
31 #include <config.h>
32 #include <stdio.h>
34 /* This makes the fields of a Display accessible, in Xlib header files. */
36 #define XLIB_ILLEGAL_ACCESS
38 #include "lisp.h"
39 #include "xterm.h"
40 #include "frame.h"
41 #include "window.h"
42 #include "buffer.h"
43 #include "dispextern.h"
44 #include "keyboard.h"
45 #include "blockinput.h"
46 #include <epaths.h>
47 #include "charset.h"
48 #include "fontset.h"
49 #include "systime.h"
50 #include "termhooks.h"
52 #ifdef HAVE_X_WINDOWS
53 extern void abort ();
55 /* On some systems, the character-composition stuff is broken in X11R5. */
57 #if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
58 #ifdef X11R5_INHIBIT_I18N
59 #define X_I18N_INHIBITED
60 #endif
61 #endif
63 #ifndef VMS
64 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
65 #include "bitmaps/gray.xbm"
66 #else
67 #include <X11/bitmaps/gray>
68 #endif
69 #else
70 #include "[.bitmaps]gray.xbm"
71 #endif
73 #ifdef USE_X_TOOLKIT
74 #include <X11/Shell.h>
76 #ifndef USE_MOTIF
77 #include <X11/Xaw/Paned.h>
78 #include <X11/Xaw/Label.h>
79 #endif /* USE_MOTIF */
81 #ifdef USG
82 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
83 #include <X11/Xos.h>
84 #define USG
85 #else
86 #include <X11/Xos.h>
87 #endif
89 #include "widget.h"
91 #include "../lwlib/lwlib.h"
93 #ifdef USE_MOTIF
94 #include <Xm/Xm.h>
95 #include <Xm/DialogS.h>
96 #include <Xm/FileSB.h>
97 #endif
99 /* Do the EDITRES protocol if running X11R5
100 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
102 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
103 #define HACK_EDITRES
104 extern void _XEditResCheckMessages ();
105 #endif /* R5 + Athena */
107 /* Unique id counter for widgets created by the Lucid Widget Library. */
109 extern LWLIB_ID widget_id_tick;
111 #ifdef USE_LUCID
112 /* This is part of a kludge--see lwlib/xlwmenu.c. */
113 extern XFontStruct *xlwmenu_default_font;
114 #endif
116 extern void free_frame_menubar ();
118 #endif /* USE_X_TOOLKIT */
120 #define min(a,b) ((a) < (b) ? (a) : (b))
121 #define max(a,b) ((a) > (b) ? (a) : (b))
123 #ifdef HAVE_X11R4
124 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
125 #else
126 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
127 #endif
129 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
130 it, and including `bitmaps/gray' more than once is a problem when
131 config.h defines `static' as an empty replacement string. */
133 int gray_bitmap_width = gray_width;
134 int gray_bitmap_height = gray_height;
135 unsigned char *gray_bitmap_bits = gray_bits;
137 /* The name we're using in resource queries. Most often "emacs". */
139 Lisp_Object Vx_resource_name;
141 /* The application class we're using in resource queries.
142 Normally "Emacs". */
144 Lisp_Object Vx_resource_class;
146 /* Non-zero means we're allowed to display a busy cursor. */
148 int display_busy_cursor_p;
150 /* The background and shape of the mouse pointer, and shape when not
151 over text or in the modeline. */
153 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
154 Lisp_Object Vx_busy_pointer_shape;
156 /* The shape when over mouse-sensitive text. */
158 Lisp_Object Vx_sensitive_text_pointer_shape;
160 /* Color of chars displayed in cursor box. */
162 Lisp_Object Vx_cursor_fore_pixel;
164 /* Nonzero if using X. */
166 static int x_in_use;
168 /* Non nil if no window manager is in use. */
170 Lisp_Object Vx_no_window_manager;
172 /* Search path for bitmap files. */
174 Lisp_Object Vx_bitmap_file_path;
176 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
178 Lisp_Object Vx_pixel_size_width_font_regexp;
180 /* Evaluate this expression to rebuild the section of syms_of_xfns
181 that initializes and staticpros the symbols declared below. Note
182 that Emacs 18 has a bug that keeps C-x C-e from being able to
183 evaluate this expression.
185 (progn
186 ;; Accumulate a list of the symbols we want to initialize from the
187 ;; declarations at the top of the file.
188 (goto-char (point-min))
189 (search-forward "/\*&&& symbols declared here &&&*\/\n")
190 (let (symbol-list)
191 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
192 (setq symbol-list
193 (cons (buffer-substring (match-beginning 1) (match-end 1))
194 symbol-list))
195 (forward-line 1))
196 (setq symbol-list (nreverse symbol-list))
197 ;; Delete the section of syms_of_... where we initialize the symbols.
198 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
199 (let ((start (point)))
200 (while (looking-at "^ Q")
201 (forward-line 2))
202 (kill-region start (point)))
203 ;; Write a new symbol initialization section.
204 (while symbol-list
205 (insert (format " %s = intern (\"" (car symbol-list)))
206 (let ((start (point)))
207 (insert (substring (car symbol-list) 1))
208 (subst-char-in-region start (point) ?_ ?-))
209 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
210 (setq symbol-list (cdr symbol-list)))))
214 /*&&& symbols declared here &&&*/
215 Lisp_Object Qauto_raise;
216 Lisp_Object Qauto_lower;
217 Lisp_Object Qbar;
218 Lisp_Object Qborder_color;
219 Lisp_Object Qborder_width;
220 Lisp_Object Qbox;
221 Lisp_Object Qcursor_color;
222 Lisp_Object Qcursor_type;
223 Lisp_Object Qgeometry;
224 Lisp_Object Qicon_left;
225 Lisp_Object Qicon_top;
226 Lisp_Object Qicon_type;
227 Lisp_Object Qicon_name;
228 Lisp_Object Qinternal_border_width;
229 Lisp_Object Qleft;
230 Lisp_Object Qright;
231 Lisp_Object Qmouse_color;
232 Lisp_Object Qnone;
233 Lisp_Object Qouter_window_id;
234 Lisp_Object Qparent_id;
235 Lisp_Object Qscroll_bar_width;
236 Lisp_Object Qsuppress_icon;
237 extern Lisp_Object Qtop;
238 Lisp_Object Qundefined_color;
239 Lisp_Object Qvertical_scroll_bars;
240 Lisp_Object Qvisibility;
241 Lisp_Object Qwindow_id;
242 Lisp_Object Qx_frame_parameter;
243 Lisp_Object Qx_resource_name;
244 Lisp_Object Quser_position;
245 Lisp_Object Quser_size;
246 Lisp_Object Qdisplay;
247 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
249 /* The below are defined in frame.c. */
251 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
252 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
253 extern Lisp_Object Qtoolbar_lines;
255 extern Lisp_Object Vwindow_system_version;
257 Lisp_Object Qface_set_after_frame_default;
260 /* Error if we are not connected to X. */
262 void
263 check_x ()
265 if (! x_in_use)
266 error ("X windows are not in use or not initialized");
269 /* Nonzero if we can use mouse menus.
270 You should not call this unless HAVE_MENUS is defined. */
273 have_menus_p ()
275 return x_in_use;
278 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
279 and checking validity for X. */
281 FRAME_PTR
282 check_x_frame (frame)
283 Lisp_Object frame;
285 FRAME_PTR f;
287 if (NILP (frame))
288 f = selected_frame;
289 else
291 CHECK_LIVE_FRAME (frame, 0);
292 f = XFRAME (frame);
294 if (! FRAME_X_P (f))
295 error ("Non-X frame used");
296 return f;
299 /* Let the user specify an X display with a frame.
300 nil stands for the selected frame--or, if that is not an X frame,
301 the first X display on the list. */
303 static struct x_display_info *
304 check_x_display_info (frame)
305 Lisp_Object frame;
307 if (NILP (frame))
309 if (FRAME_X_P (selected_frame)
310 && FRAME_LIVE_P (selected_frame))
311 return FRAME_X_DISPLAY_INFO (selected_frame);
312 else if (x_display_list != 0)
313 return x_display_list;
314 else
315 error ("X windows are not in use or not initialized");
317 else if (STRINGP (frame))
318 return x_display_info_for_name (frame);
319 else
321 FRAME_PTR f;
323 CHECK_LIVE_FRAME (frame, 0);
324 f = XFRAME (frame);
325 if (! FRAME_X_P (f))
326 error ("Non-X frame used");
327 return FRAME_X_DISPLAY_INFO (f);
332 /* Return the Emacs frame-object corresponding to an X window.
333 It could be the frame's main window or an icon window. */
335 /* This function can be called during GC, so use GC_xxx type test macros. */
337 struct frame *
338 x_window_to_frame (dpyinfo, wdesc)
339 struct x_display_info *dpyinfo;
340 int wdesc;
342 Lisp_Object tail, frame;
343 struct frame *f;
345 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
347 frame = XCONS (tail)->car;
348 if (!GC_FRAMEP (frame))
349 continue;
350 f = XFRAME (frame);
351 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
352 continue;
353 #ifdef USE_X_TOOLKIT
354 if ((f->output_data.x->edit_widget
355 && XtWindow (f->output_data.x->edit_widget) == wdesc)
356 /* A tooltip frame? */
357 || (!f->output_data.x->edit_widget
358 && FRAME_X_WINDOW (f) == wdesc)
359 || f->output_data.x->icon_desc == wdesc)
360 return f;
361 #else /* not USE_X_TOOLKIT */
362 if (FRAME_X_WINDOW (f) == wdesc
363 || f->output_data.x->icon_desc == wdesc)
364 return f;
365 #endif /* not USE_X_TOOLKIT */
367 return 0;
370 #ifdef USE_X_TOOLKIT
371 /* Like x_window_to_frame but also compares the window with the widget's
372 windows. */
374 struct frame *
375 x_any_window_to_frame (dpyinfo, wdesc)
376 struct x_display_info *dpyinfo;
377 int wdesc;
379 Lisp_Object tail, frame;
380 struct frame *f;
381 struct x_output *x;
383 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
385 frame = XCONS (tail)->car;
386 if (!GC_FRAMEP (frame))
387 continue;
388 f = XFRAME (frame);
389 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
390 continue;
391 x = f->output_data.x;
392 /* This frame matches if the window is any of its widgets. */
393 if (x->widget)
395 if (wdesc == XtWindow (x->widget)
396 || wdesc == XtWindow (x->column_widget)
397 || wdesc == XtWindow (x->edit_widget))
398 return f;
399 /* Match if the window is this frame's menubar. */
400 if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
401 return f;
403 else if (FRAME_X_WINDOW (f) == wdesc)
404 /* A tooltip frame. */
405 return f;
407 return 0;
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 = XCONS (tail)->cdr)
423 frame = XCONS (tail)->car;
424 if (!GC_FRAMEP (frame))
425 continue;
426 f = XFRAME (frame);
427 if (f->output_data.nothing == 1 || 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->widget)
433 if (wdesc == XtWindow (x->widget)
434 || wdesc == XtWindow (x->column_widget)
435 || wdesc == XtWindow (x->edit_widget))
436 return f;
438 else if (FRAME_X_WINDOW (f) == wdesc)
439 /* A tooltip frame. */
440 return f;
442 return 0;
445 /* Likewise, but consider only the menu bar widget. */
447 struct frame *
448 x_menubar_window_to_frame (dpyinfo, wdesc)
449 struct x_display_info *dpyinfo;
450 int wdesc;
452 Lisp_Object tail, frame;
453 struct frame *f;
454 struct x_output *x;
456 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
458 frame = XCONS (tail)->car;
459 if (!GC_FRAMEP (frame))
460 continue;
461 f = XFRAME (frame);
462 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
463 continue;
464 x = f->output_data.x;
465 /* Match if the window is this frame's menubar. */
466 if (x->menubar_widget
467 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
468 return f;
470 return 0;
473 /* Return the frame whose principal (outermost) window is WDESC.
474 If WDESC is some other (smaller) window, we return 0. */
476 struct frame *
477 x_top_window_to_frame (dpyinfo, wdesc)
478 struct x_display_info *dpyinfo;
479 int wdesc;
481 Lisp_Object tail, frame;
482 struct frame *f;
483 struct x_output *x;
485 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
487 frame = XCONS (tail)->car;
488 if (!GC_FRAMEP (frame))
489 continue;
490 f = XFRAME (frame);
491 if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
492 continue;
493 x = f->output_data.x;
495 if (x->widget)
497 /* This frame matches if the window is its topmost widget. */
498 if (wdesc == XtWindow (x->widget))
499 return f;
500 #if 0 /* I don't know why it did this,
501 but it seems logically wrong,
502 and it causes trouble for MapNotify events. */
503 /* Match if the window is this frame's menubar. */
504 if (x->menubar_widget
505 && wdesc == XtWindow (x->menubar_widget))
506 return f;
507 #endif
509 else if (FRAME_X_WINDOW (f) == wdesc)
510 /* Tooltip frame. */
511 return f;
513 return 0;
515 #endif /* USE_X_TOOLKIT */
519 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
520 id, which is just an int that this section returns. Bitmaps are
521 reference counted so they can be shared among frames.
523 Bitmap indices are guaranteed to be > 0, so a negative number can
524 be used to indicate no bitmap.
526 If you use x_create_bitmap_from_data, then you must keep track of
527 the bitmaps yourself. That is, creating a bitmap from the same
528 data more than once will not be caught. */
531 /* Functions to access the contents of a bitmap, given an id. */
534 x_bitmap_height (f, id)
535 FRAME_PTR f;
536 int id;
538 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
542 x_bitmap_width (f, id)
543 FRAME_PTR f;
544 int id;
546 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
550 x_bitmap_pixmap (f, id)
551 FRAME_PTR f;
552 int id;
554 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
558 /* Allocate a new bitmap record. Returns index of new record. */
560 static int
561 x_allocate_bitmap_record (f)
562 FRAME_PTR f;
564 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
565 int i;
567 if (dpyinfo->bitmaps == NULL)
569 dpyinfo->bitmaps_size = 10;
570 dpyinfo->bitmaps
571 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
572 dpyinfo->bitmaps_last = 1;
573 return 1;
576 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
577 return ++dpyinfo->bitmaps_last;
579 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
580 if (dpyinfo->bitmaps[i].refcount == 0)
581 return i + 1;
583 dpyinfo->bitmaps_size *= 2;
584 dpyinfo->bitmaps
585 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
586 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
587 return ++dpyinfo->bitmaps_last;
590 /* Add one reference to the reference count of the bitmap with id ID. */
592 void
593 x_reference_bitmap (f, id)
594 FRAME_PTR f;
595 int id;
597 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
600 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
603 x_create_bitmap_from_data (f, bits, width, height)
604 struct frame *f;
605 char *bits;
606 unsigned int width, height;
608 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
609 Pixmap bitmap;
610 int id;
612 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
613 bits, width, height);
615 if (! bitmap)
616 return -1;
618 id = x_allocate_bitmap_record (f);
619 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
620 dpyinfo->bitmaps[id - 1].file = NULL;
621 dpyinfo->bitmaps[id - 1].refcount = 1;
622 dpyinfo->bitmaps[id - 1].depth = 1;
623 dpyinfo->bitmaps[id - 1].height = height;
624 dpyinfo->bitmaps[id - 1].width = width;
626 return id;
629 /* Create bitmap from file FILE for frame F. */
632 x_create_bitmap_from_file (f, file)
633 struct frame *f;
634 Lisp_Object file;
636 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
637 unsigned int width, height;
638 Pixmap bitmap;
639 int xhot, yhot, result, id;
640 Lisp_Object found;
641 int fd;
642 char *filename;
644 /* Look for an existing bitmap with the same name. */
645 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
647 if (dpyinfo->bitmaps[id].refcount
648 && dpyinfo->bitmaps[id].file
649 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
651 ++dpyinfo->bitmaps[id].refcount;
652 return id + 1;
656 /* Search bitmap-file-path for the file, if appropriate. */
657 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
658 if (fd < 0)
659 return -1;
660 /* XReadBitmapFile won't handle magic file names. */
661 if (fd == 0)
662 return -1;
663 close (fd);
665 filename = (char *) XSTRING (found)->data;
667 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
668 filename, &width, &height, &bitmap, &xhot, &yhot);
669 if (result != BitmapSuccess)
670 return -1;
672 id = x_allocate_bitmap_record (f);
673 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
674 dpyinfo->bitmaps[id - 1].refcount = 1;
675 dpyinfo->bitmaps[id - 1].file
676 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
677 dpyinfo->bitmaps[id - 1].depth = 1;
678 dpyinfo->bitmaps[id - 1].height = height;
679 dpyinfo->bitmaps[id - 1].width = width;
680 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
682 return id;
685 /* Remove reference to bitmap with id number ID. */
687 void
688 x_destroy_bitmap (f, id)
689 FRAME_PTR f;
690 int id;
692 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
694 if (id > 0)
696 --dpyinfo->bitmaps[id - 1].refcount;
697 if (dpyinfo->bitmaps[id - 1].refcount == 0)
699 BLOCK_INPUT;
700 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
701 if (dpyinfo->bitmaps[id - 1].file)
703 xfree (dpyinfo->bitmaps[id - 1].file);
704 dpyinfo->bitmaps[id - 1].file = NULL;
706 UNBLOCK_INPUT;
711 /* Free all the bitmaps for the display specified by DPYINFO. */
713 static void
714 x_destroy_all_bitmaps (dpyinfo)
715 struct x_display_info *dpyinfo;
717 int i;
718 for (i = 0; i < dpyinfo->bitmaps_last; i++)
719 if (dpyinfo->bitmaps[i].refcount > 0)
721 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
722 if (dpyinfo->bitmaps[i].file)
723 xfree (dpyinfo->bitmaps[i].file);
725 dpyinfo->bitmaps_last = 0;
728 /* Connect the frame-parameter names for X frames
729 to the ways of passing the parameter values to the window system.
731 The name of a parameter, as a Lisp symbol,
732 has an `x-frame-parameter' property which is an integer in Lisp
733 that is an index in this table. */
735 struct x_frame_parm_table
737 char *name;
738 void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
741 void x_set_foreground_color ();
742 void x_set_background_color ();
743 void x_set_mouse_color ();
744 void x_set_cursor_color ();
745 void x_set_border_color ();
746 void x_set_cursor_type ();
747 void x_set_icon_type ();
748 void x_set_icon_name ();
749 void x_set_font ();
750 void x_set_border_width ();
751 void x_set_internal_border_width ();
752 void x_explicitly_set_name ();
753 void x_set_autoraise ();
754 void x_set_autolower ();
755 void x_set_vertical_scroll_bars ();
756 void x_set_visibility ();
757 void x_set_menu_bar_lines ();
758 void x_set_scroll_bar_width ();
759 void x_set_title ();
760 void x_set_unsplittable ();
761 void x_set_toolbar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
762 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
763 Lisp_Object));
764 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
765 Lisp_Object));
766 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
767 Lisp_Object,
768 Lisp_Object,
769 char *, char *,
770 int));
772 static struct x_frame_parm_table x_frame_parms[] =
774 "auto-raise", x_set_autoraise,
775 "auto-lower", x_set_autolower,
776 "background-color", x_set_background_color,
777 "border-color", x_set_border_color,
778 "border-width", x_set_border_width,
779 "cursor-color", x_set_cursor_color,
780 "cursor-type", x_set_cursor_type,
781 "font", x_set_font,
782 "foreground-color", x_set_foreground_color,
783 "icon-name", x_set_icon_name,
784 "icon-type", x_set_icon_type,
785 "internal-border-width", x_set_internal_border_width,
786 "menu-bar-lines", x_set_menu_bar_lines,
787 "mouse-color", x_set_mouse_color,
788 "name", x_explicitly_set_name,
789 "scroll-bar-width", x_set_scroll_bar_width,
790 "title", x_set_title,
791 "unsplittable", x_set_unsplittable,
792 "vertical-scroll-bars", x_set_vertical_scroll_bars,
793 "visibility", x_set_visibility,
794 "toolbar-lines", x_set_toolbar_lines,
795 "scroll-bar-foreground", x_set_scroll_bar_foreground,
796 "scroll-bar-background", x_set_scroll_bar_background,
799 /* Attach the `x-frame-parameter' properties to
800 the Lisp symbol names of parameters relevant to X. */
802 void
803 init_x_parm_symbols ()
805 int i;
807 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
808 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
809 make_number (i));
812 /* Change the parameters of frame F as specified by ALIST.
813 If a parameter is not specially recognized, do nothing;
814 otherwise call the `x_set_...' function for that parameter. */
816 void
817 x_set_frame_parameters (f, alist)
818 FRAME_PTR f;
819 Lisp_Object alist;
821 Lisp_Object tail;
823 /* If both of these parameters are present, it's more efficient to
824 set them both at once. So we wait until we've looked at the
825 entire list before we set them. */
826 int width, height;
828 /* Same here. */
829 Lisp_Object left, top;
831 /* Same with these. */
832 Lisp_Object icon_left, icon_top;
834 /* Record in these vectors all the parms specified. */
835 Lisp_Object *parms;
836 Lisp_Object *values;
837 int i;
838 int left_no_change = 0, top_no_change = 0;
839 int icon_left_no_change = 0, icon_top_no_change = 0;
841 struct gcpro gcpro1, gcpro2;
843 i = 0;
844 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
845 i++;
847 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
848 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
850 /* Extract parm names and values into those vectors. */
852 i = 0;
853 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
855 Lisp_Object elt;
857 elt = Fcar (tail);
858 parms[i] = Fcar (elt);
859 values[i] = Fcdr (elt);
860 i++;
862 /* TAIL and ALIST are not used again below here. */
863 alist = tail = Qnil;
865 GCPRO2 (*parms, *values);
866 gcpro1.nvars = i;
867 gcpro2.nvars = i;
869 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
870 because their values appear in VALUES and strings are not valid. */
871 top = left = Qunbound;
872 icon_left = icon_top = Qunbound;
874 /* Provide default values for HEIGHT and WIDTH. */
875 if (FRAME_NEW_WIDTH (f))
876 width = FRAME_NEW_WIDTH (f);
877 else
878 width = FRAME_WIDTH (f);
880 if (FRAME_NEW_HEIGHT (f))
881 height = FRAME_NEW_HEIGHT (f);
882 else
883 height = FRAME_HEIGHT (f);
885 /* Now process them in reverse of specified order. */
886 for (i--; i >= 0; i--)
888 Lisp_Object prop, val;
890 prop = parms[i];
891 val = values[i];
893 if (EQ (prop, Qwidth) && NUMBERP (val))
894 width = XFASTINT (val);
895 else if (EQ (prop, Qheight) && NUMBERP (val))
896 height = XFASTINT (val);
897 else if (EQ (prop, Qtop))
898 top = val;
899 else if (EQ (prop, Qleft))
900 left = val;
901 else if (EQ (prop, Qicon_top))
902 icon_top = val;
903 else if (EQ (prop, Qicon_left))
904 icon_left = val;
905 else
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 /* Don't die if just one of these was set. */
920 if (EQ (left, Qunbound))
922 left_no_change = 1;
923 if (f->output_data.x->left_pos < 0)
924 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
925 else
926 XSETINT (left, f->output_data.x->left_pos);
928 if (EQ (top, Qunbound))
930 top_no_change = 1;
931 if (f->output_data.x->top_pos < 0)
932 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
933 else
934 XSETINT (top, f->output_data.x->top_pos);
937 /* If one of the icon positions was not set, preserve or default it. */
938 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
940 icon_left_no_change = 1;
941 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
942 if (NILP (icon_left))
943 XSETINT (icon_left, 0);
945 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
947 icon_top_no_change = 1;
948 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
949 if (NILP (icon_top))
950 XSETINT (icon_top, 0);
953 /* Don't set these parameters unless they've been explicitly
954 specified. The window might be mapped or resized while we're in
955 this function, and we don't want to override that unless the lisp
956 code has asked for it.
958 Don't set these parameters unless they actually differ from the
959 window's current parameters; the window may not actually exist
960 yet. */
962 Lisp_Object frame;
964 check_frame_size (f, &height, &width);
966 XSETFRAME (frame, f);
968 if (width != FRAME_WIDTH (f)
969 || height != FRAME_HEIGHT (f)
970 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
971 Fset_frame_size (frame, make_number (width), make_number (height));
973 if ((!NILP (left) || !NILP (top))
974 && ! (left_no_change && top_no_change)
975 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
976 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
978 int leftpos = 0;
979 int toppos = 0;
981 /* Record the signs. */
982 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
983 if (EQ (left, Qminus))
984 f->output_data.x->size_hint_flags |= XNegative;
985 else if (INTEGERP (left))
987 leftpos = XINT (left);
988 if (leftpos < 0)
989 f->output_data.x->size_hint_flags |= XNegative;
991 else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
992 && CONSP (XCONS (left)->cdr)
993 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
995 leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
996 f->output_data.x->size_hint_flags |= XNegative;
998 else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
999 && CONSP (XCONS (left)->cdr)
1000 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
1002 leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
1005 if (EQ (top, Qminus))
1006 f->output_data.x->size_hint_flags |= YNegative;
1007 else if (INTEGERP (top))
1009 toppos = XINT (top);
1010 if (toppos < 0)
1011 f->output_data.x->size_hint_flags |= YNegative;
1013 else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
1014 && CONSP (XCONS (top)->cdr)
1015 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
1017 toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
1018 f->output_data.x->size_hint_flags |= YNegative;
1020 else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
1021 && CONSP (XCONS (top)->cdr)
1022 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
1024 toppos = XINT (XCONS (XCONS (top)->cdr)->car);
1028 /* Store the numeric value of the position. */
1029 f->output_data.x->top_pos = toppos;
1030 f->output_data.x->left_pos = leftpos;
1032 f->output_data.x->win_gravity = NorthWestGravity;
1034 /* Actually set that position, and convert to absolute. */
1035 x_set_offset (f, leftpos, toppos, -1);
1038 if ((!NILP (icon_left) || !NILP (icon_top))
1039 && ! (icon_left_no_change && icon_top_no_change))
1040 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1043 UNGCPRO;
1046 /* Store the screen positions of frame F into XPTR and YPTR.
1047 These are the positions of the containing window manager window,
1048 not Emacs's own window. */
1050 void
1051 x_real_positions (f, xptr, yptr)
1052 FRAME_PTR f;
1053 int *xptr, *yptr;
1055 int win_x, win_y;
1056 Window child;
1058 /* This is pretty gross, but seems to be the easiest way out of
1059 the problem that arises when restarting window-managers. */
1061 #ifdef USE_X_TOOLKIT
1062 Window outer = (f->output_data.x->widget
1063 ? XtWindow (f->output_data.x->widget)
1064 : FRAME_X_WINDOW (f));
1065 #else
1066 Window outer = f->output_data.x->window_desc;
1067 #endif
1068 Window tmp_root_window;
1069 Window *tmp_children;
1070 int tmp_nchildren;
1072 while (1)
1074 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1075 Window outer_window;
1077 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1078 &f->output_data.x->parent_desc,
1079 &tmp_children, &tmp_nchildren);
1080 XFree ((char *) tmp_children);
1082 win_x = win_y = 0;
1084 /* Find the position of the outside upper-left corner of
1085 the inner window, with respect to the outer window. */
1086 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1087 outer_window = f->output_data.x->parent_desc;
1088 else
1089 outer_window = outer;
1091 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1093 /* From-window, to-window. */
1094 outer_window,
1095 FRAME_X_DISPLAY_INFO (f)->root_window,
1097 /* From-position, to-position. */
1098 0, 0, &win_x, &win_y,
1100 /* Child of win. */
1101 &child);
1103 /* It is possible for the window returned by the XQueryNotify
1104 to become invalid by the time we call XTranslateCoordinates.
1105 That can happen when you restart some window managers.
1106 If so, we get an error in XTranslateCoordinates.
1107 Detect that and try the whole thing over. */
1108 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1110 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1111 break;
1114 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1117 *xptr = win_x;
1118 *yptr = win_y;
1121 /* Insert a description of internally-recorded parameters of frame X
1122 into the parameter alist *ALISTPTR that is to be given to the user.
1123 Only parameters that are specific to the X window system
1124 and whose values are not correctly recorded in the frame's
1125 param_alist need to be considered here. */
1127 void
1128 x_report_frame_params (f, alistptr)
1129 struct frame *f;
1130 Lisp_Object *alistptr;
1132 char buf[16];
1133 Lisp_Object tem;
1135 /* Represent negative positions (off the top or left screen edge)
1136 in a way that Fmodify_frame_parameters will understand correctly. */
1137 XSETINT (tem, f->output_data.x->left_pos);
1138 if (f->output_data.x->left_pos >= 0)
1139 store_in_alist (alistptr, Qleft, tem);
1140 else
1141 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1143 XSETINT (tem, f->output_data.x->top_pos);
1144 if (f->output_data.x->top_pos >= 0)
1145 store_in_alist (alistptr, Qtop, tem);
1146 else
1147 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1149 store_in_alist (alistptr, Qborder_width,
1150 make_number (f->output_data.x->border_width));
1151 store_in_alist (alistptr, Qinternal_border_width,
1152 make_number (f->output_data.x->internal_border_width));
1153 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1154 store_in_alist (alistptr, Qwindow_id,
1155 build_string (buf));
1156 #ifdef USE_X_TOOLKIT
1157 /* Tooltip frame may not have this widget. */
1158 if (f->output_data.x->widget)
1159 #endif
1160 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1161 store_in_alist (alistptr, Qouter_window_id,
1162 build_string (buf));
1163 store_in_alist (alistptr, Qicon_name, f->icon_name);
1164 FRAME_SAMPLE_VISIBILITY (f);
1165 store_in_alist (alistptr, Qvisibility,
1166 (FRAME_VISIBLE_P (f) ? Qt
1167 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1168 store_in_alist (alistptr, Qdisplay,
1169 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->car);
1171 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1172 tem = Qnil;
1173 else
1174 XSETFASTINT (tem, f->output_data.x->parent_desc);
1175 store_in_alist (alistptr, Qparent_id, tem);
1179 /* Decide if color named COLOR is valid for the display associated with
1180 the selected frame; if so, return the rgb values in COLOR_DEF.
1181 If ALLOC is nonzero, allocate a new colormap cell. */
1184 defined_color (f, color, color_def, alloc)
1185 FRAME_PTR f;
1186 char *color;
1187 XColor *color_def;
1188 int alloc;
1190 register int status;
1191 Colormap screen_colormap;
1192 Display *display = FRAME_X_DISPLAY (f);
1194 BLOCK_INPUT;
1195 screen_colormap = DefaultColormap (display, XDefaultScreen (display));
1197 status = XParseColor (display, screen_colormap, color, color_def);
1198 if (status && alloc)
1200 status = XAllocColor (display, screen_colormap, color_def);
1201 if (!status)
1203 /* If we got to this point, the colormap is full, so we're
1204 going to try and get the next closest color.
1205 The algorithm used is a least-squares matching, which is
1206 what X uses for closest color matching with StaticColor visuals. */
1208 XColor *cells;
1209 int no_cells;
1210 int nearest;
1211 long nearest_delta, trial_delta;
1212 int x;
1214 no_cells = XDisplayCells (display, XDefaultScreen (display));
1215 cells = (XColor *) alloca (sizeof (XColor) * no_cells);
1217 for (x = 0; x < no_cells; x++)
1218 cells[x].pixel = x;
1220 XQueryColors (display, screen_colormap, cells, no_cells);
1221 nearest = 0;
1222 /* I'm assuming CSE so I'm not going to condense this. */
1223 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
1224 * ((color_def->red >> 8) - (cells[0].red >> 8)))
1226 (((color_def->green >> 8) - (cells[0].green >> 8))
1227 * ((color_def->green >> 8) - (cells[0].green >> 8)))
1229 (((color_def->blue >> 8) - (cells[0].blue >> 8))
1230 * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
1231 for (x = 1; x < no_cells; x++)
1233 trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
1234 * ((color_def->red >> 8) - (cells[x].red >> 8)))
1236 (((color_def->green >> 8) - (cells[x].green >> 8))
1237 * ((color_def->green >> 8) - (cells[x].green >> 8)))
1239 (((color_def->blue >> 8) - (cells[x].blue >> 8))
1240 * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
1241 if (trial_delta < nearest_delta)
1243 XColor temp;
1244 temp.red = cells[x].red;
1245 temp.green = cells[x].green;
1246 temp.blue = cells[x].blue;
1247 status = XAllocColor (display, screen_colormap, &temp);
1248 if (status)
1250 nearest = x;
1251 nearest_delta = trial_delta;
1255 color_def->red = cells[nearest].red;
1256 color_def->green = cells[nearest].green;
1257 color_def->blue = cells[nearest].blue;
1258 status = XAllocColor (display, screen_colormap, color_def);
1261 UNBLOCK_INPUT;
1263 if (status)
1264 return 1;
1265 else
1266 return 0;
1269 /* Given a string ARG naming a color, compute a pixel value from it
1270 suitable for screen F.
1271 If F is not a color screen, return DEF (default) regardless of what
1272 ARG says. */
1275 x_decode_color (f, arg, def)
1276 FRAME_PTR f;
1277 Lisp_Object arg;
1278 int def;
1280 XColor cdef;
1282 CHECK_STRING (arg, 0);
1284 if (strcmp (XSTRING (arg)->data, "black") == 0)
1285 return BLACK_PIX_DEFAULT (f);
1286 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1287 return WHITE_PIX_DEFAULT (f);
1289 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1290 return def;
1292 /* defined_color is responsible for coping with failures
1293 by looking for a near-miss. */
1294 if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
1295 return cdef.pixel;
1297 Fsignal (Qerror, Fcons (build_string ("undefined color"),
1298 Fcons (arg, Qnil)));
1301 /* Functions called only from `x_set_frame_param'
1302 to set individual parameters.
1304 If FRAME_X_WINDOW (f) is 0,
1305 the frame is being created and its X-window does not exist yet.
1306 In that case, just record the parameter's new value
1307 in the standard place; do not attempt to change the window. */
1309 void
1310 x_set_foreground_color (f, arg, oldval)
1311 struct frame *f;
1312 Lisp_Object arg, oldval;
1314 unsigned long pixel
1315 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1317 unload_color (f, f->output_data.x->foreground_pixel);
1318 f->output_data.x->foreground_pixel = pixel;
1320 if (FRAME_X_WINDOW (f) != 0)
1322 BLOCK_INPUT;
1323 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1324 f->output_data.x->foreground_pixel);
1325 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1326 f->output_data.x->foreground_pixel);
1327 UNBLOCK_INPUT;
1328 recompute_basic_faces (f);
1329 if (FRAME_VISIBLE_P (f))
1330 redraw_frame (f);
1334 void
1335 x_set_background_color (f, arg, oldval)
1336 struct frame *f;
1337 Lisp_Object arg, oldval;
1339 Pixmap temp;
1340 int mask;
1342 unsigned long pixel
1343 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1345 unload_color (f, f->output_data.x->background_pixel);
1346 f->output_data.x->background_pixel = pixel;
1348 if (FRAME_X_WINDOW (f) != 0)
1350 BLOCK_INPUT;
1351 /* The main frame area. */
1352 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1353 f->output_data.x->background_pixel);
1354 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1355 f->output_data.x->background_pixel);
1356 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1357 f->output_data.x->background_pixel);
1358 XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1359 f->output_data.x->background_pixel);
1361 Lisp_Object bar;
1362 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
1363 bar = XSCROLL_BAR (bar)->next)
1364 XSetWindowBackground (FRAME_X_DISPLAY (f),
1365 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
1366 f->output_data.x->background_pixel);
1368 UNBLOCK_INPUT;
1370 recompute_basic_faces (f);
1372 if (FRAME_VISIBLE_P (f))
1373 redraw_frame (f);
1377 void
1378 x_set_mouse_color (f, arg, oldval)
1379 struct frame *f;
1380 Lisp_Object arg, oldval;
1382 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1383 Cursor busy_cursor;
1384 int count;
1385 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1386 unsigned long mask_color = f->output_data.x->background_pixel;
1388 /* Don't let pointers be invisible. */
1389 if (mask_color == pixel
1390 && mask_color == f->output_data.x->background_pixel)
1391 pixel = f->output_data.x->foreground_pixel;
1393 unload_color (f, f->output_data.x->mouse_pixel);
1394 f->output_data.x->mouse_pixel = pixel;
1396 BLOCK_INPUT;
1398 /* It's not okay to crash if the user selects a screwy cursor. */
1399 count = x_catch_errors (FRAME_X_DISPLAY (f));
1401 if (!EQ (Qnil, Vx_pointer_shape))
1403 CHECK_NUMBER (Vx_pointer_shape, 0);
1404 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
1406 else
1407 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1408 x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
1410 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1412 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1413 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1414 XINT (Vx_nontext_pointer_shape));
1416 else
1417 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
1418 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1420 if (!EQ (Qnil, Vx_busy_pointer_shape))
1422 CHECK_NUMBER (Vx_busy_pointer_shape, 0);
1423 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1424 XINT (Vx_busy_pointer_shape));
1426 else
1427 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
1428 x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s");
1430 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1431 if (!EQ (Qnil, Vx_mode_pointer_shape))
1433 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1434 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1435 XINT (Vx_mode_pointer_shape));
1437 else
1438 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1439 x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
1441 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1443 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1444 cross_cursor
1445 = XCreateFontCursor (FRAME_X_DISPLAY (f),
1446 XINT (Vx_sensitive_text_pointer_shape));
1448 else
1449 cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
1451 /* Check and report errors with the above calls. */
1452 x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
1453 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1456 XColor fore_color, back_color;
1458 fore_color.pixel = f->output_data.x->mouse_pixel;
1459 back_color.pixel = mask_color;
1460 XQueryColor (FRAME_X_DISPLAY (f),
1461 DefaultColormap (FRAME_X_DISPLAY (f),
1462 DefaultScreen (FRAME_X_DISPLAY (f))),
1463 &fore_color);
1464 XQueryColor (FRAME_X_DISPLAY (f),
1465 DefaultColormap (FRAME_X_DISPLAY (f),
1466 DefaultScreen (FRAME_X_DISPLAY (f))),
1467 &back_color);
1468 XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
1469 &fore_color, &back_color);
1470 XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
1471 &fore_color, &back_color);
1472 XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
1473 &fore_color, &back_color);
1474 XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
1475 &fore_color, &back_color);
1476 XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
1477 &fore_color, &back_color);
1480 if (FRAME_X_WINDOW (f) != 0)
1481 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
1483 if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
1484 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
1485 f->output_data.x->text_cursor = cursor;
1487 if (nontext_cursor != f->output_data.x->nontext_cursor
1488 && f->output_data.x->nontext_cursor != 0)
1489 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
1490 f->output_data.x->nontext_cursor = nontext_cursor;
1492 if (busy_cursor != f->output_data.x->busy_cursor
1493 && f->output_data.x->busy_cursor != 0)
1494 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
1495 f->output_data.x->busy_cursor = busy_cursor;
1497 if (mode_cursor != f->output_data.x->modeline_cursor
1498 && f->output_data.x->modeline_cursor != 0)
1499 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
1500 f->output_data.x->modeline_cursor = mode_cursor;
1502 if (cross_cursor != f->output_data.x->cross_cursor
1503 && f->output_data.x->cross_cursor != 0)
1504 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
1505 f->output_data.x->cross_cursor = cross_cursor;
1507 XFlush (FRAME_X_DISPLAY (f));
1508 UNBLOCK_INPUT;
1511 void
1512 x_set_cursor_color (f, arg, oldval)
1513 struct frame *f;
1514 Lisp_Object arg, oldval;
1516 unsigned long fore_pixel, pixel;
1518 if (!EQ (Vx_cursor_fore_pixel, Qnil))
1519 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1520 WHITE_PIX_DEFAULT (f));
1521 else
1522 fore_pixel = f->output_data.x->background_pixel;
1523 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1525 /* Make sure that the cursor color differs from the background color. */
1526 if (pixel == f->output_data.x->background_pixel)
1528 pixel = f->output_data.x->mouse_pixel;
1529 if (pixel == fore_pixel)
1530 fore_pixel = f->output_data.x->background_pixel;
1533 unload_color (f, f->output_data.x->cursor_foreground_pixel);
1534 f->output_data.x->cursor_foreground_pixel = fore_pixel;
1536 unload_color (f, f->output_data.x->cursor_pixel);
1537 f->output_data.x->cursor_pixel = pixel;
1539 if (FRAME_X_WINDOW (f) != 0)
1541 BLOCK_INPUT;
1542 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1543 f->output_data.x->cursor_pixel);
1544 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1545 fore_pixel);
1546 UNBLOCK_INPUT;
1548 if (FRAME_VISIBLE_P (f))
1550 x_update_cursor (f, 0);
1551 x_update_cursor (f, 1);
1556 /* Set the border-color of frame F to value described by ARG.
1557 ARG can be a string naming a color.
1558 The border-color is used for the border that is drawn by the X server.
1559 Note that this does not fully take effect if done before
1560 F has an x-window; it must be redone when the window is created.
1562 Note: this is done in two routines because of the way X10 works.
1564 Note: under X11, this is normally the province of the window manager,
1565 and so emacs' border colors may be overridden. */
1567 void
1568 x_set_border_color (f, arg, oldval)
1569 struct frame *f;
1570 Lisp_Object arg, oldval;
1572 unsigned char *str;
1573 int pix;
1575 CHECK_STRING (arg, 0);
1576 str = XSTRING (arg)->data;
1578 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1580 x_set_border_pixel (f, pix);
1583 /* Set the border-color of frame F to pixel value PIX.
1584 Note that this does not fully take effect if done before
1585 F has an x-window. */
1587 void
1588 x_set_border_pixel (f, pix)
1589 struct frame *f;
1590 int pix;
1592 unload_color (f, f->output_data.x->border_pixel);
1593 f->output_data.x->border_pixel = pix;
1595 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1597 Pixmap temp;
1598 int mask;
1600 BLOCK_INPUT;
1601 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1602 (unsigned long)pix);
1603 UNBLOCK_INPUT;
1605 if (FRAME_VISIBLE_P (f))
1606 redraw_frame (f);
1610 void
1611 x_set_cursor_type (f, arg, oldval)
1612 FRAME_PTR f;
1613 Lisp_Object arg, oldval;
1615 if (EQ (arg, Qbar))
1617 FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
1618 f->output_data.x->cursor_width = 2;
1620 else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
1621 && INTEGERP (XCONS (arg)->cdr))
1623 FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
1624 f->output_data.x->cursor_width = XINT (XCONS (arg)->cdr);
1626 else
1627 /* Treat anything unknown as "box cursor".
1628 It was bad to signal an error; people have trouble fixing
1629 .Xdefaults with Emacs, when it has something bad in it. */
1630 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
1632 /* Make sure the cursor gets redrawn. This is overkill, but how
1633 often do people change cursor types? */
1634 update_mode_lines++;
1637 void
1638 x_set_icon_type (f, arg, oldval)
1639 struct frame *f;
1640 Lisp_Object arg, oldval;
1642 int result;
1644 if (STRINGP (arg))
1646 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1647 return;
1649 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1650 return;
1652 BLOCK_INPUT;
1653 if (NILP (arg))
1654 result = x_text_icon (f,
1655 (char *) XSTRING ((!NILP (f->icon_name)
1656 ? f->icon_name
1657 : f->name))->data);
1658 else
1659 result = x_bitmap_icon (f, arg);
1661 if (result)
1663 UNBLOCK_INPUT;
1664 error ("No icon window available");
1667 XFlush (FRAME_X_DISPLAY (f));
1668 UNBLOCK_INPUT;
1671 /* Return non-nil if frame F wants a bitmap icon. */
1673 Lisp_Object
1674 x_icon_type (f)
1675 FRAME_PTR f;
1677 Lisp_Object tem;
1679 tem = assq_no_quit (Qicon_type, f->param_alist);
1680 if (CONSP (tem))
1681 return XCONS (tem)->cdr;
1682 else
1683 return Qnil;
1686 void
1687 x_set_icon_name (f, arg, oldval)
1688 struct frame *f;
1689 Lisp_Object arg, oldval;
1691 int result;
1693 if (STRINGP (arg))
1695 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1696 return;
1698 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1699 return;
1701 f->icon_name = arg;
1703 if (f->output_data.x->icon_bitmap != 0)
1704 return;
1706 BLOCK_INPUT;
1708 result = x_text_icon (f,
1709 (char *) XSTRING ((!NILP (f->icon_name)
1710 ? f->icon_name
1711 : !NILP (f->title)
1712 ? f->title
1713 : f->name))->data);
1715 if (result)
1717 UNBLOCK_INPUT;
1718 error ("No icon window available");
1721 XFlush (FRAME_X_DISPLAY (f));
1722 UNBLOCK_INPUT;
1725 void
1726 x_set_font (f, arg, oldval)
1727 struct frame *f;
1728 Lisp_Object arg, oldval;
1730 Lisp_Object result;
1731 Lisp_Object fontset_name;
1732 Lisp_Object frame;
1734 CHECK_STRING (arg, 1);
1736 fontset_name = Fquery_fontset (arg, Qnil);
1738 BLOCK_INPUT;
1739 result = (STRINGP (fontset_name)
1740 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1741 : x_new_font (f, XSTRING (arg)->data));
1742 UNBLOCK_INPUT;
1744 if (EQ (result, Qnil))
1745 error ("Font `%s' is not defined", XSTRING (arg)->data);
1746 else if (EQ (result, Qt))
1747 error ("The characters of the given font have varying widths");
1748 else if (STRINGP (result))
1750 store_frame_param (f, Qfont, result);
1751 recompute_basic_faces (f);
1753 else
1754 abort ();
1756 /* Don't call `face-set-after-frame-default' when faces haven't been
1757 initialized yet. This is the case when called from
1758 Fx_create_frame. In that case, the X widget or window doesn't
1759 exist either, and we can end up in x_report_frame_params with a
1760 null widget which gives a segfault. */
1761 if (FRAME_FACE_CACHE (f))
1763 XSETFRAME (frame, f);
1764 call1 (Qface_set_after_frame_default, frame);
1768 void
1769 x_set_border_width (f, arg, oldval)
1770 struct frame *f;
1771 Lisp_Object arg, oldval;
1773 CHECK_NUMBER (arg, 0);
1775 if (XINT (arg) == f->output_data.x->border_width)
1776 return;
1778 if (FRAME_X_WINDOW (f) != 0)
1779 error ("Cannot change the border width of a window");
1781 f->output_data.x->border_width = XINT (arg);
1784 void
1785 x_set_internal_border_width (f, arg, oldval)
1786 struct frame *f;
1787 Lisp_Object arg, oldval;
1789 int old = f->output_data.x->internal_border_width;
1791 CHECK_NUMBER (arg, 0);
1792 f->output_data.x->internal_border_width = XINT (arg);
1793 if (f->output_data.x->internal_border_width < 0)
1794 f->output_data.x->internal_border_width = 0;
1796 #ifdef USE_X_TOOLKIT
1797 if (f->output_data.x->edit_widget)
1798 widget_store_internal_border (f->output_data.x->edit_widget);
1799 #endif
1801 if (f->output_data.x->internal_border_width == old)
1802 return;
1804 if (FRAME_X_WINDOW (f) != 0)
1806 BLOCK_INPUT;
1807 x_set_window_size (f, 0, f->width, f->height);
1808 #if 0
1809 x_set_resize_hint (f);
1810 #endif
1811 XFlush (FRAME_X_DISPLAY (f));
1812 UNBLOCK_INPUT;
1813 SET_FRAME_GARBAGED (f);
1817 void
1818 x_set_visibility (f, value, oldval)
1819 struct frame *f;
1820 Lisp_Object value, oldval;
1822 Lisp_Object frame;
1823 XSETFRAME (frame, f);
1825 if (NILP (value))
1826 Fmake_frame_invisible (frame, Qt);
1827 else if (EQ (value, Qicon))
1828 Ficonify_frame (frame);
1829 else
1830 Fmake_frame_visible (frame);
1833 static void
1834 x_set_menu_bar_lines_1 (window, n)
1835 Lisp_Object window;
1836 int n;
1838 struct window *w = XWINDOW (window);
1840 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1841 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1843 /* Handle just the top child in a vertical split. */
1844 if (!NILP (w->vchild))
1845 x_set_menu_bar_lines_1 (w->vchild, n);
1847 /* Adjust all children in a horizontal split. */
1848 for (window = w->hchild; !NILP (window); window = w->next)
1850 w = XWINDOW (window);
1851 x_set_menu_bar_lines_1 (window, n);
1855 void
1856 x_set_menu_bar_lines (f, value, oldval)
1857 struct frame *f;
1858 Lisp_Object value, oldval;
1860 int nlines;
1861 int olines = FRAME_MENU_BAR_LINES (f);
1863 /* Right now, menu bars don't work properly in minibuf-only frames;
1864 most of the commands try to apply themselves to the minibuffer
1865 frame itself, and get an error because you can't switch buffers
1866 in or split the minibuffer window. */
1867 if (FRAME_MINIBUF_ONLY_P (f))
1868 return;
1870 if (INTEGERP (value))
1871 nlines = XINT (value);
1872 else
1873 nlines = 0;
1875 /* Make sure we redisplay all windows in this frame. */
1876 windows_or_buffers_changed++;
1878 #ifdef USE_X_TOOLKIT
1879 FRAME_MENU_BAR_LINES (f) = 0;
1880 if (nlines)
1882 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1883 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1884 /* Make sure next redisplay shows the menu bar. */
1885 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1887 else
1889 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1890 free_frame_menubar (f);
1891 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1892 if (FRAME_X_P (f))
1893 f->output_data.x->menubar_widget = 0;
1895 #else /* not USE_X_TOOLKIT */
1896 FRAME_MENU_BAR_LINES (f) = nlines;
1897 x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
1898 #endif /* not USE_X_TOOLKIT */
1899 adjust_glyphs (f);
1903 /* Set the number of lines used for the tool bar of frame F to VALUE.
1904 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1905 is the old number of tool bar lines. This function changes the
1906 height of all windows on frame F to match the new tool bar height.
1907 The frame's height doesn't change. */
1909 void
1910 x_set_toolbar_lines (f, value, oldval)
1911 struct frame *f;
1912 Lisp_Object value, oldval;
1914 int delta, nlines;
1916 /* Use VALUE only if an integer >= 0. */
1917 if (INTEGERP (value) && XINT (value) >= 0)
1918 nlines = XFASTINT (value);
1919 else
1920 nlines = 0;
1922 /* Make sure we redisplay all windows in this frame. */
1923 ++windows_or_buffers_changed;
1925 delta = nlines - FRAME_TOOLBAR_LINES (f);
1926 FRAME_TOOLBAR_LINES (f) = nlines;
1927 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
1928 adjust_glyphs (f);
1932 /* Set the foreground color for scroll bars on frame F to VALUE.
1933 VALUE should be a string, a color name. If it isn't a string or
1934 isn't a valid color name, do nothing. OLDVAL is the old value of
1935 the frame parameter. */
1937 void
1938 x_set_scroll_bar_foreground (f, value, oldval)
1939 struct frame *f;
1940 Lisp_Object value, oldval;
1942 unsigned long pixel;
1944 if (STRINGP (value))
1945 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1946 else
1947 pixel = -1;
1949 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1950 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1952 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1953 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1955 /* Remove all scroll bars because they have wrong colors. */
1956 if (condemn_scroll_bars_hook)
1957 (*condemn_scroll_bars_hook) (f);
1958 if (judge_scroll_bars_hook)
1959 (*judge_scroll_bars_hook) (f);
1961 redraw_frame (f);
1966 /* Set the background color for scroll bars on frame F to VALUE VALUE
1967 should be a string, a color name. If it isn't a string or isn't a
1968 valid color name, do nothing. OLDVAL is the old value of the frame
1969 parameter. */
1971 void
1972 x_set_scroll_bar_background (f, value, oldval)
1973 struct frame *f;
1974 Lisp_Object value, oldval;
1976 unsigned long pixel;
1978 if (STRINGP (value))
1979 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1980 else
1981 pixel = -1;
1983 if (f->output_data.x->scroll_bar_background_pixel != -1)
1984 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1986 f->output_data.x->scroll_bar_background_pixel = pixel;
1987 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1989 /* Remove all scroll bars because they have wrong colors. */
1990 if (condemn_scroll_bars_hook)
1991 (*condemn_scroll_bars_hook) (f);
1992 if (judge_scroll_bars_hook)
1993 (*judge_scroll_bars_hook) (f);
1995 redraw_frame (f);
2000 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2001 x_id_name.
2003 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2004 name; if NAME is a string, set F's name to NAME and set
2005 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2007 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2008 suggesting a new name, which lisp code should override; if
2009 F->explicit_name is set, ignore the new name; otherwise, set it. */
2011 void
2012 x_set_name (f, name, explicit)
2013 struct frame *f;
2014 Lisp_Object name;
2015 int explicit;
2017 /* Make sure that requests from lisp code override requests from
2018 Emacs redisplay code. */
2019 if (explicit)
2021 /* If we're switching from explicit to implicit, we had better
2022 update the mode lines and thereby update the title. */
2023 if (f->explicit_name && NILP (name))
2024 update_mode_lines = 1;
2026 f->explicit_name = ! NILP (name);
2028 else if (f->explicit_name)
2029 return;
2031 /* If NAME is nil, set the name to the x_id_name. */
2032 if (NILP (name))
2034 /* Check for no change needed in this very common case
2035 before we do any consing. */
2036 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2037 XSTRING (f->name)->data))
2038 return;
2039 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2041 else
2042 CHECK_STRING (name, 0);
2044 /* Don't change the name if it's already NAME. */
2045 if (! NILP (Fstring_equal (name, f->name)))
2046 return;
2048 f->name = name;
2050 /* For setting the frame title, the title parameter should override
2051 the name parameter. */
2052 if (! NILP (f->title))
2053 name = f->title;
2055 if (FRAME_X_WINDOW (f))
2057 BLOCK_INPUT;
2058 #ifdef HAVE_X11R4
2060 XTextProperty text, icon;
2061 Lisp_Object icon_name;
2063 text.value = XSTRING (name)->data;
2064 text.encoding = XA_STRING;
2065 text.format = 8;
2066 text.nitems = STRING_BYTES (XSTRING (name));
2068 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
2070 icon.value = XSTRING (icon_name)->data;
2071 icon.encoding = XA_STRING;
2072 icon.format = 8;
2073 icon.nitems = STRING_BYTES (XSTRING (icon_name));
2074 #ifdef USE_X_TOOLKIT
2075 XSetWMName (FRAME_X_DISPLAY (f),
2076 XtWindow (f->output_data.x->widget), &text);
2077 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2078 &icon);
2079 #else /* not USE_X_TOOLKIT */
2080 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2081 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2082 #endif /* not USE_X_TOOLKIT */
2084 #else /* not HAVE_X11R4 */
2085 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2086 XSTRING (name)->data);
2087 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2088 XSTRING (name)->data);
2089 #endif /* not HAVE_X11R4 */
2090 UNBLOCK_INPUT;
2094 /* This function should be called when the user's lisp code has
2095 specified a name for the frame; the name will override any set by the
2096 redisplay code. */
2097 void
2098 x_explicitly_set_name (f, arg, oldval)
2099 FRAME_PTR f;
2100 Lisp_Object arg, oldval;
2102 x_set_name (f, arg, 1);
2105 /* This function should be called by Emacs redisplay code to set the
2106 name; names set this way will never override names set by the user's
2107 lisp code. */
2108 void
2109 x_implicitly_set_name (f, arg, oldval)
2110 FRAME_PTR f;
2111 Lisp_Object arg, oldval;
2113 x_set_name (f, arg, 0);
2116 /* Change the title of frame F to NAME.
2117 If NAME is nil, use the frame name as the title.
2119 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2120 name; if NAME is a string, set F's name to NAME and set
2121 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2123 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2124 suggesting a new name, which lisp code should override; if
2125 F->explicit_name is set, ignore the new name; otherwise, set it. */
2127 void
2128 x_set_title (f, name)
2129 struct frame *f;
2130 Lisp_Object name;
2132 /* Don't change the title if it's already NAME. */
2133 if (EQ (name, f->title))
2134 return;
2136 update_mode_lines = 1;
2138 f->title = name;
2140 if (NILP (name))
2141 name = f->name;
2142 else
2143 CHECK_STRING (name, 0);
2145 if (FRAME_X_WINDOW (f))
2147 BLOCK_INPUT;
2148 #ifdef HAVE_X11R4
2150 XTextProperty text, icon;
2151 Lisp_Object icon_name;
2153 text.value = XSTRING (name)->data;
2154 text.encoding = XA_STRING;
2155 text.format = 8;
2156 text.nitems = STRING_BYTES (XSTRING (name));
2158 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
2160 icon.value = XSTRING (icon_name)->data;
2161 icon.encoding = XA_STRING;
2162 icon.format = 8;
2163 icon.nitems = STRING_BYTES (XSTRING (icon_name));
2164 #ifdef USE_X_TOOLKIT
2165 XSetWMName (FRAME_X_DISPLAY (f),
2166 XtWindow (f->output_data.x->widget), &text);
2167 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2168 &icon);
2169 #else /* not USE_X_TOOLKIT */
2170 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2171 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2172 #endif /* not USE_X_TOOLKIT */
2174 #else /* not HAVE_X11R4 */
2175 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2176 XSTRING (name)->data);
2177 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2178 XSTRING (name)->data);
2179 #endif /* not HAVE_X11R4 */
2180 UNBLOCK_INPUT;
2184 void
2185 x_set_autoraise (f, arg, oldval)
2186 struct frame *f;
2187 Lisp_Object arg, oldval;
2189 f->auto_raise = !EQ (Qnil, arg);
2192 void
2193 x_set_autolower (f, arg, oldval)
2194 struct frame *f;
2195 Lisp_Object arg, oldval;
2197 f->auto_lower = !EQ (Qnil, arg);
2200 void
2201 x_set_unsplittable (f, arg, oldval)
2202 struct frame *f;
2203 Lisp_Object arg, oldval;
2205 f->no_split = !NILP (arg);
2208 void
2209 x_set_vertical_scroll_bars (f, arg, oldval)
2210 struct frame *f;
2211 Lisp_Object arg, oldval;
2213 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2214 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2215 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2216 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2218 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2219 = (NILP (arg)
2220 ? vertical_scroll_bar_none
2221 : EQ (Qright, arg)
2222 ? vertical_scroll_bar_right
2223 : vertical_scroll_bar_left);
2225 /* We set this parameter before creating the X window for the
2226 frame, so we can get the geometry right from the start.
2227 However, if the window hasn't been created yet, we shouldn't
2228 call x_set_window_size. */
2229 if (FRAME_X_WINDOW (f))
2230 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2234 void
2235 x_set_scroll_bar_width (f, arg, oldval)
2236 struct frame *f;
2237 Lisp_Object arg, oldval;
2239 int wid = FONT_WIDTH (f->output_data.x->font);
2241 if (NILP (arg))
2243 #ifdef USE_X_TOOLKIT
2244 /* A too wide or narrow toolkit scroll bar doesn't look good. */
2245 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2246 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2247 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2248 #else
2249 /* Make the actual width at least 14 pixels and a multiple of a
2250 character width. */
2251 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2253 /* Use all of that space (aside from required margins) for the
2254 scroll bar. */
2255 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2256 #endif
2258 if (FRAME_X_WINDOW (f))
2259 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2261 else if (INTEGERP (arg) && XINT (arg) > 0
2262 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2264 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2265 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2267 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2268 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2269 if (FRAME_X_WINDOW (f))
2270 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2273 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0);
2274 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2275 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2280 /* Subroutines of creating an X frame. */
2282 /* Make sure that Vx_resource_name is set to a reasonable value.
2283 Fix it up, or set it to `emacs' if it is too hopeless. */
2285 static void
2286 validate_x_resource_name ()
2288 int len = 0;
2289 /* Number of valid characters in the resource name. */
2290 int good_count = 0;
2291 /* Number of invalid characters in the resource name. */
2292 int bad_count = 0;
2293 Lisp_Object new;
2294 int i;
2296 if (!STRINGP (Vx_resource_class))
2297 Vx_resource_class = build_string (EMACS_CLASS);
2299 if (STRINGP (Vx_resource_name))
2301 unsigned char *p = XSTRING (Vx_resource_name)->data;
2302 int i;
2304 len = STRING_BYTES (XSTRING (Vx_resource_name));
2306 /* Only letters, digits, - and _ are valid in resource names.
2307 Count the valid characters and count the invalid ones. */
2308 for (i = 0; i < len; i++)
2310 int c = p[i];
2311 if (! ((c >= 'a' && c <= 'z')
2312 || (c >= 'A' && c <= 'Z')
2313 || (c >= '0' && c <= '9')
2314 || c == '-' || c == '_'))
2315 bad_count++;
2316 else
2317 good_count++;
2320 else
2321 /* Not a string => completely invalid. */
2322 bad_count = 5, good_count = 0;
2324 /* If name is valid already, return. */
2325 if (bad_count == 0)
2326 return;
2328 /* If name is entirely invalid, or nearly so, use `emacs'. */
2329 if (good_count == 0
2330 || (good_count == 1 && bad_count > 0))
2332 Vx_resource_name = build_string ("emacs");
2333 return;
2336 /* Name is partly valid. Copy it and replace the invalid characters
2337 with underscores. */
2339 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2341 for (i = 0; i < len; i++)
2343 int c = XSTRING (new)->data[i];
2344 if (! ((c >= 'a' && c <= 'z')
2345 || (c >= 'A' && c <= 'Z')
2346 || (c >= '0' && c <= '9')
2347 || c == '-' || c == '_'))
2348 XSTRING (new)->data[i] = '_';
2353 extern char *x_get_string_resource ();
2355 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2356 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2357 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2358 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2359 the name specified by the `-name' or `-rn' command-line arguments.\n\
2361 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2362 class, respectively. You must specify both of them or neither.\n\
2363 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2364 and the class is `Emacs.CLASS.SUBCLASS'.")
2365 (attribute, class, component, subclass)
2366 Lisp_Object attribute, class, component, subclass;
2368 register char *value;
2369 char *name_key;
2370 char *class_key;
2372 check_x ();
2374 CHECK_STRING (attribute, 0);
2375 CHECK_STRING (class, 0);
2377 if (!NILP (component))
2378 CHECK_STRING (component, 1);
2379 if (!NILP (subclass))
2380 CHECK_STRING (subclass, 2);
2381 if (NILP (component) != NILP (subclass))
2382 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2384 validate_x_resource_name ();
2386 /* Allocate space for the components, the dots which separate them,
2387 and the final '\0'. Make them big enough for the worst case. */
2388 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2389 + (STRINGP (component)
2390 ? STRING_BYTES (XSTRING (component)) : 0)
2391 + STRING_BYTES (XSTRING (attribute))
2392 + 3);
2394 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2395 + STRING_BYTES (XSTRING (class))
2396 + (STRINGP (subclass)
2397 ? STRING_BYTES (XSTRING (subclass)) : 0)
2398 + 3);
2400 /* Start with emacs.FRAMENAME for the name (the specific one)
2401 and with `Emacs' for the class key (the general one). */
2402 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2403 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2405 strcat (class_key, ".");
2406 strcat (class_key, XSTRING (class)->data);
2408 if (!NILP (component))
2410 strcat (class_key, ".");
2411 strcat (class_key, XSTRING (subclass)->data);
2413 strcat (name_key, ".");
2414 strcat (name_key, XSTRING (component)->data);
2417 strcat (name_key, ".");
2418 strcat (name_key, XSTRING (attribute)->data);
2420 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2421 name_key, class_key);
2423 if (value != (char *) 0)
2424 return build_string (value);
2425 else
2426 return Qnil;
2429 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2431 Lisp_Object
2432 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2433 struct x_display_info *dpyinfo;
2434 Lisp_Object attribute, class, component, subclass;
2436 register char *value;
2437 char *name_key;
2438 char *class_key;
2440 check_x ();
2442 CHECK_STRING (attribute, 0);
2443 CHECK_STRING (class, 0);
2445 if (!NILP (component))
2446 CHECK_STRING (component, 1);
2447 if (!NILP (subclass))
2448 CHECK_STRING (subclass, 2);
2449 if (NILP (component) != NILP (subclass))
2450 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2452 validate_x_resource_name ();
2454 /* Allocate space for the components, the dots which separate them,
2455 and the final '\0'. Make them big enough for the worst case. */
2456 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2457 + (STRINGP (component)
2458 ? STRING_BYTES (XSTRING (component)) : 0)
2459 + STRING_BYTES (XSTRING (attribute))
2460 + 3);
2462 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2463 + STRING_BYTES (XSTRING (class))
2464 + (STRINGP (subclass)
2465 ? STRING_BYTES (XSTRING (subclass)) : 0)
2466 + 3);
2468 /* Start with emacs.FRAMENAME for the name (the specific one)
2469 and with `Emacs' for the class key (the general one). */
2470 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2471 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2473 strcat (class_key, ".");
2474 strcat (class_key, XSTRING (class)->data);
2476 if (!NILP (component))
2478 strcat (class_key, ".");
2479 strcat (class_key, XSTRING (subclass)->data);
2481 strcat (name_key, ".");
2482 strcat (name_key, XSTRING (component)->data);
2485 strcat (name_key, ".");
2486 strcat (name_key, XSTRING (attribute)->data);
2488 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2490 if (value != (char *) 0)
2491 return build_string (value);
2492 else
2493 return Qnil;
2496 /* Used when C code wants a resource value. */
2498 char *
2499 x_get_resource_string (attribute, class)
2500 char *attribute, *class;
2502 char *name_key;
2503 char *class_key;
2505 /* Allocate space for the components, the dots which separate them,
2506 and the final '\0'. */
2507 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2508 + strlen (attribute) + 2);
2509 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2510 + strlen (class) + 2);
2512 sprintf (name_key, "%s.%s",
2513 XSTRING (Vinvocation_name)->data,
2514 attribute);
2515 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2517 return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame)->xrdb,
2518 name_key, class_key);
2521 /* Types we might convert a resource string into. */
2522 enum resource_types
2524 RES_TYPE_NUMBER,
2525 RES_TYPE_BOOLEAN,
2526 RES_TYPE_STRING,
2527 RES_TYPE_SYMBOL
2530 /* Return the value of parameter PARAM.
2532 First search ALIST, then Vdefault_frame_alist, then the X defaults
2533 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2535 Convert the resource to the type specified by desired_type.
2537 If no default is specified, return Qunbound. If you call
2538 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2539 and don't let it get stored in any Lisp-visible variables! */
2541 static Lisp_Object
2542 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2543 struct x_display_info *dpyinfo;
2544 Lisp_Object alist, param;
2545 char *attribute;
2546 char *class;
2547 enum resource_types type;
2549 register Lisp_Object tem;
2551 tem = Fassq (param, alist);
2552 if (EQ (tem, Qnil))
2553 tem = Fassq (param, Vdefault_frame_alist);
2554 if (EQ (tem, Qnil))
2557 if (attribute)
2559 tem = display_x_get_resource (dpyinfo,
2560 build_string (attribute),
2561 build_string (class),
2562 Qnil, Qnil);
2564 if (NILP (tem))
2565 return Qunbound;
2567 switch (type)
2569 case RES_TYPE_NUMBER:
2570 return make_number (atoi (XSTRING (tem)->data));
2572 case RES_TYPE_BOOLEAN:
2573 tem = Fdowncase (tem);
2574 if (!strcmp (XSTRING (tem)->data, "on")
2575 || !strcmp (XSTRING (tem)->data, "true"))
2576 return Qt;
2577 else
2578 return Qnil;
2580 case RES_TYPE_STRING:
2581 return tem;
2583 case RES_TYPE_SYMBOL:
2584 /* As a special case, we map the values `true' and `on'
2585 to Qt, and `false' and `off' to Qnil. */
2587 Lisp_Object lower;
2588 lower = Fdowncase (tem);
2589 if (!strcmp (XSTRING (lower)->data, "on")
2590 || !strcmp (XSTRING (lower)->data, "true"))
2591 return Qt;
2592 else if (!strcmp (XSTRING (lower)->data, "off")
2593 || !strcmp (XSTRING (lower)->data, "false"))
2594 return Qnil;
2595 else
2596 return Fintern (tem, Qnil);
2599 default:
2600 abort ();
2603 else
2604 return Qunbound;
2606 return Fcdr (tem);
2609 /* Like x_get_arg, but also record the value in f->param_alist. */
2611 static Lisp_Object
2612 x_get_and_record_arg (f, alist, param, attribute, class, type)
2613 struct frame *f;
2614 Lisp_Object alist, param;
2615 char *attribute;
2616 char *class;
2617 enum resource_types type;
2619 Lisp_Object value;
2621 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2622 attribute, class, type);
2623 if (! NILP (value))
2624 store_frame_param (f, param, value);
2626 return value;
2629 /* Record in frame F the specified or default value according to ALIST
2630 of the parameter named PROP (a Lisp symbol).
2631 If no value is specified for PROP, look for an X default for XPROP
2632 on the frame named NAME.
2633 If that is not found either, use the value DEFLT. */
2635 static Lisp_Object
2636 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2637 struct frame *f;
2638 Lisp_Object alist;
2639 Lisp_Object prop;
2640 Lisp_Object deflt;
2641 char *xprop;
2642 char *xclass;
2643 enum resource_types type;
2645 Lisp_Object tem;
2647 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2648 if (EQ (tem, Qunbound))
2649 tem = deflt;
2650 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2651 return tem;
2655 /* Record in frame F the specified or default value according to ALIST
2656 of the parameter named PROP (a Lisp symbol). If no value is
2657 specified for PROP, look for an X default for XPROP on the frame
2658 named NAME. If that is not found either, use the value DEFLT. */
2660 static Lisp_Object
2661 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2662 foreground_p)
2663 struct frame *f;
2664 Lisp_Object alist;
2665 Lisp_Object prop;
2666 char *xprop;
2667 char *xclass;
2668 int foreground_p;
2670 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2671 Lisp_Object tem;
2673 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2674 if (EQ (tem, Qunbound))
2676 #ifdef USE_TOOLKIT_SCROLL_BARS
2678 /* See if an X resource for the scroll bar color has been
2679 specified. */
2680 tem = display_x_get_resource (dpyinfo,
2681 build_string (foreground_p
2682 ? "foreground"
2683 : "background"),
2684 build_string (""),
2685 build_string ("verticalScrollBar"),
2686 build_string (""));
2687 if (!STRINGP (tem))
2689 /* If nothing has been specified, scroll bars will use a
2690 toolkit-dependent default. Because these defaults are
2691 difficult to get at without actually creating a scroll
2692 bar, use nil to indicate that no color has been
2693 specified. */
2694 tem = Qnil;
2697 #else /* not USE_TOOLKIT_SCROLL_BARS */
2699 tem = Qnil;
2701 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2704 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2705 return tem;
2710 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2711 "Parse an X-style geometry string STRING.\n\
2712 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2713 The properties returned may include `top', `left', `height', and `width'.\n\
2714 The value of `left' or `top' may be an integer,\n\
2715 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2716 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2717 (string)
2718 Lisp_Object string;
2720 int geometry, x, y;
2721 unsigned int width, height;
2722 Lisp_Object result;
2724 CHECK_STRING (string, 0);
2726 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2727 &x, &y, &width, &height);
2729 #if 0
2730 if (!!(geometry & XValue) != !!(geometry & YValue))
2731 error ("Must specify both x and y position, or neither");
2732 #endif
2734 result = Qnil;
2735 if (geometry & XValue)
2737 Lisp_Object element;
2739 if (x >= 0 && (geometry & XNegative))
2740 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2741 else if (x < 0 && ! (geometry & XNegative))
2742 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2743 else
2744 element = Fcons (Qleft, make_number (x));
2745 result = Fcons (element, result);
2748 if (geometry & YValue)
2750 Lisp_Object element;
2752 if (y >= 0 && (geometry & YNegative))
2753 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2754 else if (y < 0 && ! (geometry & YNegative))
2755 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2756 else
2757 element = Fcons (Qtop, make_number (y));
2758 result = Fcons (element, result);
2761 if (geometry & WidthValue)
2762 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2763 if (geometry & HeightValue)
2764 result = Fcons (Fcons (Qheight, make_number (height)), result);
2766 return result;
2769 /* Calculate the desired size and position of this window,
2770 and return the flags saying which aspects were specified.
2772 This function does not make the coordinates positive. */
2774 #define DEFAULT_ROWS 40
2775 #define DEFAULT_COLS 80
2777 static int
2778 x_figure_window_size (f, parms)
2779 struct frame *f;
2780 Lisp_Object parms;
2782 register Lisp_Object tem0, tem1, tem2;
2783 int height, width, left, top;
2784 register int geometry;
2785 long window_prompting = 0;
2786 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2788 /* Default values if we fall through.
2789 Actually, if that happens we should get
2790 window manager prompting. */
2791 SET_FRAME_WIDTH (f, DEFAULT_COLS);
2792 f->height = DEFAULT_ROWS;
2793 /* Window managers expect that if program-specified
2794 positions are not (0,0), they're intentional, not defaults. */
2795 f->output_data.x->top_pos = 0;
2796 f->output_data.x->left_pos = 0;
2798 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
2799 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
2800 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
2801 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2803 if (!EQ (tem0, Qunbound))
2805 CHECK_NUMBER (tem0, 0);
2806 f->height = XINT (tem0);
2808 if (!EQ (tem1, Qunbound))
2810 CHECK_NUMBER (tem1, 0);
2811 SET_FRAME_WIDTH (f, XINT (tem1));
2813 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2814 window_prompting |= USSize;
2815 else
2816 window_prompting |= PSize;
2819 f->output_data.x->vertical_scroll_bar_extra
2820 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2822 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2823 f->output_data.x->flags_areas_extra
2824 = 2 * FRAME_FLAGS_AREA_WIDTH (f);
2825 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2826 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2828 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
2829 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
2830 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
2831 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2833 if (EQ (tem0, Qminus))
2835 f->output_data.x->top_pos = 0;
2836 window_prompting |= YNegative;
2838 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
2839 && CONSP (XCONS (tem0)->cdr)
2840 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2842 f->output_data.x->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
2843 window_prompting |= YNegative;
2845 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
2846 && CONSP (XCONS (tem0)->cdr)
2847 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2849 f->output_data.x->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
2851 else if (EQ (tem0, Qunbound))
2852 f->output_data.x->top_pos = 0;
2853 else
2855 CHECK_NUMBER (tem0, 0);
2856 f->output_data.x->top_pos = XINT (tem0);
2857 if (f->output_data.x->top_pos < 0)
2858 window_prompting |= YNegative;
2861 if (EQ (tem1, Qminus))
2863 f->output_data.x->left_pos = 0;
2864 window_prompting |= XNegative;
2866 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
2867 && CONSP (XCONS (tem1)->cdr)
2868 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2870 f->output_data.x->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
2871 window_prompting |= XNegative;
2873 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
2874 && CONSP (XCONS (tem1)->cdr)
2875 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2877 f->output_data.x->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
2879 else if (EQ (tem1, Qunbound))
2880 f->output_data.x->left_pos = 0;
2881 else
2883 CHECK_NUMBER (tem1, 0);
2884 f->output_data.x->left_pos = XINT (tem1);
2885 if (f->output_data.x->left_pos < 0)
2886 window_prompting |= XNegative;
2889 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2890 window_prompting |= USPosition;
2891 else
2892 window_prompting |= PPosition;
2895 return window_prompting;
2898 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2900 Status
2901 XSetWMProtocols (dpy, w, protocols, count)
2902 Display *dpy;
2903 Window w;
2904 Atom *protocols;
2905 int count;
2907 Atom prop;
2908 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2909 if (prop == None) return False;
2910 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2911 (unsigned char *) protocols, count);
2912 return True;
2914 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2916 #ifdef USE_X_TOOLKIT
2918 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2919 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2920 already be present because of the toolkit (Motif adds some of them,
2921 for example, but Xt doesn't). */
2923 static void
2924 hack_wm_protocols (f, widget)
2925 FRAME_PTR f;
2926 Widget widget;
2928 Display *dpy = XtDisplay (widget);
2929 Window w = XtWindow (widget);
2930 int need_delete = 1;
2931 int need_focus = 1;
2932 int need_save = 1;
2934 BLOCK_INPUT;
2936 Atom type, *atoms = 0;
2937 int format = 0;
2938 unsigned long nitems = 0;
2939 unsigned long bytes_after;
2941 if ((XGetWindowProperty (dpy, w,
2942 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2943 (long)0, (long)100, False, XA_ATOM,
2944 &type, &format, &nitems, &bytes_after,
2945 (unsigned char **) &atoms)
2946 == Success)
2947 && format == 32 && type == XA_ATOM)
2948 while (nitems > 0)
2950 nitems--;
2951 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2952 need_delete = 0;
2953 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2954 need_focus = 0;
2955 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2956 need_save = 0;
2958 if (atoms) XFree ((char *) atoms);
2961 Atom props [10];
2962 int count = 0;
2963 if (need_delete)
2964 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2965 if (need_focus)
2966 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2967 if (need_save)
2968 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2969 if (count)
2970 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2971 XA_ATOM, 32, PropModeAppend,
2972 (unsigned char *) props, count);
2974 UNBLOCK_INPUT;
2976 #endif
2978 #ifdef USE_X_TOOLKIT
2980 /* Create and set up the X widget for frame F. */
2982 static void
2983 x_window (f, window_prompting, minibuffer_only)
2984 struct frame *f;
2985 long window_prompting;
2986 int minibuffer_only;
2988 XClassHint class_hints;
2989 XSetWindowAttributes attributes;
2990 unsigned long attribute_mask;
2992 Widget shell_widget;
2993 Widget pane_widget;
2994 Widget frame_widget;
2995 Arg al [25];
2996 int ac;
2998 BLOCK_INPUT;
3000 /* Use the resource name as the top-level widget name
3001 for looking up resources. Make a non-Lisp copy
3002 for the window manager, so GC relocation won't bother it.
3004 Elsewhere we specify the window name for the window manager. */
3007 char *str = (char *) XSTRING (Vx_resource_name)->data;
3008 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3009 strcpy (f->namebuf, str);
3012 ac = 0;
3013 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3014 XtSetArg (al[ac], XtNinput, 1); ac++;
3015 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3016 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3017 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3018 applicationShellWidgetClass,
3019 FRAME_X_DISPLAY (f), al, ac);
3021 f->output_data.x->widget = shell_widget;
3022 /* maybe_set_screen_title_format (shell_widget); */
3024 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3025 (widget_value *) NULL,
3026 shell_widget, False,
3027 (lw_callback) NULL,
3028 (lw_callback) NULL,
3029 (lw_callback) NULL);
3031 f->output_data.x->column_widget = pane_widget;
3033 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3034 the emacs screen when changing menubar. This reduces flickering. */
3036 ac = 0;
3037 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3038 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3039 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3040 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3041 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3042 frame_widget = XtCreateWidget (f->namebuf,
3043 emacsFrameClass,
3044 pane_widget, al, ac);
3046 f->output_data.x->edit_widget = frame_widget;
3048 XtManageChild (frame_widget);
3050 /* Do some needed geometry management. */
3052 int len;
3053 char *tem, shell_position[32];
3054 Arg al[2];
3055 int ac = 0;
3056 int extra_borders = 0;
3057 int menubar_size
3058 = (f->output_data.x->menubar_widget
3059 ? (f->output_data.x->menubar_widget->core.height
3060 + f->output_data.x->menubar_widget->core.border_width)
3061 : 0);
3062 extern char *lwlib_toolkit_type;
3064 #if 0 /* Experimentally, we now get the right results
3065 for -geometry -0-0 without this. 24 Aug 96, rms. */
3066 if (FRAME_EXTERNAL_MENU_BAR (f))
3068 Dimension ibw = 0;
3069 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3070 menubar_size += ibw;
3072 #endif
3074 f->output_data.x->menubar_height = menubar_size;
3076 #ifndef USE_LUCID
3077 /* Motif seems to need this amount added to the sizes
3078 specified for the shell widget. The Athena/Lucid widgets don't.
3079 Both conclusions reached experimentally. -- rms. */
3080 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3081 &extra_borders, NULL);
3082 extra_borders *= 2;
3083 #endif
3085 /* Convert our geometry parameters into a geometry string
3086 and specify it.
3087 Note that we do not specify here whether the position
3088 is a user-specified or program-specified one.
3089 We pass that information later, in x_wm_set_size_hints. */
3091 int left = f->output_data.x->left_pos;
3092 int xneg = window_prompting & XNegative;
3093 int top = f->output_data.x->top_pos;
3094 int yneg = window_prompting & YNegative;
3095 if (xneg)
3096 left = -left;
3097 if (yneg)
3098 top = -top;
3100 if (window_prompting & USPosition)
3101 sprintf (shell_position, "=%dx%d%c%d%c%d",
3102 PIXEL_WIDTH (f) + extra_borders,
3103 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3104 (xneg ? '-' : '+'), left,
3105 (yneg ? '-' : '+'), top);
3106 else
3107 sprintf (shell_position, "=%dx%d",
3108 PIXEL_WIDTH (f) + extra_borders,
3109 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3112 len = strlen (shell_position) + 1;
3113 /* We don't free this because we don't know whether
3114 it is safe to free it while the frame exists.
3115 It isn't worth the trouble of arranging to free it
3116 when the frame is deleted. */
3117 tem = (char *) xmalloc (len);
3118 strncpy (tem, shell_position, len);
3119 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3120 XtSetValues (shell_widget, al, ac);
3123 XtManageChild (pane_widget);
3124 XtRealizeWidget (shell_widget);
3126 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3128 validate_x_resource_name ();
3130 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3131 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3132 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3134 #ifdef HAVE_X_I18N
3135 #ifndef X_I18N_INHIBITED
3137 XIM xim;
3138 XIC xic = NULL;
3140 xim = XOpenIM (FRAME_X_DISPLAY (f), NULL, NULL, NULL);
3142 if (xim)
3144 xic = XCreateIC (xim,
3145 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
3146 XNClientWindow, FRAME_X_WINDOW(f),
3147 XNFocusWindow, FRAME_X_WINDOW(f),
3148 NULL);
3150 if (xic == 0)
3152 XCloseIM (xim);
3153 xim = NULL;
3156 FRAME_XIM (f) = xim;
3157 FRAME_XIC (f) = xic;
3159 #else /* X_I18N_INHIBITED */
3160 FRAME_XIM (f) = 0;
3161 FRAME_XIC (f) = 0;
3162 #endif /* X_I18N_INHIBITED */
3163 #endif /* HAVE_X_I18N */
3165 f->output_data.x->wm_hints.input = True;
3166 f->output_data.x->wm_hints.flags |= InputHint;
3167 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3168 &f->output_data.x->wm_hints);
3170 hack_wm_protocols (f, shell_widget);
3172 #ifdef HACK_EDITRES
3173 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3174 #endif
3176 /* Do a stupid property change to force the server to generate a
3177 PropertyNotify event so that the event_stream server timestamp will
3178 be initialized to something relevant to the time we created the window.
3180 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3181 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3182 XA_ATOM, 32, PropModeAppend,
3183 (unsigned char*) NULL, 0);
3185 /* Make all the standard events reach the Emacs frame. */
3186 attributes.event_mask = STANDARD_EVENT_SET;
3187 attribute_mask = CWEventMask;
3188 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3189 attribute_mask, &attributes);
3191 XtMapWidget (frame_widget);
3193 /* x_set_name normally ignores requests to set the name if the
3194 requested name is the same as the current name. This is the one
3195 place where that assumption isn't correct; f->name is set, but
3196 the X server hasn't been told. */
3198 Lisp_Object name;
3199 int explicit = f->explicit_name;
3201 f->explicit_name = 0;
3202 name = f->name;
3203 f->name = Qnil;
3204 x_set_name (f, name, explicit);
3207 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3208 f->output_data.x->text_cursor);
3210 UNBLOCK_INPUT;
3212 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3213 initialize_frame_menubar (f);
3214 lw_set_main_areas (pane_widget, f->output_data.x->menubar_widget, frame_widget);
3216 if (FRAME_X_WINDOW (f) == 0)
3217 error ("Unable to create window");
3220 #else /* not USE_X_TOOLKIT */
3222 /* Create and set up the X window for frame F. */
3224 void
3225 x_window (f)
3226 struct frame *f;
3229 XClassHint class_hints;
3230 XSetWindowAttributes attributes;
3231 unsigned long attribute_mask;
3233 attributes.background_pixel = f->output_data.x->background_pixel;
3234 attributes.border_pixel = f->output_data.x->border_pixel;
3235 attributes.bit_gravity = StaticGravity;
3236 attributes.backing_store = NotUseful;
3237 attributes.save_under = True;
3238 attributes.event_mask = STANDARD_EVENT_SET;
3239 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
3240 #if 0
3241 | CWBackingStore | CWSaveUnder
3242 #endif
3243 | CWEventMask);
3245 BLOCK_INPUT;
3246 FRAME_X_WINDOW (f)
3247 = XCreateWindow (FRAME_X_DISPLAY (f),
3248 f->output_data.x->parent_desc,
3249 f->output_data.x->left_pos,
3250 f->output_data.x->top_pos,
3251 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3252 f->output_data.x->border_width,
3253 CopyFromParent, /* depth */
3254 InputOutput, /* class */
3255 FRAME_X_DISPLAY_INFO (f)->visual,
3256 attribute_mask, &attributes);
3257 #ifdef HAVE_X_I18N
3258 #ifndef X_I18N_INHIBITED
3260 XIM xim;
3261 XIC xic = NULL;
3263 xim = XOpenIM (FRAME_X_DISPLAY(f), NULL, NULL, NULL);
3265 if (xim)
3267 xic = XCreateIC (xim,
3268 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
3269 XNClientWindow, FRAME_X_WINDOW(f),
3270 XNFocusWindow, FRAME_X_WINDOW(f),
3271 NULL);
3273 if (!xic)
3275 XCloseIM (xim);
3276 xim = NULL;
3280 FRAME_XIM (f) = xim;
3281 FRAME_XIC (f) = xic;
3283 #else /* X_I18N_INHIBITED */
3284 FRAME_XIM (f) = 0;
3285 FRAME_XIC (f) = 0;
3286 #endif /* X_I18N_INHIBITED */
3287 #endif /* HAVE_X_I18N */
3289 validate_x_resource_name ();
3291 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3292 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3293 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3295 /* The menubar is part of the ordinary display;
3296 it does not count in addition to the height of the window. */
3297 f->output_data.x->menubar_height = 0;
3299 /* This indicates that we use the "Passive Input" input model.
3300 Unless we do this, we don't get the Focus{In,Out} events that we
3301 need to draw the cursor correctly. Accursed bureaucrats.
3302 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3304 f->output_data.x->wm_hints.input = True;
3305 f->output_data.x->wm_hints.flags |= InputHint;
3306 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3307 &f->output_data.x->wm_hints);
3308 f->output_data.x->wm_hints.icon_pixmap = None;
3310 /* Request "save yourself" and "delete window" commands from wm. */
3312 Atom protocols[2];
3313 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3314 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3315 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3318 /* x_set_name normally ignores requests to set the name if the
3319 requested name is the same as the current name. This is the one
3320 place where that assumption isn't correct; f->name is set, but
3321 the X server hasn't been told. */
3323 Lisp_Object name;
3324 int explicit = f->explicit_name;
3326 f->explicit_name = 0;
3327 name = f->name;
3328 f->name = Qnil;
3329 x_set_name (f, name, explicit);
3332 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3333 f->output_data.x->text_cursor);
3335 UNBLOCK_INPUT;
3337 if (FRAME_X_WINDOW (f) == 0)
3338 error ("Unable to create window");
3341 #endif /* not USE_X_TOOLKIT */
3343 /* Handle the icon stuff for this window. Perhaps later we might
3344 want an x_set_icon_position which can be called interactively as
3345 well. */
3347 static void
3348 x_icon (f, parms)
3349 struct frame *f;
3350 Lisp_Object parms;
3352 Lisp_Object icon_x, icon_y;
3353 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3355 /* Set the position of the icon. Note that twm groups all
3356 icons in an icon window. */
3357 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3358 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3359 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3361 CHECK_NUMBER (icon_x, 0);
3362 CHECK_NUMBER (icon_y, 0);
3364 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3365 error ("Both left and top icon corners of icon must be specified");
3367 BLOCK_INPUT;
3369 if (! EQ (icon_x, Qunbound))
3370 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3372 /* Start up iconic or window? */
3373 x_wm_set_window_state
3374 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3375 Qicon)
3376 ? IconicState
3377 : NormalState));
3379 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3380 ? f->icon_name
3381 : f->name))->data);
3383 UNBLOCK_INPUT;
3386 /* Make the GC's needed for this window, setting the
3387 background, border and mouse colors; also create the
3388 mouse cursor and the gray border tile. */
3390 static char cursor_bits[] =
3392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3398 static void
3399 x_make_gc (f)
3400 struct frame *f;
3402 XGCValues gc_values;
3404 BLOCK_INPUT;
3406 /* Create the GC's of this frame.
3407 Note that many default values are used. */
3409 /* Normal video */
3410 gc_values.font = f->output_data.x->font->fid;
3411 gc_values.foreground = f->output_data.x->foreground_pixel;
3412 gc_values.background = f->output_data.x->background_pixel;
3413 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3414 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
3415 FRAME_X_WINDOW (f),
3416 GCLineWidth | GCFont
3417 | GCForeground | GCBackground,
3418 &gc_values);
3420 /* Reverse video style. */
3421 gc_values.foreground = f->output_data.x->background_pixel;
3422 gc_values.background = f->output_data.x->foreground_pixel;
3423 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
3424 FRAME_X_WINDOW (f),
3425 GCFont | GCForeground | GCBackground
3426 | GCLineWidth,
3427 &gc_values);
3429 /* Cursor has cursor-color background, background-color foreground. */
3430 gc_values.foreground = f->output_data.x->background_pixel;
3431 gc_values.background = f->output_data.x->cursor_pixel;
3432 gc_values.fill_style = FillOpaqueStippled;
3433 gc_values.stipple
3434 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3435 FRAME_X_DISPLAY_INFO (f)->root_window,
3436 cursor_bits, 16, 16);
3437 f->output_data.x->cursor_gc
3438 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3439 (GCFont | GCForeground | GCBackground
3440 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3441 &gc_values);
3443 /* Reliefs. */
3444 f->output_data.x->white_relief.gc = 0;
3445 f->output_data.x->black_relief.gc = 0;
3447 /* Create the gray border tile used when the pointer is not in
3448 the frame. Since this depends on the frame's pixel values,
3449 this must be done on a per-frame basis. */
3450 f->output_data.x->border_tile
3451 = (XCreatePixmapFromBitmapData
3452 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3453 gray_bits, gray_width, gray_height,
3454 f->output_data.x->foreground_pixel,
3455 f->output_data.x->background_pixel,
3456 DefaultDepth (FRAME_X_DISPLAY (f),
3457 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3459 UNBLOCK_INPUT;
3462 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3463 1, 1, 0,
3464 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3465 Returns an Emacs frame object.\n\
3466 ALIST is an alist of frame parameters.\n\
3467 If the parameters specify that the frame should not have a minibuffer,\n\
3468 and do not specify a specific minibuffer window to use,\n\
3469 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3470 be shared by the new frame.\n\
3472 This function is an internal primitive--use `make-frame' instead.")
3473 (parms)
3474 Lisp_Object parms;
3476 struct frame *f;
3477 Lisp_Object frame, tem;
3478 Lisp_Object name;
3479 int minibuffer_only = 0;
3480 long window_prompting = 0;
3481 int width, height;
3482 int count = specpdl_ptr - specpdl;
3483 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3484 Lisp_Object display;
3485 struct x_display_info *dpyinfo = NULL;
3486 Lisp_Object parent;
3487 struct kboard *kb;
3489 check_x ();
3491 /* Use this general default value to start with
3492 until we know if this frame has a specified name. */
3493 Vx_resource_name = Vinvocation_name;
3495 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3496 if (EQ (display, Qunbound))
3497 display = Qnil;
3498 dpyinfo = check_x_display_info (display);
3499 #ifdef MULTI_KBOARD
3500 kb = dpyinfo->kboard;
3501 #else
3502 kb = &the_only_kboard;
3503 #endif
3505 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3506 if (!STRINGP (name)
3507 && ! EQ (name, Qunbound)
3508 && ! NILP (name))
3509 error ("Invalid frame name--not a string or nil");
3511 if (STRINGP (name))
3512 Vx_resource_name = name;
3514 /* See if parent window is specified. */
3515 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3516 if (EQ (parent, Qunbound))
3517 parent = Qnil;
3518 if (! NILP (parent))
3519 CHECK_NUMBER (parent, 0);
3521 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3522 /* No need to protect DISPLAY because that's not used after passing
3523 it to make_frame_without_minibuffer. */
3524 frame = Qnil;
3525 GCPRO4 (parms, parent, name, frame);
3526 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3527 RES_TYPE_SYMBOL);
3528 if (EQ (tem, Qnone) || NILP (tem))
3529 f = make_frame_without_minibuffer (Qnil, kb, display);
3530 else if (EQ (tem, Qonly))
3532 f = make_minibuffer_frame ();
3533 minibuffer_only = 1;
3535 else if (WINDOWP (tem))
3536 f = make_frame_without_minibuffer (tem, kb, display);
3537 else
3538 f = make_frame (1);
3540 XSETFRAME (frame, f);
3542 /* Note that X Windows does support scroll bars. */
3543 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3545 f->output_method = output_x_window;
3546 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3547 bzero (f->output_data.x, sizeof (struct x_output));
3548 f->output_data.x->icon_bitmap = -1;
3549 f->output_data.x->fontset = -1;
3550 f->output_data.x->scroll_bar_foreground_pixel = -1;
3551 f->output_data.x->scroll_bar_background_pixel = -1;
3553 f->icon_name
3554 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3555 RES_TYPE_STRING);
3556 if (! STRINGP (f->icon_name))
3557 f->icon_name = Qnil;
3559 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3560 #ifdef MULTI_KBOARD
3561 FRAME_KBOARD (f) = kb;
3562 #endif
3564 /* Specify the parent under which to make this X window. */
3566 if (!NILP (parent))
3568 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3569 f->output_data.x->explicit_parent = 1;
3571 else
3573 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3574 f->output_data.x->explicit_parent = 0;
3577 /* Set the name; the functions to which we pass f expect the name to
3578 be set. */
3579 if (EQ (name, Qunbound) || NILP (name))
3581 f->name = build_string (dpyinfo->x_id_name);
3582 f->explicit_name = 0;
3584 else
3586 f->name = name;
3587 f->explicit_name = 1;
3588 /* use the frame's title when getting resources for this frame. */
3589 specbind (Qx_resource_name, name);
3592 /* Create fontsets from `global_fontset_alist' before handling fonts. */
3593 for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
3594 fs_register_fontset (f, XCONS (tem)->car);
3596 /* Extract the window parameters from the supplied values
3597 that are needed to determine window geometry. */
3599 Lisp_Object font;
3601 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3603 BLOCK_INPUT;
3604 /* First, try whatever font the caller has specified. */
3605 if (STRINGP (font))
3607 tem = Fquery_fontset (font, Qnil);
3608 if (STRINGP (tem))
3609 font = x_new_fontset (f, XSTRING (tem)->data);
3610 else
3611 font = x_new_font (f, XSTRING (font)->data);
3614 /* Try out a font which we hope has bold and italic variations. */
3615 if (!STRINGP (font))
3616 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3617 if (!STRINGP (font))
3618 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3619 if (! STRINGP (font))
3620 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3621 if (! STRINGP (font))
3622 /* This was formerly the first thing tried, but it finds too many fonts
3623 and takes too long. */
3624 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3625 /* If those didn't work, look for something which will at least work. */
3626 if (! STRINGP (font))
3627 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3628 UNBLOCK_INPUT;
3629 if (! STRINGP (font))
3630 font = build_string ("fixed");
3632 x_default_parameter (f, parms, Qfont, font,
3633 "font", "Font", RES_TYPE_STRING);
3636 #ifdef USE_LUCID
3637 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3638 whereby it fails to get any font. */
3639 xlwmenu_default_font = f->output_data.x->font;
3640 #endif
3642 x_default_parameter (f, parms, Qborder_width, make_number (2),
3643 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3645 /* This defaults to 2 in order to match xterm. We recognize either
3646 internalBorderWidth or internalBorder (which is what xterm calls
3647 it). */
3648 if (NILP (Fassq (Qinternal_border_width, parms)))
3650 Lisp_Object value;
3652 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3653 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3654 if (! EQ (value, Qunbound))
3655 parms = Fcons (Fcons (Qinternal_border_width, value),
3656 parms);
3658 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3659 "internalBorderWidth", "internalBorderWidth",
3660 RES_TYPE_NUMBER);
3661 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3662 "verticalScrollBars", "ScrollBars",
3663 RES_TYPE_SYMBOL);
3665 /* Also do the stuff which must be set before the window exists. */
3666 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3667 "foreground", "Foreground", RES_TYPE_STRING);
3668 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3669 "background", "Background", RES_TYPE_STRING);
3670 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3671 "pointerColor", "Foreground", RES_TYPE_STRING);
3672 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3673 "cursorColor", "Foreground", RES_TYPE_STRING);
3674 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3675 "borderColor", "BorderColor", RES_TYPE_STRING);
3677 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3678 "scrollBarForeground",
3679 "ScrollBarForeground", 1);
3680 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3681 "scrollBarBackground",
3682 "ScrollBarBackground", 0);
3684 /* Init faces before x_default_parameter is called for scroll-bar
3685 parameters because that function calls x_set_scroll_bar_width,
3686 which calls change_frame_size, which calls Fset_window_buffer,
3687 which runs hooks, which call Fvertical_motion. At the end, we
3688 end up in init_iterator with a null face cache, which should not
3689 happen. */
3690 init_frame_faces (f);
3692 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3693 "menuBar", "MenuBar", RES_TYPE_NUMBER);
3694 x_default_parameter (f, parms, Qtoolbar_lines, make_number (0),
3695 "toolBar", "ToolBar", RES_TYPE_NUMBER);
3696 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3697 "scrollBarWidth", "ScrollBarWidth",
3698 RES_TYPE_NUMBER);
3699 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3700 "bufferPredicate", "BufferPredicate",
3701 RES_TYPE_SYMBOL);
3702 x_default_parameter (f, parms, Qtitle, Qnil,
3703 "title", "Title", RES_TYPE_STRING);
3705 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3706 window_prompting = x_figure_window_size (f, parms);
3708 if (window_prompting & XNegative)
3710 if (window_prompting & YNegative)
3711 f->output_data.x->win_gravity = SouthEastGravity;
3712 else
3713 f->output_data.x->win_gravity = NorthEastGravity;
3715 else
3717 if (window_prompting & YNegative)
3718 f->output_data.x->win_gravity = SouthWestGravity;
3719 else
3720 f->output_data.x->win_gravity = NorthWestGravity;
3723 f->output_data.x->size_hint_flags = window_prompting;
3725 /* Create the X widget or window. Add the toolbar height to the
3726 initial frame height so that the user gets a text display area of
3727 the size he specified with -g or via .Xdefaults. Later changes
3728 of the toolbar height don't change the frame size. This is done
3729 so that users can create tall Emacs frames without having to
3730 guess how tall the toolbar will get. */
3731 f->height += FRAME_TOOLBAR_LINES (f);
3732 #ifdef USE_X_TOOLKIT
3733 x_window (f, window_prompting, minibuffer_only);
3734 #else
3735 x_window (f);
3736 #endif
3737 x_icon (f, parms);
3738 x_make_gc (f);
3740 call1 (Qface_set_after_frame_default, frame);
3742 /* We need to do this after creating the X window, so that the
3743 icon-creation functions can say whose icon they're describing. */
3744 x_default_parameter (f, parms, Qicon_type, Qnil,
3745 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
3747 x_default_parameter (f, parms, Qauto_raise, Qnil,
3748 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3749 x_default_parameter (f, parms, Qauto_lower, Qnil,
3750 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3751 x_default_parameter (f, parms, Qcursor_type, Qbox,
3752 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3754 /* Dimensions, especially f->height, must be done via change_frame_size.
3755 Change will not be effected unless different from the current
3756 f->height. */
3757 width = f->width;
3758 height = f->height;
3759 f->height = 0;
3760 SET_FRAME_WIDTH (f, 0);
3761 change_frame_size (f, height, width, 1, 0);
3763 /* Tell the server what size and position, etc, we want,
3764 and how badly we want them. */
3765 BLOCK_INPUT;
3766 x_wm_set_size_hint (f, window_prompting, 0);
3767 UNBLOCK_INPUT;
3769 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3770 f->no_split = minibuffer_only || EQ (tem, Qt);
3772 UNGCPRO;
3774 /* It is now ok to make the frame official
3775 even if we get an error below.
3776 And the frame needs to be on Vframe_list
3777 or making it visible won't work. */
3778 Vframe_list = Fcons (frame, Vframe_list);
3780 /* Now that the frame is official, it counts as a reference to
3781 its display. */
3782 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3784 /* Make the window appear on the frame and enable display,
3785 unless the caller says not to. However, with explicit parent,
3786 Emacs cannot control visibility, so don't try. */
3787 if (! f->output_data.x->explicit_parent)
3789 Lisp_Object visibility;
3791 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3792 RES_TYPE_SYMBOL);
3793 if (EQ (visibility, Qunbound))
3794 visibility = Qt;
3796 if (EQ (visibility, Qicon))
3797 x_iconify_frame (f);
3798 else if (! NILP (visibility))
3799 x_make_frame_visible (f);
3800 else
3801 /* Must have been Qnil. */
3805 return unbind_to (count, frame);
3808 /* FRAME is used only to get a handle on the X display. We don't pass the
3809 display info directly because we're called from frame.c, which doesn't
3810 know about that structure. */
3812 Lisp_Object
3813 x_get_focus_frame (frame)
3814 struct frame *frame;
3816 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3817 Lisp_Object xfocus;
3818 if (! dpyinfo->x_focus_frame)
3819 return Qnil;
3821 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3822 return xfocus;
3826 DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
3827 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3828 If FRAME is omitted or nil, use the selected frame.")
3829 (color, frame)
3830 Lisp_Object color, frame;
3832 XColor foo;
3833 FRAME_PTR f = check_x_frame (frame);
3835 CHECK_STRING (color, 1);
3837 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3838 return Qt;
3839 else
3840 return Qnil;
3843 DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
3844 "Return a description of the color named COLOR on frame FRAME.\n\
3845 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3846 These values appear to range from 0 to 65280 or 65535, depending\n\
3847 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3848 If FRAME is omitted or nil, use the selected frame.")
3849 (color, frame)
3850 Lisp_Object color, frame;
3852 XColor foo;
3853 FRAME_PTR f = check_x_frame (frame);
3855 CHECK_STRING (color, 1);
3857 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3859 Lisp_Object rgb[3];
3861 rgb[0] = make_number (foo.red);
3862 rgb[1] = make_number (foo.green);
3863 rgb[2] = make_number (foo.blue);
3864 return Flist (3, rgb);
3866 else
3867 return Qnil;
3870 DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
3871 "Return t if the X display supports color.\n\
3872 The optional argument DISPLAY specifies which display to ask about.\n\
3873 DISPLAY should be either a frame or a display name (a string).\n\
3874 If omitted or nil, that stands for the selected frame's display.")
3875 (display)
3876 Lisp_Object display;
3878 struct x_display_info *dpyinfo = check_x_display_info (display);
3880 if (dpyinfo->n_planes <= 2)
3881 return Qnil;
3883 switch (dpyinfo->visual->class)
3885 case StaticColor:
3886 case PseudoColor:
3887 case TrueColor:
3888 case DirectColor:
3889 return Qt;
3891 default:
3892 return Qnil;
3896 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3897 0, 1, 0,
3898 "Return t if the X display supports shades of gray.\n\
3899 Note that color displays do support shades of gray.\n\
3900 The optional argument DISPLAY specifies which display to ask about.\n\
3901 DISPLAY should be either a frame or a display name (a string).\n\
3902 If omitted or nil, that stands for the selected frame's display.")
3903 (display)
3904 Lisp_Object display;
3906 struct x_display_info *dpyinfo = check_x_display_info (display);
3908 if (dpyinfo->n_planes <= 1)
3909 return Qnil;
3911 switch (dpyinfo->visual->class)
3913 case StaticColor:
3914 case PseudoColor:
3915 case TrueColor:
3916 case DirectColor:
3917 case StaticGray:
3918 case GrayScale:
3919 return Qt;
3921 default:
3922 return Qnil;
3926 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3927 0, 1, 0,
3928 "Returns the width in pixels of the X display DISPLAY.\n\
3929 The optional argument DISPLAY specifies which display to ask about.\n\
3930 DISPLAY should be either a frame or a display name (a string).\n\
3931 If omitted or nil, that stands for the selected frame's display.")
3932 (display)
3933 Lisp_Object display;
3935 struct x_display_info *dpyinfo = check_x_display_info (display);
3937 return make_number (dpyinfo->width);
3940 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3941 Sx_display_pixel_height, 0, 1, 0,
3942 "Returns the height in pixels of the X display DISPLAY.\n\
3943 The optional argument DISPLAY specifies which display to ask about.\n\
3944 DISPLAY should be either a frame or a display name (a string).\n\
3945 If omitted or nil, that stands for the selected frame's display.")
3946 (display)
3947 Lisp_Object display;
3949 struct x_display_info *dpyinfo = check_x_display_info (display);
3951 return make_number (dpyinfo->height);
3954 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3955 0, 1, 0,
3956 "Returns the number of bitplanes of the X display DISPLAY.\n\
3957 The optional argument DISPLAY specifies which display to ask about.\n\
3958 DISPLAY should be either a frame or a display name (a string).\n\
3959 If omitted or nil, that stands for the selected frame's display.")
3960 (display)
3961 Lisp_Object display;
3963 struct x_display_info *dpyinfo = check_x_display_info (display);
3965 return make_number (dpyinfo->n_planes);
3968 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3969 0, 1, 0,
3970 "Returns the number of color cells of the X display DISPLAY.\n\
3971 The optional argument DISPLAY specifies which display to ask about.\n\
3972 DISPLAY should be either a frame or a display name (a string).\n\
3973 If omitted or nil, that stands for the selected frame's display.")
3974 (display)
3975 Lisp_Object display;
3977 struct x_display_info *dpyinfo = check_x_display_info (display);
3979 return make_number (DisplayCells (dpyinfo->display,
3980 XScreenNumberOfScreen (dpyinfo->screen)));
3983 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3984 Sx_server_max_request_size,
3985 0, 1, 0,
3986 "Returns the maximum request size of the X server of display DISPLAY.\n\
3987 The optional argument DISPLAY specifies which display to ask about.\n\
3988 DISPLAY should be either a frame or a display name (a string).\n\
3989 If omitted or nil, that stands for the selected frame's display.")
3990 (display)
3991 Lisp_Object display;
3993 struct x_display_info *dpyinfo = check_x_display_info (display);
3995 return make_number (MAXREQUEST (dpyinfo->display));
3998 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3999 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4000 The optional argument DISPLAY specifies which display to ask about.\n\
4001 DISPLAY should be either a frame or a display name (a string).\n\
4002 If omitted or nil, that stands for the selected frame's display.")
4003 (display)
4004 Lisp_Object display;
4006 struct x_display_info *dpyinfo = check_x_display_info (display);
4007 char *vendor = ServerVendor (dpyinfo->display);
4009 if (! vendor) vendor = "";
4010 return build_string (vendor);
4013 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4014 "Returns the version numbers of the X server of display DISPLAY.\n\
4015 The value is a list of three integers: the major and minor\n\
4016 version numbers of the X Protocol in use, and the vendor-specific release\n\
4017 number. See also the function `x-server-vendor'.\n\n\
4018 The optional argument DISPLAY specifies which display to ask about.\n\
4019 DISPLAY should be either a frame or a display name (a string).\n\
4020 If omitted or nil, that stands for the selected frame's display.")
4021 (display)
4022 Lisp_Object display;
4024 struct x_display_info *dpyinfo = check_x_display_info (display);
4025 Display *dpy = dpyinfo->display;
4027 return Fcons (make_number (ProtocolVersion (dpy)),
4028 Fcons (make_number (ProtocolRevision (dpy)),
4029 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4032 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4033 "Returns the number of screens on the X server of display DISPLAY.\n\
4034 The optional argument DISPLAY specifies which display to ask about.\n\
4035 DISPLAY should be either a frame or a display name (a string).\n\
4036 If omitted or nil, that stands for the selected frame's display.")
4037 (display)
4038 Lisp_Object display;
4040 struct x_display_info *dpyinfo = check_x_display_info (display);
4042 return make_number (ScreenCount (dpyinfo->display));
4045 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4046 "Returns the height in millimeters of the X display DISPLAY.\n\
4047 The optional argument DISPLAY specifies which display to ask about.\n\
4048 DISPLAY should be either a frame or a display name (a string).\n\
4049 If omitted or nil, that stands for the selected frame's display.")
4050 (display)
4051 Lisp_Object display;
4053 struct x_display_info *dpyinfo = check_x_display_info (display);
4055 return make_number (HeightMMOfScreen (dpyinfo->screen));
4058 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4059 "Returns the width in millimeters of the X display DISPLAY.\n\
4060 The optional argument DISPLAY specifies which display to ask about.\n\
4061 DISPLAY should be either a frame or a display name (a string).\n\
4062 If omitted or nil, that stands for the selected frame's display.")
4063 (display)
4064 Lisp_Object display;
4066 struct x_display_info *dpyinfo = check_x_display_info (display);
4068 return make_number (WidthMMOfScreen (dpyinfo->screen));
4071 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4072 Sx_display_backing_store, 0, 1, 0,
4073 "Returns an indication of whether X display DISPLAY does backing store.\n\
4074 The value may be `always', `when-mapped', or `not-useful'.\n\
4075 The optional argument DISPLAY specifies which display to ask about.\n\
4076 DISPLAY should be either a frame or a display name (a string).\n\
4077 If omitted or nil, that stands for the selected frame's display.")
4078 (display)
4079 Lisp_Object display;
4081 struct x_display_info *dpyinfo = check_x_display_info (display);
4083 switch (DoesBackingStore (dpyinfo->screen))
4085 case Always:
4086 return intern ("always");
4088 case WhenMapped:
4089 return intern ("when-mapped");
4091 case NotUseful:
4092 return intern ("not-useful");
4094 default:
4095 error ("Strange value for BackingStore parameter of screen");
4099 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4100 Sx_display_visual_class, 0, 1, 0,
4101 "Returns the visual class of the X display DISPLAY.\n\
4102 The value is one of the symbols `static-gray', `gray-scale',\n\
4103 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4104 The optional argument DISPLAY specifies which display to ask about.\n\
4105 DISPLAY should be either a frame or a display name (a string).\n\
4106 If omitted or nil, that stands for the selected frame's display.")
4107 (display)
4108 Lisp_Object display;
4110 struct x_display_info *dpyinfo = check_x_display_info (display);
4112 switch (dpyinfo->visual->class)
4114 case StaticGray: return (intern ("static-gray"));
4115 case GrayScale: return (intern ("gray-scale"));
4116 case StaticColor: return (intern ("static-color"));
4117 case PseudoColor: return (intern ("pseudo-color"));
4118 case TrueColor: return (intern ("true-color"));
4119 case DirectColor: return (intern ("direct-color"));
4120 default:
4121 error ("Display has an unknown visual class");
4125 DEFUN ("x-display-save-under", Fx_display_save_under,
4126 Sx_display_save_under, 0, 1, 0,
4127 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4128 The optional argument DISPLAY specifies which display to ask about.\n\
4129 DISPLAY should be either a frame or a display name (a string).\n\
4130 If omitted or nil, that stands for the selected frame's display.")
4131 (display)
4132 Lisp_Object display;
4134 struct x_display_info *dpyinfo = check_x_display_info (display);
4136 if (DoesSaveUnders (dpyinfo->screen) == True)
4137 return Qt;
4138 else
4139 return Qnil;
4143 x_pixel_width (f)
4144 register struct frame *f;
4146 return PIXEL_WIDTH (f);
4150 x_pixel_height (f)
4151 register struct frame *f;
4153 return PIXEL_HEIGHT (f);
4157 x_char_width (f)
4158 register struct frame *f;
4160 return FONT_WIDTH (f->output_data.x->font);
4164 x_char_height (f)
4165 register struct frame *f;
4167 return f->output_data.x->line_height;
4171 x_screen_planes (f)
4172 register struct frame *f;
4174 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4177 #if 0 /* These no longer seem like the right way to do things. */
4179 /* Draw a rectangle on the frame with left top corner including
4180 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
4181 CHARS by LINES wide and long and is the color of the cursor. */
4183 void
4184 x_rectangle (f, gc, left_char, top_char, chars, lines)
4185 register struct frame *f;
4186 GC gc;
4187 register int top_char, left_char, chars, lines;
4189 int width;
4190 int height;
4191 int left = (left_char * FONT_WIDTH (f->output_data.x->font)
4192 + f->output_data.x->internal_border_width);
4193 int top = (top_char * f->output_data.x->line_height
4194 + f->output_data.x->internal_border_width);
4196 if (chars < 0)
4197 width = FONT_WIDTH (f->output_data.x->font) / 2;
4198 else
4199 width = FONT_WIDTH (f->output_data.x->font) * chars;
4200 if (lines < 0)
4201 height = f->output_data.x->line_height / 2;
4202 else
4203 height = f->output_data.x->line_height * lines;
4205 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4206 gc, left, top, width, height);
4209 DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
4210 "Draw a rectangle on FRAME between coordinates specified by\n\
4211 numbers X0, Y0, X1, Y1 in the cursor pixel.")
4212 (frame, X0, Y0, X1, Y1)
4213 register Lisp_Object frame, X0, X1, Y0, Y1;
4215 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
4217 CHECK_LIVE_FRAME (frame, 0);
4218 CHECK_NUMBER (X0, 0);
4219 CHECK_NUMBER (Y0, 1);
4220 CHECK_NUMBER (X1, 2);
4221 CHECK_NUMBER (Y1, 3);
4223 x0 = XINT (X0);
4224 x1 = XINT (X1);
4225 y0 = XINT (Y0);
4226 y1 = XINT (Y1);
4228 if (y1 > y0)
4230 top = y0;
4231 n_lines = y1 - y0 + 1;
4233 else
4235 top = y1;
4236 n_lines = y0 - y1 + 1;
4239 if (x1 > x0)
4241 left = x0;
4242 n_chars = x1 - x0 + 1;
4244 else
4246 left = x1;
4247 n_chars = x0 - x1 + 1;
4250 BLOCK_INPUT;
4251 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
4252 left, top, n_chars, n_lines);
4253 UNBLOCK_INPUT;
4255 return Qt;
4258 DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
4259 "Draw a rectangle drawn on FRAME between coordinates\n\
4260 X0, Y0, X1, Y1 in the regular background-pixel.")
4261 (frame, X0, Y0, X1, Y1)
4262 register Lisp_Object frame, X0, Y0, X1, Y1;
4264 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
4266 CHECK_LIVE_FRAME (frame, 0);
4267 CHECK_NUMBER (X0, 0);
4268 CHECK_NUMBER (Y0, 1);
4269 CHECK_NUMBER (X1, 2);
4270 CHECK_NUMBER (Y1, 3);
4272 x0 = XINT (X0);
4273 x1 = XINT (X1);
4274 y0 = XINT (Y0);
4275 y1 = XINT (Y1);
4277 if (y1 > y0)
4279 top = y0;
4280 n_lines = y1 - y0 + 1;
4282 else
4284 top = y1;
4285 n_lines = y0 - y1 + 1;
4288 if (x1 > x0)
4290 left = x0;
4291 n_chars = x1 - x0 + 1;
4293 else
4295 left = x1;
4296 n_chars = x0 - x1 + 1;
4299 BLOCK_INPUT;
4300 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
4301 left, top, n_chars, n_lines);
4302 UNBLOCK_INPUT;
4304 return Qt;
4307 /* Draw lines around the text region beginning at the character position
4308 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4309 pixel and line characteristics. */
4311 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4313 static void
4314 outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
4315 register struct frame *f;
4316 GC gc;
4317 int top_x, top_y, bottom_x, bottom_y;
4319 register int ibw = f->output_data.x->internal_border_width;
4320 register int font_w = FONT_WIDTH (f->output_data.x->font);
4321 register int font_h = f->output_data.x->line_height;
4322 int y = top_y;
4323 int x = line_len (y);
4324 XPoint *pixel_points
4325 = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
4326 register XPoint *this_point = pixel_points;
4328 /* Do the horizontal top line/lines */
4329 if (top_x == 0)
4331 this_point->x = ibw;
4332 this_point->y = ibw + (font_h * top_y);
4333 this_point++;
4334 if (x == 0)
4335 this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
4336 else
4337 this_point->x = ibw + (font_w * x);
4338 this_point->y = (this_point - 1)->y;
4340 else
4342 this_point->x = ibw;
4343 this_point->y = ibw + (font_h * (top_y + 1));
4344 this_point++;
4345 this_point->x = ibw + (font_w * top_x);
4346 this_point->y = (this_point - 1)->y;
4347 this_point++;
4348 this_point->x = (this_point - 1)->x;
4349 this_point->y = ibw + (font_h * top_y);
4350 this_point++;
4351 this_point->x = ibw + (font_w * x);
4352 this_point->y = (this_point - 1)->y;
4355 /* Now do the right side. */
4356 while (y < bottom_y)
4357 { /* Right vertical edge */
4358 this_point++;
4359 this_point->x = (this_point - 1)->x;
4360 this_point->y = ibw + (font_h * (y + 1));
4361 this_point++;
4363 y++; /* Horizontal connection to next line */
4364 x = line_len (y);
4365 if (x == 0)
4366 this_point->x = ibw + (font_w / 2);
4367 else
4368 this_point->x = ibw + (font_w * x);
4370 this_point->y = (this_point - 1)->y;
4373 /* Now do the bottom and connect to the top left point. */
4374 this_point->x = ibw + (font_w * (bottom_x + 1));
4376 this_point++;
4377 this_point->x = (this_point - 1)->x;
4378 this_point->y = ibw + (font_h * (bottom_y + 1));
4379 this_point++;
4380 this_point->x = ibw;
4381 this_point->y = (this_point - 1)->y;
4382 this_point++;
4383 this_point->x = pixel_points->x;
4384 this_point->y = pixel_points->y;
4386 XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4387 gc, pixel_points,
4388 (this_point - pixel_points + 1), CoordModeOrigin);
4391 DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
4392 "Highlight the region between point and the character under the mouse\n\
4393 selected frame.")
4394 (event)
4395 register Lisp_Object event;
4397 register int x0, y0, x1, y1;
4398 register struct frame *f = selected_frame;
4399 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
4400 register int p1, p2;
4402 CHECK_CONS (event, 0);
4404 BLOCK_INPUT;
4405 x0 = XINT (Fcar (Fcar (event)));
4406 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4408 /* If the mouse is past the end of the line, don't that area. */
4409 /* ReWrite this... */
4411 /* Where the cursor is. */
4412 x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
4413 y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
4415 if (y1 > y0) /* point below mouse */
4416 outline_region (f, f->output_data.x->cursor_gc,
4417 x0, y0, x1, y1);
4418 else if (y1 < y0) /* point above mouse */
4419 outline_region (f, f->output_data.x->cursor_gc,
4420 x1, y1, x0, y0);
4421 else /* same line: draw horizontal rectangle */
4423 if (x1 > x0)
4424 x_rectangle (f, f->output_data.x->cursor_gc,
4425 x0, y0, (x1 - x0 + 1), 1);
4426 else if (x1 < x0)
4427 x_rectangle (f, f->output_data.x->cursor_gc,
4428 x1, y1, (x0 - x1 + 1), 1);
4431 XFlush (FRAME_X_DISPLAY (f));
4432 UNBLOCK_INPUT;
4434 return Qnil;
4437 DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
4438 "Erase any highlighting of the region between point and the character\n\
4439 at X, Y on the selected frame.")
4440 (event)
4441 register Lisp_Object event;
4443 register int x0, y0, x1, y1;
4444 register struct frame *f = selected_frame;
4445 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
4447 BLOCK_INPUT;
4448 x0 = XINT (Fcar (Fcar (event)));
4449 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4450 x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
4451 y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
4453 if (y1 > y0) /* point below mouse */
4454 outline_region (f, f->output_data.x->reverse_gc,
4455 x0, y0, x1, y1);
4456 else if (y1 < y0) /* point above mouse */
4457 outline_region (f, f->output_data.x->reverse_gc,
4458 x1, y1, x0, y0);
4459 else /* same line: draw horizontal rectangle */
4461 if (x1 > x0)
4462 x_rectangle (f, f->output_data.x->reverse_gc,
4463 x0, y0, (x1 - x0 + 1), 1);
4464 else if (x1 < x0)
4465 x_rectangle (f, f->output_data.x->reverse_gc,
4466 x1, y1, (x0 - x1 + 1), 1);
4468 UNBLOCK_INPUT;
4470 return Qnil;
4473 #if 0
4474 int contour_begin_x, contour_begin_y;
4475 int contour_end_x, contour_end_y;
4476 int contour_npoints;
4478 /* Clip the top part of the contour lines down (and including) line Y_POS.
4479 If X_POS is in the middle (rather than at the end) of the line, drop
4480 down a line at that character. */
4482 static void
4483 clip_contour_top (y_pos, x_pos)
4485 register XPoint *begin = contour_lines[y_pos].top_left;
4486 register XPoint *end;
4487 register int npoints;
4488 register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
4490 if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
4492 end = contour_lines[y_pos].top_right;
4493 npoints = (end - begin + 1);
4494 XDrawLines (x_current_display, contour_window,
4495 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4497 bcopy (end, begin + 1, contour_last_point - end + 1);
4498 contour_last_point -= (npoints - 2);
4499 XDrawLines (x_current_display, contour_window,
4500 contour_erase_gc, begin, 2, CoordModeOrigin);
4501 XFlush (x_current_display);
4503 /* Now, update contour_lines structure. */
4505 /* ______. */
4506 else /* |________*/
4508 register XPoint *p = begin + 1;
4509 end = contour_lines[y_pos].bottom_right;
4510 npoints = (end - begin + 1);
4511 XDrawLines (x_current_display, contour_window,
4512 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4514 p->y = begin->y;
4515 p->x = ibw + (font_w * (x_pos + 1));
4516 p++;
4517 p->y = begin->y + font_h;
4518 p->x = (p - 1)->x;
4519 bcopy (end, begin + 3, contour_last_point - end + 1);
4520 contour_last_point -= (npoints - 5);
4521 XDrawLines (x_current_display, contour_window,
4522 contour_erase_gc, begin, 4, CoordModeOrigin);
4523 XFlush (x_current_display);
4525 /* Now, update contour_lines structure. */
4529 /* Erase the top horizontal lines of the contour, and then extend
4530 the contour upwards. */
4532 static void
4533 extend_contour_top (line)
4537 static void
4538 clip_contour_bottom (x_pos, y_pos)
4539 int x_pos, y_pos;
4543 static void
4544 extend_contour_bottom (x_pos, y_pos)
4548 DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
4550 (event)
4551 Lisp_Object event;
4553 register struct frame *f = selected_frame;
4554 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
4555 register int point_x = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
4556 register int point_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
4557 register int mouse_below_point;
4558 register Lisp_Object obj;
4559 register int x_contour_x, x_contour_y;
4561 x_contour_x = x_mouse_x;
4562 x_contour_y = x_mouse_y;
4563 if (x_contour_y > point_y || (x_contour_y == point_y
4564 && x_contour_x > point_x))
4566 mouse_below_point = 1;
4567 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4568 x_contour_x, x_contour_y);
4570 else
4572 mouse_below_point = 0;
4573 outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
4574 point_x, point_y);
4577 while (1)
4579 obj = read_char (-1, 0, 0, Qnil, 0);
4580 if (!CONSP (obj))
4581 break;
4583 if (mouse_below_point)
4585 if (x_mouse_y <= point_y) /* Flipped. */
4587 mouse_below_point = 0;
4589 outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
4590 x_contour_x, x_contour_y);
4591 outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
4592 point_x, point_y);
4594 else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
4596 clip_contour_bottom (x_mouse_y);
4598 else if (x_mouse_y > x_contour_y) /* Bottom extended. */
4600 extend_bottom_contour (x_mouse_y);
4603 x_contour_x = x_mouse_x;
4604 x_contour_y = x_mouse_y;
4606 else /* mouse above or same line as point */
4608 if (x_mouse_y >= point_y) /* Flipped. */
4610 mouse_below_point = 1;
4612 outline_region (f, f->output_data.x->reverse_gc,
4613 x_contour_x, x_contour_y, point_x, point_y);
4614 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4615 x_mouse_x, x_mouse_y);
4617 else if (x_mouse_y > x_contour_y) /* Top clipped. */
4619 clip_contour_top (x_mouse_y);
4621 else if (x_mouse_y < x_contour_y) /* Top extended. */
4623 extend_contour_top (x_mouse_y);
4628 unread_command_event = obj;
4629 if (mouse_below_point)
4631 contour_begin_x = point_x;
4632 contour_begin_y = point_y;
4633 contour_end_x = x_contour_x;
4634 contour_end_y = x_contour_y;
4636 else
4638 contour_begin_x = x_contour_x;
4639 contour_begin_y = x_contour_y;
4640 contour_end_x = point_x;
4641 contour_end_y = point_y;
4644 #endif
4646 DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
4648 (event)
4649 Lisp_Object event;
4651 register Lisp_Object obj;
4652 struct frame *f = selected_frame;
4653 register struct window *w = XWINDOW (selected_window);
4654 register GC line_gc = f->output_data.x->cursor_gc;
4655 register GC erase_gc = f->output_data.x->reverse_gc;
4656 #if 0
4657 char dash_list[] = {6, 4, 6, 4};
4658 int dashes = 4;
4659 XGCValues gc_values;
4660 #endif
4661 register int previous_y;
4662 register int line = (x_mouse_y + 1) * f->output_data.x->line_height
4663 + f->output_data.x->internal_border_width;
4664 register int left = f->output_data.x->internal_border_width
4665 + (WINDOW_LEFT_MARGIN (w)
4666 * FONT_WIDTH (f->output_data.x->font));
4667 register int right = left + (w->width
4668 * FONT_WIDTH (f->output_data.x->font))
4669 - f->output_data.x->internal_border_width;
4671 #if 0
4672 BLOCK_INPUT;
4673 gc_values.foreground = f->output_data.x->cursor_pixel;
4674 gc_values.background = f->output_data.x->background_pixel;
4675 gc_values.line_width = 1;
4676 gc_values.line_style = LineOnOffDash;
4677 gc_values.cap_style = CapRound;
4678 gc_values.join_style = JoinRound;
4680 line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4681 GCLineStyle | GCJoinStyle | GCCapStyle
4682 | GCLineWidth | GCForeground | GCBackground,
4683 &gc_values);
4684 XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
4685 gc_values.foreground = f->output_data.x->background_pixel;
4686 gc_values.background = f->output_data.x->foreground_pixel;
4687 erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4688 GCLineStyle | GCJoinStyle | GCCapStyle
4689 | GCLineWidth | GCForeground | GCBackground,
4690 &gc_values);
4691 XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
4692 UNBLOCK_INPUT;
4693 #endif
4695 while (1)
4697 BLOCK_INPUT;
4698 if (x_mouse_y >= XINT (w->top)
4699 && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
4701 previous_y = x_mouse_y;
4702 line = (x_mouse_y + 1) * f->output_data.x->line_height
4703 + f->output_data.x->internal_border_width;
4704 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4705 line_gc, left, line, right, line);
4707 XFlush (FRAME_X_DISPLAY (f));
4708 UNBLOCK_INPUT;
4712 obj = read_char (-1, 0, 0, Qnil, 0);
4713 if (!CONSP (obj)
4714 || (! EQ (Fcar (Fcdr (Fcdr (obj))),
4715 Qvertical_scroll_bar))
4716 || x_mouse_grabbed)
4718 BLOCK_INPUT;
4719 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4720 erase_gc, left, line, right, line);
4721 unread_command_event = obj;
4722 #if 0
4723 XFreeGC (FRAME_X_DISPLAY (f), line_gc);
4724 XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
4725 #endif
4726 UNBLOCK_INPUT;
4727 return Qnil;
4730 while (x_mouse_y == previous_y);
4732 BLOCK_INPUT;
4733 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4734 erase_gc, left, line, right, line);
4735 UNBLOCK_INPUT;
4738 #endif
4740 #if 0
4741 /* These keep track of the rectangle following the pointer. */
4742 int mouse_track_top, mouse_track_left, mouse_track_width;
4744 /* Offset in buffer of character under the pointer, or 0. */
4745 int mouse_buffer_offset;
4747 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
4748 "Track the pointer.")
4751 static Cursor current_pointer_shape;
4752 FRAME_PTR f = x_mouse_frame;
4754 BLOCK_INPUT;
4755 if (EQ (Vmouse_frame_part, Qtext_part)
4756 && (current_pointer_shape != f->output_data.x->nontext_cursor))
4758 unsigned char c;
4759 struct buffer *buf;
4761 current_pointer_shape = f->output_data.x->nontext_cursor;
4762 XDefineCursor (FRAME_X_DISPLAY (f),
4763 FRAME_X_WINDOW (f),
4764 current_pointer_shape);
4766 buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
4767 c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
4769 else if (EQ (Vmouse_frame_part, Qmodeline_part)
4770 && (current_pointer_shape != f->output_data.x->modeline_cursor))
4772 current_pointer_shape = f->output_data.x->modeline_cursor;
4773 XDefineCursor (FRAME_X_DISPLAY (f),
4774 FRAME_X_WINDOW (f),
4775 current_pointer_shape);
4778 XFlush (FRAME_X_DISPLAY (f));
4779 UNBLOCK_INPUT;
4781 #endif
4783 #if 0
4784 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
4785 "Draw rectangle around character under mouse pointer, if there is one.")
4786 (event)
4787 Lisp_Object event;
4789 struct window *w = XWINDOW (Vmouse_window);
4790 struct frame *f = XFRAME (WINDOW_FRAME (w));
4791 struct buffer *b = XBUFFER (w->buffer);
4792 Lisp_Object obj;
4794 if (! EQ (Vmouse_window, selected_window))
4795 return Qnil;
4797 if (EQ (event, Qnil))
4799 int x, y;
4801 x_read_mouse_position (selected_frame, &x, &y);
4804 BLOCK_INPUT;
4805 mouse_track_width = 0;
4806 mouse_track_left = mouse_track_top = -1;
4810 if ((x_mouse_x != mouse_track_left
4811 && (x_mouse_x < mouse_track_left
4812 || x_mouse_x > (mouse_track_left + mouse_track_width)))
4813 || x_mouse_y != mouse_track_top)
4815 int hp = 0; /* Horizontal position */
4816 int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
4817 int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
4818 int tab_width = XINT (b->tab_width);
4819 int ctl_arrow_p = !NILP (b->ctl_arrow);
4820 unsigned char c;
4821 int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
4822 int in_mode_line = 0;
4824 if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
4825 break;
4827 /* Erase previous rectangle. */
4828 if (mouse_track_width)
4830 x_rectangle (f, f->output_data.x->reverse_gc,
4831 mouse_track_left, mouse_track_top,
4832 mouse_track_width, 1);
4834 if ((mouse_track_left == f->phys_cursor_x
4835 || mouse_track_left == f->phys_cursor_x - 1)
4836 && mouse_track_top == f->phys_cursor_y)
4838 x_display_cursor (f, 1);
4842 mouse_track_left = x_mouse_x;
4843 mouse_track_top = x_mouse_y;
4844 mouse_track_width = 0;
4846 if (mouse_track_left > len) /* Past the end of line. */
4847 goto draw_or_not;
4849 if (mouse_track_top == mode_line_vpos)
4851 in_mode_line = 1;
4852 goto draw_or_not;
4855 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
4858 c = FETCH_BYTE (p);
4859 if (len == f->width && hp == len - 1 && c != '\n')
4860 goto draw_or_not;
4862 switch (c)
4864 case '\t':
4865 mouse_track_width = tab_width - (hp % tab_width);
4866 p++;
4867 hp += mouse_track_width;
4868 if (hp > x_mouse_x)
4870 mouse_track_left = hp - mouse_track_width;
4871 goto draw_or_not;
4873 continue;
4875 case '\n':
4876 mouse_track_width = -1;
4877 goto draw_or_not;
4879 default:
4880 if (ctl_arrow_p && (c < 040 || c == 0177))
4882 if (p > ZV)
4883 goto draw_or_not;
4885 mouse_track_width = 2;
4886 p++;
4887 hp +=2;
4888 if (hp > x_mouse_x)
4890 mouse_track_left = hp - mouse_track_width;
4891 goto draw_or_not;
4894 else
4896 mouse_track_width = 1;
4897 p++;
4898 hp++;
4900 continue;
4903 while (hp <= x_mouse_x);
4905 draw_or_not:
4906 if (mouse_track_width) /* Over text; use text pointer shape. */
4908 XDefineCursor (FRAME_X_DISPLAY (f),
4909 FRAME_X_WINDOW (f),
4910 f->output_data.x->text_cursor);
4911 x_rectangle (f, f->output_data.x->cursor_gc,
4912 mouse_track_left, mouse_track_top,
4913 mouse_track_width, 1);
4915 else if (in_mode_line)
4916 XDefineCursor (FRAME_X_DISPLAY (f),
4917 FRAME_X_WINDOW (f),
4918 f->output_data.x->modeline_cursor);
4919 else
4920 XDefineCursor (FRAME_X_DISPLAY (f),
4921 FRAME_X_WINDOW (f),
4922 f->output_data.x->nontext_cursor);
4925 XFlush (FRAME_X_DISPLAY (f));
4926 UNBLOCK_INPUT;
4928 obj = read_char (-1, 0, 0, Qnil, 0);
4929 BLOCK_INPUT;
4931 while (CONSP (obj) /* Mouse event */
4932 && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
4933 && EQ (Vmouse_depressed, Qnil) /* Only motion events */
4934 && EQ (Vmouse_window, selected_window) /* In this window */
4935 && x_mouse_frame);
4937 unread_command_event = obj;
4939 if (mouse_track_width)
4941 x_rectangle (f, f->output_data.x->reverse_gc,
4942 mouse_track_left, mouse_track_top,
4943 mouse_track_width, 1);
4944 mouse_track_width = 0;
4945 if ((mouse_track_left == f->phys_cursor_x
4946 || mouse_track_left - 1 == f->phys_cursor_x)
4947 && mouse_track_top == f->phys_cursor_y)
4949 x_display_cursor (f, 1);
4952 XDefineCursor (FRAME_X_DISPLAY (f),
4953 FRAME_X_WINDOW (f),
4954 f->output_data.x->nontext_cursor);
4955 XFlush (FRAME_X_DISPLAY (f));
4956 UNBLOCK_INPUT;
4958 return Qnil;
4960 #endif
4962 #if 0
4963 #include "glyphs.h"
4965 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
4966 on the frame F at position X, Y. */
4968 x_draw_pixmap (f, x, y, image_data, width, height)
4969 struct frame *f;
4970 int x, y, width, height;
4971 char *image_data;
4973 Pixmap image;
4975 image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
4976 FRAME_X_WINDOW (f), image_data,
4977 width, height);
4978 XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
4979 f->output_data.x->normal_gc, 0, 0, width, height, x, y);
4981 #endif
4983 #if 0 /* I'm told these functions are superfluous
4984 given the ability to bind function keys. */
4986 #ifdef HAVE_X11
4987 DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
4988 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
4989 KEYSYM is a string which conforms to the X keysym definitions found\n\
4990 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
4991 list of strings specifying modifier keys such as Control_L, which must\n\
4992 also be depressed for NEWSTRING to appear.")
4993 (x_keysym, modifiers, newstring)
4994 register Lisp_Object x_keysym;
4995 register Lisp_Object modifiers;
4996 register Lisp_Object newstring;
4998 char *rawstring;
4999 register KeySym keysym;
5000 KeySym modifier_list[16];
5002 check_x ();
5003 CHECK_STRING (x_keysym, 1);
5004 CHECK_STRING (newstring, 3);
5006 keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
5007 if (keysym == NoSymbol)
5008 error ("Keysym does not exist");
5010 if (NILP (modifiers))
5011 XRebindKeysym (x_current_display, keysym, modifier_list, 0,
5012 XSTRING (newstring)->data,
5013 STRING_BYTES (XSTRING (newstring)));
5014 else
5016 register Lisp_Object rest, mod;
5017 register int i = 0;
5019 for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
5021 if (i == 16)
5022 error ("Can't have more than 16 modifiers");
5024 mod = Fcar (rest);
5025 CHECK_STRING (mod, 3);
5026 modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
5027 #ifndef HAVE_X11R5
5028 if (modifier_list[i] == NoSymbol
5029 || !(IsModifierKey (modifier_list[i])
5030 || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
5031 || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
5032 #else
5033 if (modifier_list[i] == NoSymbol
5034 || !IsModifierKey (modifier_list[i]))
5035 #endif
5036 error ("Element is not a modifier keysym");
5037 i++;
5040 XRebindKeysym (x_current_display, keysym, modifier_list, i,
5041 XSTRING (newstring)->data,
5042 STRING_BYTES (XSTRING (newstring)));
5045 return Qnil;
5048 DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
5049 "Rebind KEYCODE to list of strings STRINGS.\n\
5050 STRINGS should be a list of 16 elements, one for each shift combination.\n\
5051 nil as element means don't change.\n\
5052 See the documentation of `x-rebind-key' for more information.")
5053 (keycode, strings)
5054 register Lisp_Object keycode;
5055 register Lisp_Object strings;
5057 register Lisp_Object item;
5058 register unsigned char *rawstring;
5059 KeySym rawkey, modifier[1];
5060 int strsize;
5061 register unsigned i;
5063 check_x ();
5064 CHECK_NUMBER (keycode, 1);
5065 CHECK_CONS (strings, 2);
5066 rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
5067 for (i = 0; i <= 15; strings = Fcdr (strings), i++)
5069 item = Fcar (strings);
5070 if (!NILP (item))
5072 CHECK_STRING (item, 2);
5073 strsize = STRING_BYTES (XSTRING (item));
5074 rawstring = (unsigned char *) xmalloc (strsize);
5075 bcopy (XSTRING (item)->data, rawstring, strsize);
5076 modifier[1] = 1 << i;
5077 XRebindKeysym (x_current_display, rawkey, modifier, 1,
5078 rawstring, strsize);
5081 return Qnil;
5083 #endif /* HAVE_X11 */
5084 #endif /* 0 */
5086 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5088 XScreenNumberOfScreen (scr)
5089 register Screen *scr;
5091 register Display *dpy;
5092 register Screen *dpyscr;
5093 register int i;
5095 dpy = scr->display;
5096 dpyscr = dpy->screens;
5098 for (i = 0; i < dpy->nscreens; i++, dpyscr++)
5099 if (scr == dpyscr)
5100 return i;
5102 return -1;
5104 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5106 Visual *
5107 select_visual (dpy, screen, depth)
5108 Display *dpy;
5109 Screen *screen;
5110 unsigned int *depth;
5112 Visual *v;
5113 XVisualInfo *vinfo, vinfo_template;
5114 int n_visuals;
5116 v = DefaultVisualOfScreen (screen);
5118 #ifdef HAVE_X11R4
5119 vinfo_template.visualid = XVisualIDFromVisual (v);
5120 #else
5121 vinfo_template.visualid = v->visualid;
5122 #endif
5124 vinfo_template.screen = XScreenNumberOfScreen (screen);
5126 vinfo = XGetVisualInfo (dpy,
5127 VisualIDMask | VisualScreenMask, &vinfo_template,
5128 &n_visuals);
5129 if (n_visuals != 1)
5130 fatal ("Can't get proper X visual info");
5132 if ((1 << vinfo->depth) == vinfo->colormap_size)
5133 *depth = vinfo->depth;
5134 else
5136 int i = 0;
5137 int n = vinfo->colormap_size - 1;
5138 while (n)
5140 n = n >> 1;
5141 i++;
5143 *depth = i;
5146 XFree ((char *) vinfo);
5147 return v;
5150 /* Return the X display structure for the display named NAME.
5151 Open a new connection if necessary. */
5153 struct x_display_info *
5154 x_display_info_for_name (name)
5155 Lisp_Object name;
5157 Lisp_Object names;
5158 struct x_display_info *dpyinfo;
5160 CHECK_STRING (name, 0);
5162 if (! EQ (Vwindow_system, intern ("x")))
5163 error ("Not using X Windows");
5165 for (dpyinfo = x_display_list, names = x_display_name_list;
5166 dpyinfo;
5167 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
5169 Lisp_Object tem;
5170 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
5171 if (!NILP (tem))
5172 return dpyinfo;
5175 /* Use this general default value to start with. */
5176 Vx_resource_name = Vinvocation_name;
5178 validate_x_resource_name ();
5180 dpyinfo = x_term_init (name, (unsigned char *)0,
5181 (char *) XSTRING (Vx_resource_name)->data);
5183 if (dpyinfo == 0)
5184 error ("Cannot connect to X server %s", XSTRING (name)->data);
5186 x_in_use = 1;
5187 XSETFASTINT (Vwindow_system_version, 11);
5189 return dpyinfo;
5192 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5193 1, 3, 0, "Open a connection to an X server.\n\
5194 DISPLAY is the name of the display to connect to.\n\
5195 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5196 If the optional third arg MUST-SUCCEED is non-nil,\n\
5197 terminate Emacs if we can't open the connection.")
5198 (display, xrm_string, must_succeed)
5199 Lisp_Object display, xrm_string, must_succeed;
5201 unsigned char *xrm_option;
5202 struct x_display_info *dpyinfo;
5204 CHECK_STRING (display, 0);
5205 if (! NILP (xrm_string))
5206 CHECK_STRING (xrm_string, 1);
5208 if (! EQ (Vwindow_system, intern ("x")))
5209 error ("Not using X Windows");
5211 if (! NILP (xrm_string))
5212 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5213 else
5214 xrm_option = (unsigned char *) 0;
5216 validate_x_resource_name ();
5218 /* This is what opens the connection and sets x_current_display.
5219 This also initializes many symbols, such as those used for input. */
5220 dpyinfo = x_term_init (display, xrm_option,
5221 (char *) XSTRING (Vx_resource_name)->data);
5223 if (dpyinfo == 0)
5225 if (!NILP (must_succeed))
5226 fatal ("Cannot connect to X server %s.\n\
5227 Check the DISPLAY environment variable or use `-d'.\n\
5228 Also use the `xhost' program to verify that it is set to permit\n\
5229 connections from your machine.\n",
5230 XSTRING (display)->data);
5231 else
5232 error ("Cannot connect to X server %s", XSTRING (display)->data);
5235 x_in_use = 1;
5237 XSETFASTINT (Vwindow_system_version, 11);
5238 return Qnil;
5241 DEFUN ("x-close-connection", Fx_close_connection,
5242 Sx_close_connection, 1, 1, 0,
5243 "Close the connection to DISPLAY's X server.\n\
5244 For DISPLAY, specify either a frame or a display name (a string).\n\
5245 If DISPLAY is nil, that stands for the selected frame's display.")
5246 (display)
5247 Lisp_Object display;
5249 struct x_display_info *dpyinfo = check_x_display_info (display);
5250 int i;
5252 if (dpyinfo->reference_count > 0)
5253 error ("Display still has frames on it");
5255 BLOCK_INPUT;
5256 /* Free the fonts in the font table. */
5257 for (i = 0; i < dpyinfo->n_fonts; i++)
5258 if (dpyinfo->font_table[i].name)
5260 xfree (dpyinfo->font_table[i].name);
5261 /* Don't free the full_name string;
5262 it is always shared with something else. */
5263 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5266 x_destroy_all_bitmaps (dpyinfo);
5267 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5269 #ifdef USE_X_TOOLKIT
5270 XtCloseDisplay (dpyinfo->display);
5271 #else
5272 XCloseDisplay (dpyinfo->display);
5273 #endif
5275 x_delete_display (dpyinfo);
5276 UNBLOCK_INPUT;
5278 return Qnil;
5281 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5282 "Return the list of display names that Emacs has connections to.")
5285 Lisp_Object tail, result;
5287 result = Qnil;
5288 for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
5289 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
5291 return result;
5294 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5295 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5296 If ON is nil, allow buffering of requests.\n\
5297 Turning on synchronization prohibits the Xlib routines from buffering\n\
5298 requests and seriously degrades performance, but makes debugging much\n\
5299 easier.\n\
5300 The optional second argument DISPLAY specifies which display to act on.\n\
5301 DISPLAY should be either a frame or a display name (a string).\n\
5302 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5303 (on, display)
5304 Lisp_Object display, on;
5306 struct x_display_info *dpyinfo = check_x_display_info (display);
5308 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5310 return Qnil;
5313 /* Wait for responses to all X commands issued so far for frame F. */
5315 void
5316 x_sync (f)
5317 FRAME_PTR f;
5319 BLOCK_INPUT;
5320 XSync (FRAME_X_DISPLAY (f), False);
5321 UNBLOCK_INPUT;
5325 /***********************************************************************
5326 Image types
5327 ***********************************************************************/
5329 /* Value is the number of elements of vector VECTOR. */
5331 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5333 /* List of supported image types. Use define_image_type to add new
5334 types. Use lookup_image_type to find a type for a given symbol. */
5336 static struct image_type *image_types;
5338 /* A list of symbols, one for each supported image type. */
5340 Lisp_Object Vimage_types;
5342 /* The symbol `image' which is the car of the lists used to represent
5343 images in Lisp. */
5345 extern Lisp_Object Qimage;
5347 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5349 Lisp_Object Qxbm;
5351 /* Keywords. */
5353 Lisp_Object QCtype, QCdata, QCfile, QCascent, QCmargin, QCrelief;
5354 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground;
5355 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
5356 extern Lisp_Object QCimage;
5358 /* Other symbols. */
5360 Lisp_Object Qlaplace;
5362 /* Time in seconds after which images should be removed from the cache
5363 if not displayed. */
5365 Lisp_Object Vimage_eviction_seconds;
5367 /* Function prototypes. */
5369 static void define_image_type P_ ((struct image_type *type));
5370 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5371 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5372 static void x_laplace P_ ((struct frame *, struct image *));
5373 static int x_build_heuristic_mask P_ ((struct frame *, Lisp_Object,
5374 struct image *, Lisp_Object));
5377 /* Define a new image type from TYPE. This adds a copy of TYPE to
5378 image_types and adds the symbol *TYPE->type to Vimage_types. */
5380 static void
5381 define_image_type (type)
5382 struct image_type *type;
5384 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5385 The initialized data segment is read-only. */
5386 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5387 bcopy (type, p, sizeof *p);
5388 p->next = image_types;
5389 image_types = p;
5390 Vimage_types = Fcons (*p->type, Vimage_types);
5394 /* Look up image type SYMBOL, and return a pointer to its image_type
5395 structure. Value is null if SYMBOL is not a known image type. */
5397 static INLINE struct image_type *
5398 lookup_image_type (symbol)
5399 Lisp_Object symbol;
5401 struct image_type *type;
5403 for (type = image_types; type; type = type->next)
5404 if (EQ (symbol, *type->type))
5405 break;
5407 return type;
5411 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5412 valid image specification is a list whose car is the symbol
5413 `image', and whose rest is a property list. The property list must
5414 contain a value for key `:type'. That value must be the name of a
5415 supported image type. The rest of the property list depends on the
5416 image type. */
5419 valid_image_p (object)
5420 Lisp_Object object;
5422 int valid_p = 0;
5424 if (CONSP (object) && EQ (XCAR (object), Qimage))
5426 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
5427 struct image_type *type = lookup_image_type (symbol);
5429 if (type)
5430 valid_p = type->valid_p (object);
5433 return valid_p;
5437 /* Display an error message with format string FORMAT and argument
5438 ARG. Signaling an error, e.g. when an image cannot be loaded,
5439 is not a good idea because this would interrupt redisplay, and
5440 the error message display would lead to another redisplay. This
5441 function therefore simply displays a message. */
5443 static void
5444 image_error (format, arg1, arg2)
5445 char *format;
5446 Lisp_Object arg1, arg2;
5448 Lisp_Object args[3];
5450 args[0] = build_string (format);
5451 args[1] = arg1;
5452 args[2] = arg2;
5453 Fmessage (make_number (DIM (args)), args);
5458 /***********************************************************************
5459 Image specifications
5460 ***********************************************************************/
5462 enum image_value_type
5464 IMAGE_DONT_CHECK_VALUE_TYPE,
5465 IMAGE_STRING_VALUE,
5466 IMAGE_SYMBOL_VALUE,
5467 IMAGE_POSITIVE_INTEGER_VALUE,
5468 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5469 IMAGE_INTEGER_VALUE,
5470 IMAGE_FUNCTION_VALUE,
5471 IMAGE_NUMBER_VALUE,
5472 IMAGE_BOOL_VALUE
5475 /* Structure used when parsing image specifications. */
5477 struct image_keyword
5479 /* Name of keyword. */
5480 char *name;
5482 /* The type of value allowed. */
5483 enum image_value_type type;
5485 /* Non-zero means key must be present. */
5486 int mandatory_p;
5488 /* Used to recognize duplicate keywords in a property list. */
5489 int count;
5491 /* The value that was found. */
5492 Lisp_Object value;
5496 static int parse_image_spec P_ ((Lisp_Object spec,
5497 struct image_keyword *keywords,
5498 int nkeywords, Lisp_Object type,
5499 int allow_other_keys_p));
5500 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5503 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5504 has the format (image KEYWORD VALUE ...). One of the keyword/
5505 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5506 image_keywords structures of size NKEYWORDS describing other
5507 allowed keyword/value pairs. ALLOW_OTHER_KEYS_P non-zero means
5508 allow KEYWORD/VALUE pairs other than those described by KEYWORDS
5509 without checking them. Value is non-zero if SPEC is valid. */
5511 static int
5512 parse_image_spec (spec, keywords, nkeywords, type, allow_other_keys_p)
5513 Lisp_Object spec;
5514 struct image_keyword *keywords;
5515 int nkeywords;
5516 Lisp_Object type;
5517 int allow_other_keys_p;
5519 int i;
5520 Lisp_Object plist;
5522 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5523 return 0;
5525 plist = XCDR (spec);
5526 while (CONSP (plist))
5528 Lisp_Object key, value;
5530 /* First element of a pair must be a symbol. */
5531 key = XCAR (plist);
5532 plist = XCDR (plist);
5533 if (!SYMBOLP (key))
5534 return 0;
5536 /* There must follow a value. */
5537 if (!CONSP (plist))
5538 return 0;
5539 value = XCAR (plist);
5540 plist = XCDR (plist);
5542 /* Find key in KEYWORDS. Error if not found. */
5543 for (i = 0; i < nkeywords; ++i)
5544 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5545 break;
5547 if (i == nkeywords)
5549 if (!allow_other_keys_p)
5550 return 0;
5551 continue;
5554 /* Record that we recognized the keyword. If a keywords
5555 was found more than once, it's an error. */
5556 keywords[i].value = value;
5557 ++keywords[i].count;
5559 if (keywords[i].count > 1)
5560 return 0;
5562 /* Check type of value against allowed type. */
5563 switch (keywords[i].type)
5565 case IMAGE_STRING_VALUE:
5566 if (!STRINGP (value))
5567 return 0;
5568 break;
5570 case IMAGE_SYMBOL_VALUE:
5571 if (!SYMBOLP (value))
5572 return 0;
5573 break;
5575 case IMAGE_POSITIVE_INTEGER_VALUE:
5576 if (!INTEGERP (value) || XINT (value) <= 0)
5577 return 0;
5578 break;
5580 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5581 if (!INTEGERP (value) || XINT (value) < 0)
5582 return 0;
5583 break;
5585 case IMAGE_DONT_CHECK_VALUE_TYPE:
5586 break;
5588 case IMAGE_FUNCTION_VALUE:
5589 value = indirect_function (value);
5590 if (SUBRP (value)
5591 || COMPILEDP (value)
5592 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5593 break;
5594 return 0;
5596 case IMAGE_NUMBER_VALUE:
5597 if (!INTEGERP (value) && !FLOATP (value))
5598 return 0;
5599 break;
5601 case IMAGE_INTEGER_VALUE:
5602 if (!INTEGERP (value))
5603 return 0;
5604 break;
5606 case IMAGE_BOOL_VALUE:
5607 if (!NILP (value) && !EQ (value, Qt))
5608 return 0;
5609 break;
5611 default:
5612 abort ();
5613 break;
5616 if (EQ (key, QCtype) && !EQ (type, value))
5617 return 0;
5620 /* Check that all mandatory fields are present. */
5621 for (i = 0; i < nkeywords; ++i)
5622 if (keywords[i].mandatory_p && keywords[i].count == 0)
5623 return 0;
5625 return NILP (plist);
5629 /* Return the value of KEY in image specification SPEC. Value is nil
5630 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5631 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5633 static Lisp_Object
5634 image_spec_value (spec, key, found)
5635 Lisp_Object spec, key;
5636 int *found;
5638 Lisp_Object tail;
5640 xassert (valid_image_p (spec));
5642 for (tail = XCDR (spec);
5643 CONSP (tail) && CONSP (XCDR (tail));
5644 tail = XCDR (XCDR (tail)))
5646 if (EQ (XCAR (tail), key))
5648 if (found)
5649 *found = 1;
5650 return XCAR (XCDR (tail));
5654 if (found)
5655 *found = 0;
5656 return Qnil;
5662 /***********************************************************************
5663 Image type independent image structures
5664 ***********************************************************************/
5666 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5667 static void free_image P_ ((struct frame *f, struct image *img));
5670 /* Allocate and return a new image structure for image specification
5671 SPEC. SPEC has a hash value of HASH. */
5673 static struct image *
5674 make_image (spec, hash)
5675 Lisp_Object spec;
5676 unsigned hash;
5678 struct image *img = (struct image *) xmalloc (sizeof *img);
5680 xassert (valid_image_p (spec));
5681 bzero (img, sizeof *img);
5682 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5683 xassert (img->type != NULL);
5684 img->spec = spec;
5685 img->data.lisp_val = Qnil;
5686 img->ascent = DEFAULT_IMAGE_ASCENT;
5687 img->hash = hash;
5688 return img;
5692 /* Free image IMG which was used on frame F, including its resources. */
5694 static void
5695 free_image (f, img)
5696 struct frame *f;
5697 struct image *img;
5699 if (img)
5701 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5703 /* Remove IMG from the hash table of its cache. */
5704 if (img->prev)
5705 img->prev->next = img->next;
5706 else
5707 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5709 if (img->next)
5710 img->next->prev = img->prev;
5712 c->images[img->id] = NULL;
5714 /* Free resources, then free IMG. */
5715 img->type->free (f, img);
5716 xfree (img);
5721 /* Prepare image IMG for display on frame F. Must be called before
5722 drawing an image. */
5724 void
5725 prepare_image_for_display (f, img)
5726 struct frame *f;
5727 struct image *img;
5729 EMACS_TIME t;
5731 /* We're about to display IMG, so set its timestamp to `now'. */
5732 EMACS_GET_TIME (t);
5733 img->timestamp = EMACS_SECS (t);
5735 /* If IMG doesn't have a pixmap yet, load it now, using the image
5736 type dependent loader function. */
5737 if (img->pixmap == 0)
5738 img->type->load (f, img);
5743 /***********************************************************************
5744 Helper functions for X image types
5745 ***********************************************************************/
5747 static void x_clear_image P_ ((struct frame *f, struct image *img));
5748 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5749 struct image *img,
5750 Lisp_Object color_name,
5751 unsigned long dflt));
5753 /* Free X resources of image IMG which is used on frame F. */
5755 static void
5756 x_clear_image (f, img)
5757 struct frame *f;
5758 struct image *img;
5760 if (img->pixmap)
5762 BLOCK_INPUT;
5763 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5764 img->pixmap = 0;
5765 UNBLOCK_INPUT;
5768 if (img->ncolors)
5770 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
5772 /* If display has an immutable color map, freeing colors is not
5773 necessary and some servers don't allow it. So don't do it. */
5774 if (class != StaticColor
5775 && class != StaticGray
5776 && class != TrueColor)
5778 Colormap cmap;
5779 BLOCK_INPUT;
5780 cmap = DefaultColormapOfScreen (FRAME_X_DISPLAY_INFO (f)->screen);
5781 XFreeColors (FRAME_X_DISPLAY (f), cmap, img->colors,
5782 img->ncolors, 0);
5783 UNBLOCK_INPUT;
5786 xfree (img->colors);
5787 img->colors = NULL;
5788 img->ncolors = 0;
5793 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5794 cannot be allocated, use DFLT. Add a newly allocated color to
5795 IMG->colors, so that it can be freed again. Value is the pixel
5796 color. */
5798 static unsigned long
5799 x_alloc_image_color (f, img, color_name, dflt)
5800 struct frame *f;
5801 struct image *img;
5802 Lisp_Object color_name;
5803 unsigned long dflt;
5805 XColor color;
5806 unsigned long result;
5808 xassert (STRINGP (color_name));
5810 if (defined_color (f, XSTRING (color_name)->data, &color, 1))
5812 /* This isn't called frequently so we get away with simply
5813 reallocating the color vector to the needed size, here. */
5814 ++img->ncolors;
5815 img->colors =
5816 (unsigned long *) xrealloc (img->colors,
5817 img->ncolors * sizeof *img->colors);
5818 img->colors[img->ncolors - 1] = color.pixel;
5819 result = color.pixel;
5821 else
5822 result = dflt;
5824 return result;
5829 /***********************************************************************
5830 Image Cache
5831 ***********************************************************************/
5833 static void cache_image P_ ((struct frame *f, struct image *img));
5836 /* Return a new, initialized image cache that is allocated from the
5837 heap. Call free_image_cache to free an image cache. */
5839 struct image_cache *
5840 make_image_cache ()
5842 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5843 int size;
5845 bzero (c, sizeof *c);
5846 c->size = 50;
5847 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5848 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5849 c->buckets = (struct image **) xmalloc (size);
5850 bzero (c->buckets, size);
5851 return c;
5855 /* Free image cache of frame F. Be aware that X frames share images
5856 caches. */
5858 void
5859 free_image_cache (f)
5860 struct frame *f;
5862 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5863 if (c)
5865 int i;
5867 /* Cache should not be referenced by any frame when freed. */
5868 xassert (c->refcount == 0);
5870 for (i = 0; i < c->used; ++i)
5871 free_image (f, c->images[i]);
5872 xfree (c->images);
5873 xfree (c);
5874 xfree (c->buckets);
5875 FRAME_X_IMAGE_CACHE (f) = NULL;
5880 /* Clear image cache of frame F. FORCE_P non-zero means free all
5881 images. FORCE_P zero means clear only images that haven't been
5882 displayed for some time. Should be called from time to time to
5883 reduce the number of loaded images. If image-eviction-seconds is
5884 non-nil, this frees images in the cache which weren't displayed for
5885 at least that many seconds. */
5887 void
5888 clear_image_cache (f, force_p)
5889 struct frame *f;
5890 int force_p;
5892 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5894 if (c && INTEGERP (Vimage_eviction_seconds))
5896 EMACS_TIME t;
5897 unsigned long old;
5898 int i, any_freed_p = 0;
5900 EMACS_GET_TIME (t);
5901 old = EMACS_SECS (t) - XFASTINT (Vimage_eviction_seconds);
5903 for (i = 0; i < c->used; ++i)
5905 struct image *img = c->images[i];
5906 if (img != NULL
5907 && (force_p
5908 || (img->timestamp > old)))
5910 free_image (f, img);
5911 any_freed_p = 1;
5915 /* We may be clearing the image cache because, for example,
5916 Emacs was iconified for a longer period of time. In that
5917 case, current matrices may still contain references to
5918 images freed above. So, clear these matrices. */
5919 if (any_freed_p)
5921 clear_current_matrices (f);
5922 ++windows_or_buffers_changed;
5928 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5929 0, 1, 0,
5930 "Clear the image cache of FRAME.\n\
5931 FRAME nil or omitted means use the selected frame.\n\
5932 FRAME t means clear the image caches of all frames.")
5933 (frame)
5934 Lisp_Object frame;
5936 if (EQ (frame, Qt))
5938 Lisp_Object tail;
5940 FOR_EACH_FRAME (tail, frame)
5941 if (FRAME_X_P (XFRAME (frame)))
5942 clear_image_cache (XFRAME (frame), 1);
5944 else
5945 clear_image_cache (check_x_frame (frame), 1);
5947 return Qnil;
5951 /* Return the id of image with Lisp specification SPEC on frame F.
5952 SPEC must be a valid Lisp image specification (see valid_image_p). */
5955 lookup_image (f, spec)
5956 struct frame *f;
5957 Lisp_Object spec;
5959 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5960 struct image *img;
5961 int i;
5962 unsigned hash;
5963 struct gcpro gcpro1;
5965 /* F must be a window-system frame, and SPEC must be a valid image
5966 specification. */
5967 xassert (FRAME_WINDOW_P (f));
5968 xassert (valid_image_p (spec));
5970 GCPRO1 (spec);
5972 /* Look up SPEC in the hash table of the image cache. */
5973 hash = sxhash (spec, 0);
5974 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5976 for (img = c->buckets[i]; img; img = img->next)
5977 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5978 break;
5980 /* If not found, create a new image and cache it. */
5981 if (img == NULL)
5983 extern Lisp_Object QCenable, QCselect;
5984 Lisp_Object tem;
5985 int loading_failed_p;
5987 img = make_image (spec, hash);
5988 cache_image (f, img);
5989 loading_failed_p = img->type->load (f, img) == 0;
5991 /* If we can't load the image, and we don't have a width and
5992 height, use some arbitrary width and height so that we can
5993 draw a rectangle for it. */
5994 if (loading_failed_p)
5996 Lisp_Object value;
5998 value = image_spec_value (spec, QCwidth, NULL);
5999 img->width = (INTEGERP (value)
6000 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6001 value = image_spec_value (spec, QCheight, NULL);
6002 img->height = (INTEGERP (value)
6003 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6005 else
6007 /* Handle image type independent image attributes
6008 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
6009 Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
6010 Lisp_Object file;
6012 ascent = image_spec_value (spec, QCascent, NULL);
6013 if (INTEGERP (ascent))
6014 img->ascent = XFASTINT (ascent);
6016 margin = image_spec_value (spec, QCmargin, NULL);
6017 if (INTEGERP (margin) && XINT (margin) >= 0)
6018 img->margin = XFASTINT (margin);
6020 relief = image_spec_value (spec, QCrelief, NULL);
6021 if (INTEGERP (relief))
6023 img->relief = XINT (relief);
6024 img->margin += abs (img->relief);
6027 /* Should we apply a Laplace edge-detection algorithm? */
6028 algorithm = image_spec_value (spec, QCalgorithm, NULL);
6029 if (img->pixmap && EQ (algorithm, Qlaplace))
6030 x_laplace (f, img);
6032 /* Should we built a mask heuristically? */
6033 heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
6034 if (img->pixmap && !img->mask && !NILP (heuristic_mask))
6036 file = image_spec_value (spec, QCfile, NULL);
6037 x_build_heuristic_mask (f, file, img, heuristic_mask);
6042 UNGCPRO;
6044 /* Value is the image id. */
6045 return img->id;
6049 /* Cache image IMG in the image cache of frame F. */
6051 static void
6052 cache_image (f, img)
6053 struct frame *f;
6054 struct image *img;
6056 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6057 int i;
6059 /* Find a free slot in c->images. */
6060 for (i = 0; i < c->used; ++i)
6061 if (c->images[i] == NULL)
6062 break;
6064 /* If no free slot found, maybe enlarge c->images. */
6065 if (i == c->used && c->used == c->size)
6067 c->size *= 2;
6068 c->images = (struct image **) xrealloc (c->images,
6069 c->size * sizeof *c->images);
6072 /* Add IMG to c->images, and assign IMG an id. */
6073 c->images[i] = img;
6074 img->id = i;
6075 if (i == c->used)
6076 ++c->used;
6078 /* Add IMG to the cache's hash table. */
6079 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6080 img->next = c->buckets[i];
6081 if (img->next)
6082 img->next->prev = img;
6083 img->prev = NULL;
6084 c->buckets[i] = img;
6088 /* Call FN on every image in the image cache of frame F. Used to mark
6089 Lisp Objects in the image cache. */
6091 void
6092 forall_images_in_image_cache (f, fn)
6093 struct frame *f;
6094 void (*fn) P_ ((struct image *img));
6096 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6098 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6099 if (c)
6101 int i;
6102 for (i = 0; i < c->used; ++i)
6103 if (c->images[i])
6104 fn (c->images[i]);
6111 /***********************************************************************
6112 X support code
6113 ***********************************************************************/
6115 static int x_create_x_image_and_pixmap P_ ((struct frame *, Lisp_Object,
6116 int, int, int, XImage **,
6117 Pixmap *));
6118 static void x_destroy_x_image P_ ((XImage *));
6119 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6122 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6123 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6124 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6125 via xmalloc. Print error messages via image_error if an error
6126 occurs. FILE is the name of an image file being processed, for
6127 error messages. Value is non-zero if successful. */
6129 static int
6130 x_create_x_image_and_pixmap (f, file, width, height, depth, ximg, pixmap)
6131 struct frame *f;
6132 Lisp_Object file;
6133 int width, height, depth;
6134 XImage **ximg;
6135 Pixmap *pixmap;
6137 Display *display = FRAME_X_DISPLAY (f);
6138 Screen *screen = FRAME_X_SCREEN (f);
6139 Window window = FRAME_X_WINDOW (f);
6141 xassert (interrupt_input_blocked);
6143 if (depth <= 0)
6144 depth = DefaultDepthOfScreen (screen);
6145 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6146 depth, ZPixmap, 0, NULL, width, height,
6147 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6148 if (*ximg == NULL)
6150 image_error ("Unable to allocate X image for %s", file, Qnil);
6151 return 0;
6154 /* Allocate image raster. */
6155 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6157 /* Allocate a pixmap of the same size. */
6158 *pixmap = XCreatePixmap (display, window, width, height, depth);
6159 if (*pixmap == 0)
6161 x_destroy_x_image (*ximg);
6162 *ximg = NULL;
6163 image_error ("Unable to create pixmap for `%s'", file, Qnil);
6164 return 0;
6167 return 1;
6171 /* Destroy XImage XIMG. Free XIMG->data. */
6173 static void
6174 x_destroy_x_image (ximg)
6175 XImage *ximg;
6177 xassert (interrupt_input_blocked);
6178 if (ximg)
6180 xfree (ximg->data);
6181 ximg->data = NULL;
6182 XDestroyImage (ximg);
6187 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6188 are width and height of both the image and pixmap. */
6190 void
6191 x_put_x_image (f, ximg, pixmap, width, height)
6192 struct frame *f;
6193 XImage *ximg;
6194 Pixmap pixmap;
6196 GC gc;
6198 xassert (interrupt_input_blocked);
6199 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6200 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6201 XFreeGC (FRAME_X_DISPLAY (f), gc);
6206 /***********************************************************************
6207 Searching files
6208 ***********************************************************************/
6210 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6212 /* Find image file FILE. Look in data-directory, then
6213 x-bitmap-file-path. Value is the full name of the file found, or
6214 nil if not found. */
6216 static Lisp_Object
6217 x_find_image_file (file)
6218 Lisp_Object file;
6220 Lisp_Object file_found, search_path;
6221 struct gcpro gcpro1, gcpro2;
6222 int fd;
6224 file_found = Qnil;
6225 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6226 GCPRO2 (file_found, search_path);
6228 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6229 fd = openp (search_path, file, "", &file_found, 0);
6231 if (fd < 0)
6232 file_found = Qnil;
6233 else
6234 close (fd);
6236 UNGCPRO;
6237 return file_found;
6242 /***********************************************************************
6243 XBM images
6244 ***********************************************************************/
6246 static int xbm_load P_ ((struct frame *f, struct image *img));
6247 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
6248 Lisp_Object file));
6249 static int xbm_image_p P_ ((Lisp_Object object));
6250 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
6251 unsigned char **));
6252 static int xbm_read_hexint P_ ((FILE *));
6255 /* Indices of image specification fields in xbm_format, below. */
6257 enum xbm_keyword_index
6259 XBM_TYPE,
6260 XBM_FILE,
6261 XBM_WIDTH,
6262 XBM_HEIGHT,
6263 XBM_DATA,
6264 XBM_FOREGROUND,
6265 XBM_BACKGROUND,
6266 XBM_ASCENT,
6267 XBM_MARGIN,
6268 XBM_RELIEF,
6269 XBM_ALGORITHM,
6270 XBM_HEURISTIC_MASK,
6271 XBM_LAST
6274 /* Vector of image_keyword structures describing the format
6275 of valid XBM image specifications. */
6277 static struct image_keyword xbm_format[XBM_LAST] =
6279 {":type", IMAGE_SYMBOL_VALUE, 1},
6280 {":file", IMAGE_STRING_VALUE, 0},
6281 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6282 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6283 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6284 {":foreground", IMAGE_STRING_VALUE, 0},
6285 {":background", IMAGE_STRING_VALUE, 0},
6286 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6287 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6288 {":relief", IMAGE_INTEGER_VALUE, 0},
6289 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6290 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6293 /* Structure describing the image type XBM. */
6295 static struct image_type xbm_type =
6297 &Qxbm,
6298 xbm_image_p,
6299 xbm_load,
6300 x_clear_image,
6301 NULL
6304 /* Tokens returned from xbm_scan. */
6306 enum xbm_token
6308 XBM_TK_IDENT = 256,
6309 XBM_TK_NUMBER
6313 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6314 A valid specification is a list starting with the symbol `image'
6315 The rest of the list is a property list which must contain an
6316 entry `:type xbm..
6318 If the specification specifies a file to load, it must contain
6319 an entry `:file FILENAME' where FILENAME is a string.
6321 If the specification is for a bitmap loaded from memory it must
6322 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6323 WIDTH and HEIGHT are integers > 0. DATA may be:
6325 1. a string large enough to hold the bitmap data, i.e. it must
6326 have a size >= (WIDTH + 7) / 8 * HEIGHT
6328 2. a bool-vector of size >= WIDTH * HEIGHT
6330 3. a vector of strings or bool-vectors, one for each line of the
6331 bitmap.
6333 Both the file and data forms may contain the additional entries
6334 `:background COLOR' and `:foreground COLOR'. If not present,
6335 foreground and background of the frame on which the image is
6336 displayed, is used. */
6338 static int
6339 xbm_image_p (object)
6340 Lisp_Object object;
6342 struct image_keyword kw[XBM_LAST];
6344 bcopy (xbm_format, kw, sizeof kw);
6345 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm, 0))
6346 return 0;
6348 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6350 if (kw[XBM_FILE].count)
6352 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6353 return 0;
6355 else
6357 Lisp_Object data;
6358 int width, height;
6360 /* Entries for `:width', `:height' and `:data' must be present. */
6361 if (!kw[XBM_WIDTH].count
6362 || !kw[XBM_HEIGHT].count
6363 || !kw[XBM_DATA].count)
6364 return 0;
6366 data = kw[XBM_DATA].value;
6367 width = XFASTINT (kw[XBM_WIDTH].value);
6368 height = XFASTINT (kw[XBM_HEIGHT].value);
6370 /* Check type of data, and width and height against contents of
6371 data. */
6372 if (VECTORP (data))
6374 int i;
6376 /* Number of elements of the vector must be >= height. */
6377 if (XVECTOR (data)->size < height)
6378 return 0;
6380 /* Each string or bool-vector in data must be large enough
6381 for one line of the image. */
6382 for (i = 0; i < height; ++i)
6384 Lisp_Object elt = XVECTOR (data)->contents[i];
6386 if (STRINGP (elt))
6388 if (XSTRING (elt)->size
6389 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6390 return 0;
6392 else if (BOOL_VECTOR_P (elt))
6394 if (XBOOL_VECTOR (elt)->size < width)
6395 return 0;
6397 else
6398 return 0;
6401 else if (STRINGP (data))
6403 if (XSTRING (data)->size
6404 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6405 return 0;
6407 else if (BOOL_VECTOR_P (data))
6409 if (XBOOL_VECTOR (data)->size < width * height)
6410 return 0;
6412 else
6413 return 0;
6416 /* Baseline must be a value between 0 and 100 (a percentage). */
6417 if (kw[XBM_ASCENT].count
6418 && XFASTINT (kw[XBM_ASCENT].value) > 100)
6419 return 0;
6421 return 1;
6425 /* Scan a bitmap file. FP is the stream to read from. Value is
6426 either an enumerator from enum xbm_token, or a character for a
6427 single-character token, or 0 at end of file. If scanning an
6428 identifier, store the lexeme of the identifier in SVAL. If
6429 scanning a number, store its value in *IVAL. */
6431 static int
6432 xbm_scan (fp, sval, ival)
6433 FILE *fp;
6434 char *sval;
6435 int *ival;
6437 int c;
6439 /* Skip white space. */
6440 while ((c = fgetc (fp)) != EOF && isspace (c))
6443 if (c == EOF)
6444 c = 0;
6445 else if (isdigit (c))
6447 int value = 0, digit;
6449 if (c == '0')
6451 c = fgetc (fp);
6452 if (c == 'x' || c == 'X')
6454 while ((c = fgetc (fp)) != EOF)
6456 if (isdigit (c))
6457 digit = c - '0';
6458 else if (c >= 'a' && c <= 'f')
6459 digit = c - 'a' + 10;
6460 else if (c >= 'A' && c <= 'F')
6461 digit = c - 'A' + 10;
6462 else
6463 break;
6464 value = 16 * value + digit;
6467 else if (isdigit (c))
6469 value = c - '0';
6470 while ((c = fgetc (fp)) != EOF
6471 && isdigit (c))
6472 value = 8 * value + c - '0';
6475 else
6477 value = c - '0';
6478 while ((c = fgetc (fp)) != EOF
6479 && isdigit (c))
6480 value = 10 * value + c - '0';
6483 if (c != EOF)
6484 ungetc (c, fp);
6485 *ival = value;
6486 c = XBM_TK_NUMBER;
6488 else if (isalpha (c) || c == '_')
6490 *sval++ = c;
6491 while ((c = fgetc (fp)) != EOF
6492 && (isalnum (c) || c == '_'))
6493 *sval++ = c;
6494 *sval = 0;
6495 if (c != EOF)
6496 ungetc (c, fp);
6497 c = XBM_TK_IDENT;
6500 return c;
6504 /* Replacement for XReadBitmapFileData which isn't available under old
6505 X versions. FILE is the name of the bitmap file to read. Set
6506 *WIDTH and *HEIGHT to the width and height of the image. Return in
6507 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
6508 successful. */
6510 static int
6511 xbm_read_bitmap_file_data (file, width, height, data)
6512 char *file;
6513 int *width, *height;
6514 unsigned char **data;
6516 FILE *fp;
6517 char buffer[BUFSIZ];
6518 int padding_p = 0;
6519 int v10 = 0;
6520 int bytes_per_line, i, nbytes;
6521 unsigned char *p;
6522 int value;
6523 int LA1;
6525 #define match() \
6526 LA1 = xbm_scan (fp, buffer, &value)
6528 #define expect(TOKEN) \
6529 if (LA1 != (TOKEN)) \
6530 goto failure; \
6531 else \
6532 match ()
6534 #define expect_ident(IDENT) \
6535 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6536 match (); \
6537 else \
6538 goto failure
6540 fp = fopen (file, "r");
6541 if (fp == NULL)
6542 return 0;
6544 *width = *height = -1;
6545 *data = NULL;
6546 LA1 = xbm_scan (fp, buffer, &value);
6548 /* Parse defines for width, height and hot-spots. */
6549 while (LA1 == '#')
6551 char *p;
6553 match ();
6554 expect_ident ("define");
6555 expect (XBM_TK_IDENT);
6557 if (LA1 == XBM_TK_NUMBER);
6559 char *p = strrchr (buffer, '_');
6560 p = p ? p + 1 : buffer;
6561 if (strcmp (p, "width") == 0)
6562 *width = value;
6563 else if (strcmp (p, "height") == 0)
6564 *height = value;
6566 expect (XBM_TK_NUMBER);
6569 if (*width < 0 || *height < 0)
6570 goto failure;
6572 /* Parse bits. Must start with `static'. */
6573 expect_ident ("static");
6574 if (LA1 == XBM_TK_IDENT)
6576 if (strcmp (buffer, "unsigned") == 0)
6578 match ();
6579 expect_ident ("char");
6581 else if (strcmp (buffer, "short") == 0)
6583 match ();
6584 v10 = 1;
6585 if (*width % 16 && *width % 16 < 9)
6586 padding_p = 1;
6588 else if (strcmp (buffer, "char") == 0)
6589 match ();
6590 else
6591 goto failure;
6593 else
6594 goto failure;
6596 expect (XBM_TK_IDENT);
6597 expect ('[');
6598 expect (']');
6599 expect ('=');
6600 expect ('{');
6602 bytes_per_line = (*width + 7) / 8 + padding_p;
6603 nbytes = bytes_per_line * *height;
6604 p = *data = (char *) xmalloc (nbytes);
6606 if (v10)
6609 for (i = 0; i < nbytes; i += 2)
6611 int val = value;
6612 expect (XBM_TK_NUMBER);
6614 *p++ = val;
6615 if (!padding_p || ((i + 2) % bytes_per_line))
6616 *p++ = value >> 8;
6618 if (LA1 == ',' || LA1 == '}')
6619 match ();
6620 else
6621 goto failure;
6624 else
6626 for (i = 0; i < nbytes; ++i)
6628 int val = value;
6629 expect (XBM_TK_NUMBER);
6631 *p++ = val;
6633 if (LA1 == ',' || LA1 == '}')
6634 match ();
6635 else
6636 goto failure;
6640 fclose (fp);
6641 return 1;
6643 failure:
6645 fclose (fp);
6646 if (*data)
6648 xfree (*data);
6649 *data = NULL;
6651 return 0;
6653 #undef match
6654 #undef expect
6655 #undef expect_ident
6659 /* Load XBM image IMG which will be displayed on frame F from file
6660 SPECIFIED_FILE. Value is non-zero if successful. */
6662 static int
6663 xbm_load_image_from_file (f, img, specified_file)
6664 struct frame *f;
6665 struct image *img;
6666 Lisp_Object specified_file;
6668 int rc;
6669 unsigned char *data;
6670 int success_p = 0;
6671 Lisp_Object file;
6672 struct gcpro gcpro1;
6674 xassert (STRINGP (specified_file));
6675 file = Qnil;
6676 GCPRO1 (file);
6678 file = x_find_image_file (specified_file);
6679 if (!STRINGP (file))
6681 image_error ("Cannot find image file %s", specified_file, Qnil);
6682 UNGCPRO;
6683 return 0;
6686 rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
6687 &img->height, &data);
6688 if (rc)
6690 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6691 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6692 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6693 Lisp_Object value;
6695 xassert (img->width > 0 && img->height > 0);
6697 /* Get foreground and background colors, maybe allocate colors. */
6698 value = image_spec_value (img->spec, QCforeground, NULL);
6699 if (!NILP (value))
6700 foreground = x_alloc_image_color (f, img, value, foreground);
6702 value = image_spec_value (img->spec, QCbackground, NULL);
6703 if (!NILP (value))
6704 background = x_alloc_image_color (f, img, value, background);
6706 BLOCK_INPUT;
6707 img->pixmap
6708 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6709 FRAME_X_WINDOW (f),
6710 data,
6711 img->width, img->height,
6712 foreground, background,
6713 depth);
6714 xfree (data);
6716 if (img->pixmap == 0)
6718 x_clear_image (f, img);
6719 image_error ("Unable to create X pixmap for `%s'", file, Qnil);
6721 else
6722 success_p = 1;
6724 UNBLOCK_INPUT;
6726 else
6727 image_error ("Error loading XBM image %s", img->spec, Qnil);
6729 UNGCPRO;
6730 return success_p;
6734 /* Fill image IMG which is used on frame F with pixmap data. Value is
6735 non-zero if successful. */
6737 static int
6738 xbm_load (f, img)
6739 struct frame *f;
6740 struct image *img;
6742 int success_p = 0;
6743 Lisp_Object file_name;
6745 xassert (xbm_image_p (img->spec));
6747 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6748 file_name = image_spec_value (img->spec, QCfile, NULL);
6749 if (STRINGP (file_name))
6750 success_p = xbm_load_image_from_file (f, img, file_name);
6751 else
6753 struct image_keyword fmt[XBM_LAST];
6754 Lisp_Object data;
6755 int depth;
6756 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6757 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6758 char *bits;
6759 int parsed_p;
6761 /* Parse the list specification. */
6762 bcopy (xbm_format, fmt, sizeof fmt);
6763 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm, 0);
6764 xassert (parsed_p);
6766 /* Get specified width, and height. */
6767 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6768 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6769 xassert (img->width > 0 && img->height > 0);
6771 BLOCK_INPUT;
6773 if (fmt[XBM_ASCENT].count)
6774 img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
6776 /* Get foreground and background colors, maybe allocate colors. */
6777 if (fmt[XBM_FOREGROUND].count)
6778 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6779 foreground);
6780 if (fmt[XBM_BACKGROUND].count)
6781 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6782 background);
6784 /* Set bits to the bitmap image data. */
6785 data = fmt[XBM_DATA].value;
6786 if (VECTORP (data))
6788 int i;
6789 char *p;
6790 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6792 p = bits = (char *) alloca (nbytes * img->height);
6793 for (i = 0; i < img->height; ++i, p += nbytes)
6795 Lisp_Object line = XVECTOR (data)->contents[i];
6796 if (STRINGP (line))
6797 bcopy (XSTRING (line)->data, p, nbytes);
6798 else
6799 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6802 else if (STRINGP (data))
6803 bits = XSTRING (data)->data;
6804 else
6805 bits = XBOOL_VECTOR (data)->data;
6807 /* Create the pixmap. */
6808 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6809 img->pixmap
6810 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6811 FRAME_X_WINDOW (f),
6812 bits,
6813 img->width, img->height,
6814 foreground, background,
6815 depth);
6816 if (img->pixmap)
6817 success_p = 1;
6818 else
6820 image_error ("Unable to create pixmap for XBM image", Qnil, Qnil);
6821 x_clear_image (f, img);
6824 UNBLOCK_INPUT;
6827 return success_p;
6832 /***********************************************************************
6833 XPM images
6834 ***********************************************************************/
6836 #if HAVE_XPM
6838 static int xpm_image_p P_ ((Lisp_Object object));
6839 static int xpm_load P_ ((struct frame *f, struct image *img));
6840 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6842 #include "X11/xpm.h"
6844 /* The symbol `xpm' identifying XPM-format images. */
6846 Lisp_Object Qxpm;
6848 /* Indices of image specification fields in xpm_format, below. */
6850 enum xpm_keyword_index
6852 XPM_TYPE,
6853 XPM_FILE,
6854 XPM_DATA,
6855 XPM_ASCENT,
6856 XPM_MARGIN,
6857 XPM_RELIEF,
6858 XPM_ALGORITHM,
6859 XPM_HEURISTIC_MASK,
6860 XPM_COLOR_SYMBOLS,
6861 XPM_LAST
6864 /* Vector of image_keyword structures describing the format
6865 of valid XPM image specifications. */
6867 static struct image_keyword xpm_format[XPM_LAST] =
6869 {":type", IMAGE_SYMBOL_VALUE, 1},
6870 {":file", IMAGE_STRING_VALUE, 0},
6871 {":data", IMAGE_STRING_VALUE, 0},
6872 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6873 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6874 {":relief", IMAGE_INTEGER_VALUE, 0},
6875 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6876 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6877 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6880 /* Structure describing the image type XBM. */
6882 static struct image_type xpm_type =
6884 &Qxpm,
6885 xpm_image_p,
6886 xpm_load,
6887 x_clear_image,
6888 NULL
6892 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6893 for XPM images. Such a list must consist of conses whose car and
6894 cdr are strings. */
6896 static int
6897 xpm_valid_color_symbols_p (color_symbols)
6898 Lisp_Object color_symbols;
6900 while (CONSP (color_symbols))
6902 Lisp_Object sym = XCAR (color_symbols);
6903 if (!CONSP (sym)
6904 || !STRINGP (XCAR (sym))
6905 || !STRINGP (XCDR (sym)))
6906 break;
6907 color_symbols = XCDR (color_symbols);
6910 return NILP (color_symbols);
6914 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6916 static int
6917 xpm_image_p (object)
6918 Lisp_Object object;
6920 struct image_keyword fmt[XPM_LAST];
6921 bcopy (xpm_format, fmt, sizeof fmt);
6922 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm, 0)
6923 /* Either `:file' or `:data' must be present. */
6924 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
6925 /* Either no `:color-symbols' or it's a list of conses
6926 whose car and cdr are strings. */
6927 && (fmt[XPM_COLOR_SYMBOLS].count == 0
6928 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
6929 && (fmt[XPM_ASCENT].count == 0
6930 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
6934 /* Load image IMG which will be displayed on frame F. Value is
6935 non-zero if successful. */
6937 static int
6938 xpm_load (f, img)
6939 struct frame *f;
6940 struct image *img;
6942 int rc, i;
6943 XpmAttributes attrs;
6944 Lisp_Object specified_file, color_symbols;
6946 /* Configure the XPM lib. Use the visual of frame F. Allocate
6947 close colors. Return colors allocated. */
6948 bzero (&attrs, sizeof attrs);
6949 attrs.visual = FRAME_X_DISPLAY_INFO (f)->visual;
6950 attrs.valuemask |= XpmVisual;
6951 attrs.valuemask |= XpmReturnAllocPixels;
6952 attrs.alloc_close_colors = 1;
6953 attrs.valuemask |= XpmAllocCloseColors;
6955 /* If image specification contains symbolic color definitions, add
6956 these to `attrs'. */
6957 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
6958 if (CONSP (color_symbols))
6960 Lisp_Object tail;
6961 XpmColorSymbol *xpm_syms;
6962 int i, size;
6964 attrs.valuemask |= XpmColorSymbols;
6966 /* Count number of symbols. */
6967 attrs.numsymbols = 0;
6968 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
6969 ++attrs.numsymbols;
6971 /* Allocate an XpmColorSymbol array. */
6972 size = attrs.numsymbols * sizeof *xpm_syms;
6973 xpm_syms = (XpmColorSymbol *) alloca (size);
6974 bzero (xpm_syms, size);
6975 attrs.colorsymbols = xpm_syms;
6977 /* Fill the color symbol array. */
6978 for (tail = color_symbols, i = 0;
6979 CONSP (tail);
6980 ++i, tail = XCDR (tail))
6982 Lisp_Object name = XCAR (XCAR (tail));
6983 Lisp_Object color = XCDR (XCAR (tail));
6984 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
6985 strcpy (xpm_syms[i].name, XSTRING (name)->data);
6986 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
6987 strcpy (xpm_syms[i].value, XSTRING (color)->data);
6991 /* Create a pixmap for the image, either from a file, or from a
6992 string buffer containing data in the same format as an XPM file. */
6993 BLOCK_INPUT;
6994 specified_file = image_spec_value (img->spec, QCfile, NULL);
6995 if (STRINGP (specified_file))
6997 Lisp_Object file = x_find_image_file (specified_file);
6998 if (!STRINGP (file))
7000 image_error ("Cannot find image file %s", specified_file, Qnil);
7001 return 0;
7004 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7005 XSTRING (file)->data, &img->pixmap, &img->mask,
7006 &attrs);
7008 else
7010 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7011 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7012 XSTRING (buffer)->data,
7013 &img->pixmap, &img->mask,
7014 &attrs);
7016 UNBLOCK_INPUT;
7018 if (rc == XpmSuccess)
7020 /* Remember allocated colors. */
7021 img->ncolors = attrs.nalloc_pixels;
7022 img->colors = (unsigned long *) xmalloc (img->ncolors
7023 * sizeof *img->colors);
7024 for (i = 0; i < attrs.nalloc_pixels; ++i)
7025 img->colors[i] = attrs.alloc_pixels[i];
7027 img->width = attrs.width;
7028 img->height = attrs.height;
7029 xassert (img->width > 0 && img->height > 0);
7031 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7032 BLOCK_INPUT;
7033 XpmFreeAttributes (&attrs);
7034 UNBLOCK_INPUT;
7036 else
7038 switch (rc)
7040 case XpmOpenFailed:
7041 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7042 break;
7044 case XpmFileInvalid:
7045 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7046 break;
7048 case XpmNoMemory:
7049 image_error ("Out of memory (%s)", img->spec, Qnil);
7050 break;
7052 case XpmColorFailed:
7053 image_error ("Color allocation error (%s)", img->spec, Qnil);
7054 break;
7056 default:
7057 image_error ("Unknown error (%s)", img->spec, Qnil);
7058 break;
7062 return rc == XpmSuccess;
7065 #endif /* HAVE_XPM != 0 */
7068 /***********************************************************************
7069 Color table
7070 ***********************************************************************/
7072 /* An entry in the color table mapping an RGB color to a pixel color. */
7074 struct ct_color
7076 int r, g, b;
7077 unsigned long pixel;
7079 /* Next in color table collision list. */
7080 struct ct_color *next;
7083 /* The bucket vector size to use. Must be prime. */
7085 #define CT_SIZE 101
7087 /* Value is a hash of the RGB color given by R, G, and B. */
7089 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7091 /* The color hash table. */
7093 struct ct_color **ct_table;
7095 /* Number of entries in the color table. */
7097 int ct_colors_allocated;
7099 /* Function prototypes. */
7101 static void init_color_table P_ ((void));
7102 static void free_color_table P_ ((void));
7103 static unsigned long *colors_in_color_table P_ ((int *n));
7104 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
7105 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
7108 /* Initialize the color table. */
7110 static void
7111 init_color_table ()
7113 int size = CT_SIZE * sizeof (*ct_table);
7114 ct_table = (struct ct_color **) xmalloc (size);
7115 bzero (ct_table, size);
7116 ct_colors_allocated = 0;
7120 /* Free memory associated with the color table. */
7122 static void
7123 free_color_table ()
7125 int i;
7126 struct ct_color *p, *next;
7128 for (i = 0; i < CT_SIZE; ++i)
7129 for (p = ct_table[i]; p; p = next)
7131 next = p->next;
7132 xfree (p);
7135 xfree (ct_table);
7136 ct_table = NULL;
7140 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7141 entry for that color already is in the color table, return the
7142 pixel color of that entry. Otherwise, allocate a new color for R,
7143 G, B, and make an entry in the color table. */
7145 static unsigned long
7146 lookup_rgb_color (f, r, g, b)
7147 struct frame *f;
7148 int r, g, b;
7150 unsigned hash = CT_HASH_RGB (r, g, b);
7151 int i = hash % CT_SIZE;
7152 struct ct_color *p;
7154 for (p = ct_table[i]; p; p = p->next)
7155 if (p->r == r && p->g == g && p->b == b)
7156 break;
7158 if (p == NULL)
7160 XColor color;
7161 Colormap cmap;
7162 int rc;
7164 color.red = r;
7165 color.green = g;
7166 color.blue = b;
7168 BLOCK_INPUT;
7169 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7170 rc = x_alloc_nearest_color (FRAME_X_DISPLAY (f), FRAME_X_SCREEN (f),
7171 cmap, &color);
7172 UNBLOCK_INPUT;
7174 if (rc)
7176 ++ct_colors_allocated;
7178 p = (struct ct_color *) xmalloc (sizeof *p);
7179 p->r = r;
7180 p->g = g;
7181 p->b = b;
7182 p->pixel = color.pixel;
7183 p->next = ct_table[i];
7184 ct_table[i] = p;
7186 else
7187 return FRAME_FOREGROUND_PIXEL (f);
7190 return p->pixel;
7194 /* Look up pixel color PIXEL which is used on frame F in the color
7195 table. If not already present, allocate it. Value is PIXEL. */
7197 static unsigned long
7198 lookup_pixel_color (f, pixel)
7199 struct frame *f;
7200 unsigned long pixel;
7202 int i = pixel % CT_SIZE;
7203 struct ct_color *p;
7205 for (p = ct_table[i]; p; p = p->next)
7206 if (p->pixel == pixel)
7207 break;
7209 if (p == NULL)
7211 XColor color;
7212 Colormap cmap;
7213 int rc;
7215 BLOCK_INPUT;
7217 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7218 color.pixel = pixel;
7219 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
7220 rc = x_alloc_nearest_color (FRAME_X_DISPLAY (f), FRAME_X_SCREEN (f),
7221 cmap, &color);
7222 UNBLOCK_INPUT;
7224 if (rc)
7226 ++ct_colors_allocated;
7228 p = (struct ct_color *) xmalloc (sizeof *p);
7229 p->r = color.red;
7230 p->g = color.green;
7231 p->b = color.blue;
7232 p->pixel = pixel;
7233 p->next = ct_table[i];
7234 ct_table[i] = p;
7236 else
7237 return FRAME_FOREGROUND_PIXEL (f);
7240 return p->pixel;
7244 /* Value is a vector of all pixel colors contained in the color table,
7245 allocated via xmalloc. Set *N to the number of colors. */
7247 static unsigned long *
7248 colors_in_color_table (n)
7249 int *n;
7251 int i, j;
7252 struct ct_color *p;
7253 unsigned long *colors;
7255 if (ct_colors_allocated == 0)
7257 *n = 0;
7258 colors = NULL;
7260 else
7262 colors = (unsigned long *) xmalloc (ct_colors_allocated
7263 * sizeof *colors);
7264 *n = ct_colors_allocated;
7266 for (i = j = 0; i < CT_SIZE; ++i)
7267 for (p = ct_table[i]; p; p = p->next)
7268 colors[j++] = p->pixel;
7271 return colors;
7276 /***********************************************************************
7277 Algorithms
7278 ***********************************************************************/
7280 static void x_laplace_write_row P_ ((struct frame *, long *,
7281 int, XImage *, int));
7282 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7283 XColor *, int, XImage *, int));
7286 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
7287 frame we operate on, CMAP is the color-map in effect, and WIDTH is
7288 the width of one row in the image. */
7290 static void
7291 x_laplace_read_row (f, cmap, colors, width, ximg, y)
7292 struct frame *f;
7293 Colormap cmap;
7294 XColor *colors;
7295 int width;
7296 XImage *ximg;
7297 int y;
7299 int x;
7301 for (x = 0; x < width; ++x)
7302 colors[x].pixel = XGetPixel (ximg, x, y);
7304 XQueryColors (FRAME_X_DISPLAY (f), cmap, colors, width);
7308 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
7309 containing the pixel colors to write. F is the frame we are
7310 working on. */
7312 static void
7313 x_laplace_write_row (f, pixels, width, ximg, y)
7314 struct frame *f;
7315 long *pixels;
7316 int width;
7317 XImage *ximg;
7318 int y;
7320 int x;
7322 for (x = 0; x < width; ++x)
7323 XPutPixel (ximg, x, y, pixels[x]);
7327 /* Transform image IMG which is used on frame F with a Laplace
7328 edge-detection algorithm. The result is an image that can be used
7329 to draw disabled buttons, for example. */
7331 static void
7332 x_laplace (f, img)
7333 struct frame *f;
7334 struct image *img;
7336 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7337 XImage *ximg, *oimg;
7338 XColor *in[3];
7339 long *out;
7340 Pixmap pixmap;
7341 int x, y, i;
7342 long pixel;
7343 int in_y, out_y, rc;
7344 int mv2 = 45000;
7346 BLOCK_INPUT;
7348 /* Get the X image IMG->pixmap. */
7349 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7350 0, 0, img->width, img->height, ~0, ZPixmap);
7352 /* Allocate 3 input rows, and one output row of colors. */
7353 for (i = 0; i < 3; ++i)
7354 in[i] = (XColor *) alloca (img->width * sizeof (XColor));
7355 out = (long *) alloca (img->width * sizeof (long));
7357 /* Create an X image for output. */
7358 rc = x_create_x_image_and_pixmap (f, Qnil, img->width, img->height, 0,
7359 &oimg, &pixmap);
7361 /* Fill first two rows. */
7362 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
7363 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
7364 in_y = 2;
7366 /* Write first row, all zeros. */
7367 init_color_table ();
7368 pixel = lookup_rgb_color (f, 0, 0, 0);
7369 for (x = 0; x < img->width; ++x)
7370 out[x] = pixel;
7371 x_laplace_write_row (f, out, img->width, oimg, 0);
7372 out_y = 1;
7374 for (y = 2; y < img->height; ++y)
7376 int rowa = y % 3;
7377 int rowb = (y + 2) % 3;
7379 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
7381 for (x = 0; x < img->width - 2; ++x)
7383 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
7384 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
7385 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
7387 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
7388 b & 0xffff);
7391 x_laplace_write_row (f, out, img->width, oimg, out_y++);
7394 /* Write last line, all zeros. */
7395 for (x = 0; x < img->width; ++x)
7396 out[x] = pixel;
7397 x_laplace_write_row (f, out, img->width, oimg, out_y);
7399 /* Free the input image, and free resources of IMG. */
7400 XDestroyImage (ximg);
7401 x_clear_image (f, img);
7403 /* Put the output image into pixmap, and destroy it. */
7404 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7405 x_destroy_x_image (oimg);
7407 /* Remember new pixmap and colors in IMG. */
7408 img->pixmap = pixmap;
7409 img->colors = colors_in_color_table (&img->ncolors);
7410 free_color_table ();
7412 UNBLOCK_INPUT;
7416 /* Build a mask for image IMG which is used on frame F. FILE is the
7417 name of an image file, for error messages. HOW determines how to
7418 determine the background color of IMG. If it is an integer, take
7419 that as the pixel value of the background. Otherwise, determine
7420 the background color of IMG heuristically. Value is non-zero
7421 if successful. */
7423 static int
7424 x_build_heuristic_mask (f, file, img, how)
7425 struct frame *f;
7426 Lisp_Object file;
7427 struct image *img;
7428 Lisp_Object how;
7430 Display *dpy = FRAME_X_DISPLAY (f);
7431 Window win = FRAME_X_WINDOW (f);
7432 XImage *ximg, *mask_img;
7433 int x, y, rc;
7434 unsigned long bg;
7436 BLOCK_INPUT;
7438 /* Create an image and pixmap serving as mask. */
7439 rc = x_create_x_image_and_pixmap (f, file, img->width, img->height, 1,
7440 &mask_img, &img->mask);
7441 if (!rc)
7443 UNBLOCK_INPUT;
7444 return 0;
7447 /* Get the X image of IMG->pixmap. */
7448 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7449 ~0, ZPixmap);
7451 /* Determine the background color of ximg. If HOW is an integer,
7452 take that as a pixel color. Otherwise, try to determine the
7453 color heuristically. */
7454 if (NATNUMP (how))
7455 bg = XFASTINT (how);
7456 else
7458 unsigned long corners[4];
7459 int i, best_count;
7461 /* Get the colors at the corners of ximg. */
7462 corners[0] = XGetPixel (ximg, 0, 0);
7463 corners[1] = XGetPixel (ximg, img->width - 1, 0);
7464 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
7465 corners[3] = XGetPixel (ximg, 0, img->height - 1);
7467 /* Choose the most frequently found color as background. */
7468 for (i = best_count = 0; i < 4; ++i)
7470 int j, n;
7472 for (j = n = 0; j < 4; ++j)
7473 if (corners[i] == corners[j])
7474 ++n;
7476 if (n > best_count)
7477 bg = corners[i], best_count = n;
7481 /* Set all bits in mask_img to 1 whose color in ximg is different
7482 from the background color bg. */
7483 for (y = 0; y < img->height; ++y)
7484 for (x = 0; x < img->width; ++x)
7485 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7487 /* Put mask_img into img->mask. */
7488 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7489 x_destroy_x_image (mask_img);
7490 XDestroyImage (ximg);
7492 UNBLOCK_INPUT;
7493 return 1;
7498 /***********************************************************************
7499 PBM (mono, gray, color)
7500 ***********************************************************************/
7502 static int pbm_image_p P_ ((Lisp_Object object));
7503 static int pbm_load P_ ((struct frame *f, struct image *img));
7504 static int pbm_scan_number P_ ((FILE *fp));
7506 /* The symbol `pbm' identifying images of this type. */
7508 Lisp_Object Qpbm;
7510 /* Indices of image specification fields in gs_format, below. */
7512 enum pbm_keyword_index
7514 PBM_TYPE,
7515 PBM_FILE,
7516 PBM_ASCENT,
7517 PBM_MARGIN,
7518 PBM_RELIEF,
7519 PBM_ALGORITHM,
7520 PBM_HEURISTIC_MASK,
7521 PBM_LAST
7524 /* Vector of image_keyword structures describing the format
7525 of valid user-defined image specifications. */
7527 static struct image_keyword pbm_format[PBM_LAST] =
7529 {":type", IMAGE_SYMBOL_VALUE, 1},
7530 {":file", IMAGE_STRING_VALUE, 1},
7531 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7532 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7533 {":relief", IMAGE_INTEGER_VALUE, 0},
7534 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7535 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7538 /* Structure describing the image type `pbm'. */
7540 static struct image_type pbm_type =
7542 &Qpbm,
7543 pbm_image_p,
7544 pbm_load,
7545 x_clear_image,
7546 NULL
7550 /* Return non-zero if OBJECT is a valid PBM image specification. */
7552 static int
7553 pbm_image_p (object)
7554 Lisp_Object object;
7556 struct image_keyword fmt[PBM_LAST];
7558 bcopy (pbm_format, fmt, sizeof fmt);
7560 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm, 0)
7561 || (fmt[PBM_ASCENT].count
7562 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
7563 return 0;
7564 return 1;
7568 /* Scan a decimal number from PBM input file FP and return it. Value
7569 is -1 at end of file or if an error occurs. */
7571 static int
7572 pbm_scan_number (fp)
7573 FILE *fp;
7575 int c, val = -1;
7577 while (!feof (fp))
7579 /* Skip white-space. */
7580 while ((c = fgetc (fp)) != EOF && isspace (c))
7583 if (c == '#')
7585 /* Skip comment to end of line. */
7586 while ((c = fgetc (fp)) != EOF && c != '\n')
7589 else if (isdigit (c))
7591 /* Read decimal number. */
7592 val = c - '0';
7593 while ((c = fgetc (fp)) != EOF && isdigit (c))
7594 val = 10 * val + c - '0';
7595 break;
7597 else
7598 break;
7601 return val;
7605 /* Load PBM image IMG for use on frame F. */
7607 static int
7608 pbm_load (f, img)
7609 struct frame *f;
7610 struct image *img;
7612 FILE *fp;
7613 char magic[2];
7614 int raw_p, x, y;
7615 int width, height, max_color_idx = 0, value;
7616 XImage *ximg;
7617 Lisp_Object file, specified_file;
7618 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7619 struct gcpro gcpro1;
7621 specified_file = image_spec_value (img->spec, QCfile, NULL);
7622 file = x_find_image_file (specified_file);
7623 GCPRO1 (file);
7624 if (!STRINGP (file))
7626 image_error ("Cannot find image file %s", specified_file, Qnil);
7627 UNGCPRO;
7628 return 0;
7631 fp = fopen (XSTRING (file)->data, "r");
7632 if (fp == NULL)
7634 UNGCPRO;
7635 return 0;
7638 /* Read first two characters. */
7639 if (fread (magic, sizeof *magic, 2, fp) != 2)
7641 fclose (fp);
7642 image_error ("Not a PBM image file: %s", file, Qnil);
7643 UNGCPRO;
7644 return 0;
7647 if (*magic != 'P')
7649 fclose (fp);
7650 image_error ("Not a PBM image file: %s", file, Qnil);
7651 UNGCPRO;
7652 return 0;
7655 switch (magic[1])
7657 case '1':
7658 raw_p = 0, type = PBM_MONO;
7659 break;
7661 case '2':
7662 raw_p = 0, type = PBM_GRAY;
7663 break;
7665 case '3':
7666 raw_p = 0, type = PBM_COLOR;
7667 break;
7669 case '4':
7670 raw_p = 1, type = PBM_MONO;
7671 break;
7673 case '5':
7674 raw_p = 1, type = PBM_GRAY;
7675 break;
7677 case '6':
7678 raw_p = 1, type = PBM_COLOR;
7679 break;
7681 default:
7682 fclose (fp);
7683 image_error ("Not a PBM image file: %s", file, Qnil);
7684 UNGCPRO;
7685 return 0;
7688 /* Read width, height, maximum color-component. Characters
7689 starting with `#' up to the end of a line are ignored. */
7690 width = pbm_scan_number (fp);
7691 height = pbm_scan_number (fp);
7693 if (type != PBM_MONO)
7695 max_color_idx = pbm_scan_number (fp);
7696 if (raw_p && max_color_idx > 255)
7697 max_color_idx = 255;
7700 if (width < 0 || height < 0
7701 || (type != PBM_MONO && max_color_idx < 0))
7703 fclose (fp);
7704 UNGCPRO;
7705 return 0;
7708 BLOCK_INPUT;
7709 if (!x_create_x_image_and_pixmap (f, file, width, height, 0,
7710 &ximg, &img->pixmap))
7712 fclose (fp);
7713 UNBLOCK_INPUT;
7714 UNGCPRO;
7715 return 0;
7718 /* Initialize the color hash table. */
7719 init_color_table ();
7721 if (type == PBM_MONO)
7723 int c = 0, g;
7725 for (y = 0; y < height; ++y)
7726 for (x = 0; x < width; ++x)
7728 if (raw_p)
7730 if ((x & 7) == 0)
7731 c = fgetc (fp);
7732 g = c & 0x80;
7733 c <<= 1;
7735 else
7736 g = pbm_scan_number (fp);
7738 XPutPixel (ximg, x, y, (g
7739 ? FRAME_FOREGROUND_PIXEL (f)
7740 : FRAME_BACKGROUND_PIXEL (f)));
7743 else
7745 for (y = 0; y < height; ++y)
7746 for (x = 0; x < width; ++x)
7748 int r, g, b;
7750 if (type == PBM_GRAY)
7751 r = g = b = raw_p ? fgetc (fp) : pbm_scan_number (fp);
7752 else if (raw_p)
7754 r = fgetc (fp);
7755 g = fgetc (fp);
7756 b = fgetc (fp);
7758 else
7760 r = pbm_scan_number (fp);
7761 g = pbm_scan_number (fp);
7762 b = pbm_scan_number (fp);
7765 if (r < 0 || g < 0 || b < 0)
7767 fclose (fp);
7768 xfree (ximg->data);
7769 ximg->data = NULL;
7770 XDestroyImage (ximg);
7771 UNBLOCK_INPUT;
7772 image_error ("Invalid pixel value in file `%s'",
7773 file, Qnil);
7774 UNGCPRO;
7775 return 0;
7778 /* RGB values are now in the range 0..max_color_idx.
7779 Scale this to the range 0..0xffff supported by X. */
7780 r = (double) r * 65535 / max_color_idx;
7781 g = (double) g * 65535 / max_color_idx;
7782 b = (double) b * 65535 / max_color_idx;
7783 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7787 fclose (fp);
7789 /* Store in IMG->colors the colors allocated for the image, and
7790 free the color table. */
7791 img->colors = colors_in_color_table (&img->ncolors);
7792 free_color_table ();
7794 /* Put the image into a pixmap. */
7795 x_put_x_image (f, ximg, img->pixmap, width, height);
7796 x_destroy_x_image (ximg);
7797 UNBLOCK_INPUT;
7799 img->width = width;
7800 img->height = height;
7802 UNGCPRO;
7803 return 1;
7808 /***********************************************************************
7810 ***********************************************************************/
7812 #if HAVE_PNG
7814 #include <png.h>
7816 /* Function prototypes. */
7818 static int png_image_p P_ ((Lisp_Object object));
7819 static int png_load P_ ((struct frame *f, struct image *img));
7821 /* The symbol `png' identifying images of this type. */
7823 Lisp_Object Qpng;
7825 /* Indices of image specification fields in png_format, below. */
7827 enum png_keyword_index
7829 PNG_TYPE,
7830 PNG_FILE,
7831 PNG_ASCENT,
7832 PNG_MARGIN,
7833 PNG_RELIEF,
7834 PNG_ALGORITHM,
7835 PNG_HEURISTIC_MASK,
7836 PNG_LAST
7839 /* Vector of image_keyword structures describing the format
7840 of valid user-defined image specifications. */
7842 static struct image_keyword png_format[PNG_LAST] =
7844 {":type", IMAGE_SYMBOL_VALUE, 1},
7845 {":file", IMAGE_STRING_VALUE, 1},
7846 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7847 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7848 {":relief", IMAGE_INTEGER_VALUE, 0},
7849 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7850 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7853 /* Structure describing the image type `gif'. */
7855 static struct image_type png_type =
7857 &Qpng,
7858 png_image_p,
7859 png_load,
7860 x_clear_image,
7861 NULL
7865 /* Return non-zero if OBJECT is a valid PNG image specification. */
7867 static int
7868 png_image_p (object)
7869 Lisp_Object object;
7871 struct image_keyword fmt[PNG_LAST];
7872 bcopy (png_format, fmt, sizeof fmt);
7874 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng, 1)
7875 || (fmt[PNG_ASCENT].count
7876 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
7877 return 0;
7878 return 1;
7882 /* Error and warning handlers installed when the PNG library
7883 is initialized. */
7885 static void
7886 my_png_error (png_ptr, msg)
7887 png_struct *png_ptr;
7888 char *msg;
7890 xassert (png_ptr != NULL);
7891 image_error ("PNG error: %s", build_string (msg), Qnil);
7892 longjmp (png_ptr->jmpbuf, 1);
7896 static void
7897 my_png_warning (png_ptr, msg)
7898 png_struct *png_ptr;
7899 char *msg;
7901 xassert (png_ptr != NULL);
7902 image_error ("PNG warning: %s", build_string (msg), Qnil);
7906 /* Load PNG image IMG for use on frame F. Value is non-zero if
7907 successful. */
7909 static int
7910 png_load (f, img)
7911 struct frame *f;
7912 struct image *img;
7914 Lisp_Object file, specified_file;
7915 int rc, x, y, i;
7916 XImage *ximg, *mask_img = NULL;
7917 struct gcpro gcpro1;
7918 png_struct *png_ptr = NULL;
7919 png_info *info_ptr = NULL, *end_info = NULL;
7920 FILE *fp;
7921 png_byte sig[8];
7922 png_byte *pixels = NULL;
7923 png_byte **rows = NULL;
7924 png_uint_32 width, height;
7925 int bit_depth, color_type, interlace_type;
7926 png_byte channels;
7927 png_uint_32 row_bytes;
7928 int transparent_p;
7929 char *gamma_str;
7930 double screen_gamma, image_gamma;
7931 int intent;
7933 /* Find out what file to load. */
7934 specified_file = image_spec_value (img->spec, QCfile, NULL);
7935 file = x_find_image_file (specified_file);
7936 GCPRO1 (file);
7937 if (!STRINGP (file))
7939 image_error ("Cannot find image file %s", specified_file, Qnil);
7940 UNGCPRO;
7941 return 0;
7944 /* Open the image file. */
7945 fp = fopen (XSTRING (file)->data, "rb");
7946 if (!fp)
7948 image_error ("Cannot open image file %s", file, Qnil);
7949 UNGCPRO;
7950 fclose (fp);
7951 return 0;
7954 /* Check PNG signature. */
7955 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7956 || !png_check_sig (sig, sizeof sig))
7958 image_error ("Not a PNG file: %s", file, Qnil);
7959 UNGCPRO;
7960 fclose (fp);
7961 return 0;
7964 /* Initialize read and info structs for PNG lib. */
7965 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7966 my_png_error, my_png_warning);
7967 if (!png_ptr)
7969 fclose (fp);
7970 UNGCPRO;
7971 return 0;
7974 info_ptr = png_create_info_struct (png_ptr);
7975 if (!info_ptr)
7977 png_destroy_read_struct (&png_ptr, NULL, NULL);
7978 fclose (fp);
7979 UNGCPRO;
7980 return 0;
7983 end_info = png_create_info_struct (png_ptr);
7984 if (!end_info)
7986 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7987 fclose (fp);
7988 UNGCPRO;
7989 return 0;
7992 /* Set error jump-back. We come back here when the PNG library
7993 detects an error. */
7994 if (setjmp (png_ptr->jmpbuf))
7996 error:
7997 if (png_ptr)
7998 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7999 xfree (pixels);
8000 xfree (rows);
8001 if (fp)
8002 fclose (fp);
8003 UNGCPRO;
8004 return 0;
8007 /* Read image info. */
8008 png_init_io (png_ptr, fp);
8009 png_set_sig_bytes (png_ptr, sizeof sig);
8010 png_read_info (png_ptr, info_ptr);
8011 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8012 &interlace_type, NULL, NULL);
8014 /* If image contains simply transparency data, we prefer to
8015 construct a clipping mask. */
8016 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8017 transparent_p = 1;
8018 else
8019 transparent_p = 0;
8021 /* This function is easier to write if we only have to handle
8022 one data format: RGB or RGBA with 8 bits per channel. Let's
8023 transform other formats into that format. */
8025 /* Strip more than 8 bits per channel. */
8026 if (bit_depth == 16)
8027 png_set_strip_16 (png_ptr);
8029 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8030 if available. */
8031 png_set_expand (png_ptr);
8033 /* Convert grayscale images to RGB. */
8034 if (color_type == PNG_COLOR_TYPE_GRAY
8035 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8036 png_set_gray_to_rgb (png_ptr);
8038 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8039 gamma_str = getenv ("SCREEN_GAMMA");
8040 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8042 /* Tell the PNG lib to handle gamma correction for us. */
8044 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8045 /* There is a special chunk in the image specifying the gamma. */
8046 png_set_sRGB (png_ptr, info_ptr, intent);
8047 else if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8048 /* Image contains gamma information. */
8049 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8050 else
8051 /* Use a default of 0.5 for the image gamma. */
8052 png_set_gamma (png_ptr, screen_gamma, 0.5);
8054 /* Handle alpha channel by combining the image with a background
8055 color. Do this only if a real alpha channel is supplied. For
8056 simple transparency, we prefer a clipping mask. */
8057 if (!transparent_p)
8059 png_color_16 *image_background;
8061 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
8062 /* Image contains a background color with which to
8063 combine the image. */
8064 png_set_background (png_ptr, image_background,
8065 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8066 else
8068 /* Image does not contain a background color with which
8069 to combine the image data via an alpha channel. Use
8070 the frame's background instead. */
8071 XColor color;
8072 Colormap cmap;
8073 png_color_16 frame_background;
8075 BLOCK_INPUT;
8076 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
8077 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8078 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
8079 UNBLOCK_INPUT;
8081 bzero (&frame_background, sizeof frame_background);
8082 frame_background.red = color.red;
8083 frame_background.green = color.green;
8084 frame_background.blue = color.blue;
8086 png_set_background (png_ptr, &frame_background,
8087 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8091 /* Update info structure. */
8092 png_read_update_info (png_ptr, info_ptr);
8094 /* Get number of channels. Valid values are 1 for grayscale images
8095 and images with a palette, 2 for grayscale images with transparency
8096 information (alpha channel), 3 for RGB images, and 4 for RGB
8097 images with alpha channel, i.e. RGBA. If conversions above were
8098 sufficient we should only have 3 or 4 channels here. */
8099 channels = png_get_channels (png_ptr, info_ptr);
8100 xassert (channels == 3 || channels == 4);
8102 /* Number of bytes needed for one row of the image. */
8103 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8105 /* Allocate memory for the image. */
8106 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8107 rows = (png_byte **) xmalloc (height * sizeof *rows);
8108 for (i = 0; i < height; ++i)
8109 rows[i] = pixels + i * row_bytes;
8111 /* Read the entire image. */
8112 png_read_image (png_ptr, rows);
8113 png_read_end (png_ptr, info_ptr);
8114 fclose (fp);
8115 fp = NULL;
8117 BLOCK_INPUT;
8119 /* Create the X image and pixmap. */
8120 if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
8121 &img->pixmap))
8123 UNBLOCK_INPUT;
8124 goto error;
8127 /* Create an image and pixmap serving as mask if the PNG image
8128 contains an alpha channel. */
8129 if (channels == 4
8130 && !transparent_p
8131 && !x_create_x_image_and_pixmap (f, file, width, height, 1,
8132 &mask_img, &img->mask))
8134 x_destroy_x_image (ximg);
8135 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8136 img->pixmap = 0;
8137 UNBLOCK_INPUT;
8138 goto error;
8141 /* Fill the X image and mask from PNG data. */
8142 init_color_table ();
8144 for (y = 0; y < height; ++y)
8146 png_byte *p = rows[y];
8148 for (x = 0; x < width; ++x)
8150 unsigned r, g, b;
8152 r = *p++ << 8;
8153 g = *p++ << 8;
8154 b = *p++ << 8;
8155 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8157 /* An alpha channel, aka mask channel, associates variable
8158 transparency with an image. Where other image formats
8159 support binary transparency---fully transparent or fully
8160 opaque---PNG allows up to 254 levels of partial transparency.
8161 The PNG library implements partial transparency by combining
8162 the image with a specified background color.
8164 I'm not sure how to handle this here nicely: because the
8165 background on which the image is displayed may change, for
8166 real alpha channel support, it would be necessary to create
8167 a new image for each possible background.
8169 What I'm doing now is that a mask is created if we have
8170 boolean transparency information. Otherwise I'm using
8171 the frame's background color to combine the image with. */
8173 if (channels == 4)
8175 if (mask_img)
8176 XPutPixel (mask_img, x, y, *p > 0);
8177 ++p;
8182 /* Remember colors allocated for this image. */
8183 img->colors = colors_in_color_table (&img->ncolors);
8184 free_color_table ();
8186 /* Clean up. */
8187 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8188 xfree (rows);
8189 xfree (pixels);
8191 img->width = width;
8192 img->height = height;
8194 /* Put the image into the pixmap, then free the X image and its buffer. */
8195 x_put_x_image (f, ximg, img->pixmap, width, height);
8196 x_destroy_x_image (ximg);
8198 /* Same for the mask. */
8199 if (mask_img)
8201 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8202 x_destroy_x_image (mask_img);
8205 UNBLOCK_INPUT;
8206 UNGCPRO;
8207 return 1;
8210 #endif /* HAVE_PNG != 0 */
8214 /***********************************************************************
8215 JPEG
8216 ***********************************************************************/
8218 #if HAVE_JPEG
8220 #include <jpeglib.h>
8221 #include <jerror.h>
8222 #include <setjmp.h>
8224 static int jpeg_image_p P_ ((Lisp_Object object));
8225 static int jpeg_load P_ ((struct frame *f, struct image *img));
8227 /* The symbol `jpeg' identifying images of this type. */
8229 Lisp_Object Qjpeg;
8231 /* Indices of image specification fields in gs_format, below. */
8233 enum jpeg_keyword_index
8235 JPEG_TYPE,
8236 JPEG_FILE,
8237 JPEG_ASCENT,
8238 JPEG_MARGIN,
8239 JPEG_RELIEF,
8240 JPEG_ALGORITHM,
8241 JPEG_HEURISTIC_MASK,
8242 JPEG_LAST
8245 /* Vector of image_keyword structures describing the format
8246 of valid user-defined image specifications. */
8248 static struct image_keyword jpeg_format[JPEG_LAST] =
8250 {":type", IMAGE_SYMBOL_VALUE, 1},
8251 {":file", IMAGE_STRING_VALUE, 1},
8252 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8253 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8254 {":relief", IMAGE_INTEGER_VALUE, 0},
8255 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8256 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8259 /* Structure describing the image type `jpeg'. */
8261 static struct image_type jpeg_type =
8263 &Qjpeg,
8264 jpeg_image_p,
8265 jpeg_load,
8266 x_clear_image,
8267 NULL
8271 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8273 static int
8274 jpeg_image_p (object)
8275 Lisp_Object object;
8277 struct image_keyword fmt[JPEG_LAST];
8279 bcopy (jpeg_format, fmt, sizeof fmt);
8281 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg, 0)
8282 || (fmt[JPEG_ASCENT].count
8283 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
8284 return 0;
8285 return 1;
8288 struct my_jpeg_error_mgr
8290 struct jpeg_error_mgr pub;
8291 jmp_buf setjmp_buffer;
8294 static void
8295 my_error_exit (cinfo)
8296 j_common_ptr cinfo;
8298 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8299 longjmp (mgr->setjmp_buffer, 1);
8302 /* Load image IMG for use on frame F. Patterned after example.c
8303 from the JPEG lib. */
8305 static int
8306 jpeg_load (f, img)
8307 struct frame *f;
8308 struct image *img;
8310 struct jpeg_decompress_struct cinfo;
8311 struct my_jpeg_error_mgr mgr;
8312 Lisp_Object file, specified_file;
8313 FILE *fp;
8314 JSAMPARRAY buffer;
8315 int row_stride, x, y;
8316 XImage *ximg = NULL;
8317 int rc, value;
8318 unsigned long *colors;
8319 int width, height;
8320 struct gcpro gcpro1;
8322 /* Open the JPEG file. */
8323 specified_file = image_spec_value (img->spec, QCfile, NULL);
8324 file = x_find_image_file (specified_file);
8325 GCPRO1 (file);
8326 if (!STRINGP (file))
8328 image_error ("Cannot find image file %s", specified_file, Qnil);
8329 UNGCPRO;
8330 return 0;
8333 fp = fopen (XSTRING (file)->data, "r");
8334 if (fp == NULL)
8336 image_error ("Cannot open `%s'", file, Qnil);
8337 UNGCPRO;
8338 return 0;
8341 /* Customize libjpeg's error handling to call my_error_exit
8342 when an error is detected. This function will perform
8343 a longjmp. */
8344 mgr.pub.error_exit = my_error_exit;
8345 cinfo.err = jpeg_std_error (&mgr.pub);
8347 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8349 if (rc == 1)
8351 /* Called from my_error_exit. Display a JPEG error. */
8352 char buffer[JMSG_LENGTH_MAX];
8353 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8354 image_error ("Error reading JPEG file `%s': %s", file,
8355 build_string (buffer));
8358 /* Close the input file and destroy the JPEG object. */
8359 fclose (fp);
8360 jpeg_destroy_decompress (&cinfo);
8362 BLOCK_INPUT;
8364 /* If we already have an XImage, free that. */
8365 x_destroy_x_image (ximg);
8367 /* Free pixmap and colors. */
8368 x_clear_image (f, img);
8370 UNBLOCK_INPUT;
8371 UNGCPRO;
8372 return 0;
8375 /* Create the JPEG decompression object. Let it read from fp.
8376 Read the JPEG image header. */
8377 jpeg_create_decompress (&cinfo);
8378 jpeg_stdio_src (&cinfo, fp);
8379 jpeg_read_header (&cinfo, TRUE);
8381 /* Customize decompression so that color quantization will be used.
8382 Start decompression. */
8383 cinfo.quantize_colors = TRUE;
8384 jpeg_start_decompress (&cinfo);
8385 width = img->width = cinfo.output_width;
8386 height = img->height = cinfo.output_height;
8388 BLOCK_INPUT;
8390 /* Create X image and pixmap. */
8391 if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
8392 &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 fclose (fp);
8452 /* Put the image into the pixmap. */
8453 x_put_x_image (f, ximg, img->pixmap, width, height);
8454 x_destroy_x_image (ximg);
8455 UNBLOCK_INPUT;
8456 UNGCPRO;
8457 return 1;
8460 #endif /* HAVE_JPEG */
8464 /***********************************************************************
8465 TIFF
8466 ***********************************************************************/
8468 #if HAVE_TIFF
8470 #include <tiff34/tiffio.h>
8472 static int tiff_image_p P_ ((Lisp_Object object));
8473 static int tiff_load P_ ((struct frame *f, struct image *img));
8475 /* The symbol `tiff' identifying images of this type. */
8477 Lisp_Object Qtiff;
8479 /* Indices of image specification fields in tiff_format, below. */
8481 enum tiff_keyword_index
8483 TIFF_TYPE,
8484 TIFF_FILE,
8485 TIFF_ASCENT,
8486 TIFF_MARGIN,
8487 TIFF_RELIEF,
8488 TIFF_ALGORITHM,
8489 TIFF_HEURISTIC_MASK,
8490 TIFF_LAST
8493 /* Vector of image_keyword structures describing the format
8494 of valid user-defined image specifications. */
8496 static struct image_keyword tiff_format[TIFF_LAST] =
8498 {":type", IMAGE_SYMBOL_VALUE, 1},
8499 {":file", IMAGE_STRING_VALUE, 1},
8500 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8501 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8502 {":relief", IMAGE_INTEGER_VALUE, 0},
8503 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8504 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8507 /* Structure describing the image type `tiff'. */
8509 static struct image_type tiff_type =
8511 &Qtiff,
8512 tiff_image_p,
8513 tiff_load,
8514 x_clear_image,
8515 NULL
8519 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8521 static int
8522 tiff_image_p (object)
8523 Lisp_Object object;
8525 struct image_keyword fmt[TIFF_LAST];
8526 bcopy (tiff_format, fmt, sizeof fmt);
8528 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff, 1)
8529 || (fmt[TIFF_ASCENT].count
8530 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
8531 return 0;
8532 return 1;
8536 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8537 successful. */
8539 static int
8540 tiff_load (f, img)
8541 struct frame *f;
8542 struct image *img;
8544 Lisp_Object file, specified_file;
8545 TIFF *tiff;
8546 int width, height, x, y;
8547 uint32 *buf;
8548 int rc;
8549 XImage *ximg;
8550 struct gcpro gcpro1;
8552 specified_file = image_spec_value (img->spec, QCfile, NULL);
8553 file = x_find_image_file (specified_file);
8554 GCPRO1 (file);
8555 if (!STRINGP (file))
8557 image_error ("Cannot find image file %s", file, Qnil);
8558 UNGCPRO;
8559 return 0;
8562 /* Try to open the image file. */
8563 tiff = TIFFOpen (XSTRING (file)->data, "r");
8564 if (tiff == NULL)
8566 image_error ("Cannot open `%s'", file, Qnil);
8567 UNGCPRO;
8568 return 0;
8571 /* Get width and height of the image, and allocate a raster buffer
8572 of width x height 32-bit values. */
8573 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8574 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8575 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8577 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8578 TIFFClose (tiff);
8579 if (!rc)
8581 image_error ("Error reading `%s'", file, Qnil);
8582 xfree (buf);
8583 UNGCPRO;
8584 return 0;
8587 BLOCK_INPUT;
8589 /* Create the X image and pixmap. */
8590 if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
8591 &img->pixmap))
8593 UNBLOCK_INPUT;
8594 xfree (buf);
8595 UNGCPRO;
8596 return 0;
8599 /* Initialize the color table. */
8600 init_color_table ();
8602 /* Process the pixel raster. Origin is in the lower-left corner. */
8603 for (y = 0; y < height; ++y)
8605 uint32 *row = buf + y * width;
8607 for (x = 0; x < width; ++x)
8609 uint32 abgr = row[x];
8610 int r = TIFFGetR (abgr) << 8;
8611 int g = TIFFGetG (abgr) << 8;
8612 int b = TIFFGetB (abgr) << 8;
8613 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8617 /* Remember the colors allocated for the image. Free the color table. */
8618 img->colors = colors_in_color_table (&img->ncolors);
8619 free_color_table ();
8621 /* Put the image into the pixmap, then free the X image and its buffer. */
8622 x_put_x_image (f, ximg, img->pixmap, width, height);
8623 x_destroy_x_image (ximg);
8624 xfree (buf);
8625 UNBLOCK_INPUT;
8627 img->width = width;
8628 img->height = height;
8630 UNGCPRO;
8631 return 1;
8634 #endif /* HAVE_TIFF != 0 */
8638 /***********************************************************************
8640 ***********************************************************************/
8642 #if HAVE_GIF
8644 #include <gif_lib.h>
8646 static int gif_image_p P_ ((Lisp_Object object));
8647 static int gif_load P_ ((struct frame *f, struct image *img));
8649 /* The symbol `gif' identifying images of this type. */
8651 Lisp_Object Qgif;
8653 /* Indices of image specification fields in gif_format, below. */
8655 enum gif_keyword_index
8657 GIF_TYPE,
8658 GIF_FILE,
8659 GIF_ASCENT,
8660 GIF_MARGIN,
8661 GIF_RELIEF,
8662 GIF_ALGORITHM,
8663 GIF_HEURISTIC_MASK,
8664 GIF_IMAGE,
8665 GIF_LAST
8668 /* Vector of image_keyword structures describing the format
8669 of valid user-defined image specifications. */
8671 static struct image_keyword gif_format[GIF_LAST] =
8673 {":type", IMAGE_SYMBOL_VALUE, 1},
8674 {":file", IMAGE_STRING_VALUE, 1},
8675 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8676 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8677 {":relief", IMAGE_INTEGER_VALUE, 0},
8678 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8679 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8680 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
8683 /* Structure describing the image type `gif'. */
8685 static struct image_type gif_type =
8687 &Qgif,
8688 gif_image_p,
8689 gif_load,
8690 x_clear_image,
8691 NULL
8695 /* Return non-zero if OBJECT is a valid GIF image specification. */
8697 static int
8698 gif_image_p (object)
8699 Lisp_Object object;
8701 struct image_keyword fmt[GIF_LAST];
8702 bcopy (gif_format, fmt, sizeof fmt);
8704 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif, 1)
8705 || (fmt[GIF_ASCENT].count
8706 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
8707 return 0;
8708 return 1;
8712 /* Load GIF image IMG for use on frame F. Value is non-zero if
8713 successful. */
8715 static int
8716 gif_load (f, img)
8717 struct frame *f;
8718 struct image *img;
8720 Lisp_Object file, specified_file;
8721 int rc, width, height, x, y, i;
8722 XImage *ximg;
8723 ColorMapObject *gif_color_map;
8724 unsigned long pixel_colors[256];
8725 GifFileType *gif;
8726 struct gcpro gcpro1;
8727 Lisp_Object image;
8728 int ino, image_left, image_top, image_width, image_height;
8729 int bg;
8731 specified_file = image_spec_value (img->spec, QCfile, NULL);
8732 file = x_find_image_file (specified_file);
8733 GCPRO1 (file);
8734 if (!STRINGP (file))
8736 image_error ("Cannot find image file %s", specified_file, Qnil);
8737 UNGCPRO;
8738 return 0;
8741 /* Open the GIF file. */
8742 gif = DGifOpenFileName (XSTRING (file)->data);
8743 if (gif == NULL)
8745 image_error ("Cannot open `%s'", file, Qnil);
8746 UNGCPRO;
8747 return 0;
8750 /* Read entire contents. */
8751 rc = DGifSlurp (gif);
8752 if (rc == GIF_ERROR)
8754 image_error ("Error reading `%s'", file, Qnil);
8755 DGifCloseFile (gif);
8756 UNGCPRO;
8757 return 0;
8760 image = image_spec_value (img->spec, QCimage, NULL);
8761 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8762 if (ino >= gif->ImageCount)
8764 image_error ("Invalid image number `%s'", image, Qnil);
8765 DGifCloseFile (gif);
8766 UNGCPRO;
8767 return 0;
8770 width = img->width = gif->SWidth;
8771 height = img->height = gif->SHeight;
8773 BLOCK_INPUT;
8775 /* Create the X image and pixmap. */
8776 if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
8777 &img->pixmap))
8779 UNBLOCK_INPUT;
8780 DGifCloseFile (gif);
8781 UNGCPRO;
8782 return 0;
8785 /* Allocate colors. */
8786 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8787 if (!gif_color_map)
8788 gif_color_map = gif->SColorMap;
8789 init_color_table ();
8790 bzero (pixel_colors, sizeof pixel_colors);
8792 for (i = 0; i < gif_color_map->ColorCount; ++i)
8794 int r = gif_color_map->Colors[i].Red << 8;
8795 int g = gif_color_map->Colors[i].Green << 8;
8796 int b = gif_color_map->Colors[i].Blue << 8;
8797 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8800 img->colors = colors_in_color_table (&img->ncolors);
8801 free_color_table ();
8803 /* Clear the part of the screen image that are not covered by
8804 the image from the GIF file. Full animated GIF support
8805 requires more than can be done here (see the gif89 spec,
8806 disposal methods). Let's simply assume that the part
8807 not covered by a sub-image is in the frame's background color. */
8808 image_top = gif->SavedImages[ino].ImageDesc.Top;
8809 image_left = gif->SavedImages[ino].ImageDesc.Left;
8810 image_width = gif->SavedImages[ino].ImageDesc.Width;
8811 image_height = gif->SavedImages[ino].ImageDesc.Height;
8813 for (y = 0; y < image_top; ++y)
8814 for (x = 0; x < width; ++x)
8815 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8817 for (y = image_top + image_height; y < height; ++y)
8818 for (x = 0; x < width; ++x)
8819 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8821 for (y = image_top; y < image_top + image_height; ++y)
8823 for (x = 0; x < image_left; ++x)
8824 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8825 for (x = image_left + image_width; x < width; ++x)
8826 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8829 /* Read the GIF image into the X image. */
8830 if (gif->SavedImages[ino].ImageDesc.Interlace)
8832 static int interlace_start[] = {0, 4, 2, 1};
8833 static int interlace_increment[] = {8, 8, 4, 2};
8834 int pass, inc;
8836 for (pass = 0; pass < 4; ++pass)
8838 inc = interlace_increment[pass];
8839 for (y = interlace_start[pass]; y < image_height; y += inc)
8840 for (x = 0; x < image_width; ++x)
8842 unsigned i = gif->SavedImages[ino].RasterBits[y * image_width + x];
8843 XPutPixel (ximg, x + image_left, y + image_top,
8844 pixel_colors[i]);
8848 else
8850 for (y = 0; y < image_height; ++y)
8851 for (x = 0; x < image_width; ++x)
8853 unsigned i = gif->SavedImages[ino].RasterBits[y * image_width + x];
8854 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
8858 DGifCloseFile (gif);
8860 /* Put the image into the pixmap, then free the X image and its buffer. */
8861 x_put_x_image (f, ximg, img->pixmap, width, height);
8862 x_destroy_x_image (ximg);
8863 UNBLOCK_INPUT;
8865 UNGCPRO;
8866 return 1;
8869 #endif /* HAVE_GIF != 0 */
8873 /***********************************************************************
8874 Ghostscript
8875 ***********************************************************************/
8877 static int gs_image_p P_ ((Lisp_Object object));
8878 static int gs_load P_ ((struct frame *f, struct image *img));
8879 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8881 /* The symbol `ghostscript' identifying images of this type. */
8883 Lisp_Object Qghostscript;
8885 /* Keyword symbols. */
8887 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8889 /* Indices of image specification fields in gs_format, below. */
8891 enum gs_keyword_index
8893 GS_TYPE,
8894 GS_PT_WIDTH,
8895 GS_PT_HEIGHT,
8896 GS_FILE,
8897 GS_LOADER,
8898 GS_BOUNDING_BOX,
8899 GS_ASCENT,
8900 GS_MARGIN,
8901 GS_RELIEF,
8902 GS_ALGORITHM,
8903 GS_HEURISTIC_MASK,
8904 GS_LAST
8907 /* Vector of image_keyword structures describing the format
8908 of valid user-defined image specifications. */
8910 static struct image_keyword gs_format[GS_LAST] =
8912 {":type", IMAGE_SYMBOL_VALUE, 1},
8913 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8914 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8915 {":file", IMAGE_STRING_VALUE, 1},
8916 {":loader", IMAGE_FUNCTION_VALUE, 0},
8917 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8918 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8919 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8920 {":relief", IMAGE_INTEGER_VALUE, 0},
8921 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8922 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8925 /* Structure describing the image type `ghostscript'. */
8927 static struct image_type gs_type =
8929 &Qghostscript,
8930 gs_image_p,
8931 gs_load,
8932 gs_clear_image,
8933 NULL
8937 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8939 static void
8940 gs_clear_image (f, img)
8941 struct frame *f;
8942 struct image *img;
8944 /* IMG->data.ptr_val may contain a recorded colormap. */
8945 xfree (img->data.ptr_val);
8946 x_clear_image (f, img);
8950 /* Return non-zero if OBJECT is a valid Ghostscript image
8951 specification. */
8953 static int
8954 gs_image_p (object)
8955 Lisp_Object object;
8957 struct image_keyword fmt[GS_LAST];
8958 Lisp_Object tem;
8959 int i;
8961 bcopy (gs_format, fmt, sizeof fmt);
8963 if (!parse_image_spec (object, fmt, GS_LAST, Qghostscript, 1)
8964 || (fmt[GS_ASCENT].count
8965 && XFASTINT (fmt[GS_ASCENT].value) > 100))
8966 return 0;
8968 /* Bounding box must be a list or vector containing 4 integers. */
8969 tem = fmt[GS_BOUNDING_BOX].value;
8970 if (CONSP (tem))
8972 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8973 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8974 return 0;
8975 if (!NILP (tem))
8976 return 0;
8978 else if (VECTORP (tem))
8980 if (XVECTOR (tem)->size != 4)
8981 return 0;
8982 for (i = 0; i < 4; ++i)
8983 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8984 return 0;
8986 else
8987 return 0;
8989 return 1;
8993 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8994 if successful. */
8996 static int
8997 gs_load (f, img)
8998 struct frame *f;
8999 struct image *img;
9001 char buffer[100];
9002 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9003 struct gcpro gcpro1, gcpro2;
9004 Lisp_Object frame;
9005 double in_width, in_height;
9006 Lisp_Object pixel_colors = Qnil;
9008 /* Compute pixel size of pixmap needed from the given size in the
9009 image specification. Sizes in the specification are in pt. 1 pt
9010 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9011 info. */
9012 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9013 in_width = XFASTINT (pt_width) / 72.0;
9014 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9015 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9016 in_height = XFASTINT (pt_height) / 72.0;
9017 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9019 /* Create the pixmap. */
9020 BLOCK_INPUT;
9021 xassert (img->pixmap == 0);
9022 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9023 img->width, img->height,
9024 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9025 UNBLOCK_INPUT;
9027 if (!img->pixmap)
9029 image_error ("Unable to create pixmap for `%s'",
9030 image_spec_value (img->spec, QCfile, NULL), Qnil);
9031 return 0;
9034 /* Call the loader to fill the pixmap. It returns a process object
9035 if successful. We do not record_unwind_protect here because
9036 other places in redisplay like calling window scroll functions
9037 don't either. Let the Lisp loader use `unwind-protect' instead. */
9038 GCPRO2 (window_and_pixmap_id, pixel_colors);
9040 sprintf (buffer, "%lu %lu",
9041 (unsigned long) FRAME_X_WINDOW (f),
9042 (unsigned long) img->pixmap);
9043 window_and_pixmap_id = build_string (buffer);
9045 sprintf (buffer, "%lu %lu",
9046 FRAME_FOREGROUND_PIXEL (f),
9047 FRAME_BACKGROUND_PIXEL (f));
9048 pixel_colors = build_string (buffer);
9050 XSETFRAME (frame, f);
9051 loader = image_spec_value (img->spec, QCloader, NULL);
9052 if (NILP (loader))
9053 loader = intern ("gs-load-image");
9055 img->data.lisp_val = call6 (loader, frame, img->spec,
9056 make_number (img->width),
9057 make_number (img->height),
9058 window_and_pixmap_id,
9059 pixel_colors);
9060 UNGCPRO;
9061 return PROCESSP (img->data.lisp_val);
9065 /* Kill the Ghostscript process that was started to fill PIXMAP on
9066 frame F. Called from XTread_socket when receiving an event
9067 telling Emacs that Ghostscript has finished drawing. */
9069 void
9070 x_kill_gs_process (pixmap, f)
9071 Pixmap pixmap;
9072 struct frame *f;
9074 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9075 int class, i;
9076 struct image *img;
9078 /* Find the image containing PIXMAP. */
9079 for (i = 0; i < c->used; ++i)
9080 if (c->images[i]->pixmap == pixmap)
9081 break;
9083 /* Kill the GS process. We should have found PIXMAP in the image
9084 cache and its image should contain a process object. */
9085 xassert (i < c->used);
9086 img = c->images[i];
9087 xassert (PROCESSP (img->data.lisp_val));
9088 Fkill_process (img->data.lisp_val, Qnil);
9089 img->data.lisp_val = Qnil;
9091 /* On displays with a mutable colormap, figure out the colors
9092 allocated for the image by looking at the pixels of an XImage for
9093 img->pixmap. */
9094 class = FRAME_X_DISPLAY_INFO (f)->visual->class;
9095 if (class != StaticColor && class != StaticGray && class != TrueColor)
9097 XImage *ximg;
9099 BLOCK_INPUT;
9101 /* Try to get an XImage for img->pixmep. */
9102 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9103 0, 0, img->width, img->height, ~0, ZPixmap);
9104 if (ximg)
9106 int x, y;
9108 /* Initialize the color table. */
9109 init_color_table ();
9111 /* For each pixel of the image, look its color up in the
9112 color table. After having done so, the color table will
9113 contain an entry for each color used by the image. */
9114 for (y = 0; y < img->height; ++y)
9115 for (x = 0; x < img->width; ++x)
9117 unsigned long pixel = XGetPixel (ximg, x, y);
9118 lookup_pixel_color (f, pixel);
9121 /* Record colors in the image. Free color table and XImage. */
9122 img->colors = colors_in_color_table (&img->ncolors);
9123 free_color_table ();
9124 XDestroyImage (ximg);
9126 #if 0 /* This doesn't seem to be the case. If we free the colors
9127 here, we get a BadAccess later in x_clear_image when
9128 freeing the colors. */
9129 /* We have allocated colors once, but Ghostscript has also
9130 allocated colors on behalf of us. So, to get the
9131 reference counts right, free them once. */
9132 if (img->ncolors)
9134 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
9135 XFreeColors (FRAME_X_DISPLAY (f), cmap,
9136 img->colors, img->ncolors, 0);
9138 #endif
9140 else
9141 image_error ("Cannot get X image of `%s'; colors will not be freed",
9142 image_spec_value (img->spec, QCfile, NULL), Qnil);
9144 UNBLOCK_INPUT;
9150 /***********************************************************************
9151 Window properties
9152 ***********************************************************************/
9154 DEFUN ("x-change-window-property", Fx_change_window_property,
9155 Sx_change_window_property, 2, 3, 0,
9156 "Change window property PROP to VALUE on the X window of FRAME.\n\
9157 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9158 selected frame. Value is VALUE.")
9159 (prop, value, frame)
9160 Lisp_Object frame, prop, value;
9162 struct frame *f = check_x_frame (frame);
9163 Atom prop_atom;
9165 CHECK_STRING (prop, 1);
9166 CHECK_STRING (value, 2);
9168 BLOCK_INPUT;
9169 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9170 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9171 prop_atom, XA_STRING, 8, PropModeReplace,
9172 XSTRING (value)->data, XSTRING (value)->size);
9174 /* Make sure the property is set when we return. */
9175 XFlush (FRAME_X_DISPLAY (f));
9176 UNBLOCK_INPUT;
9178 return value;
9182 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9183 Sx_delete_window_property, 1, 2, 0,
9184 "Remove window property PROP from X window of FRAME.\n\
9185 FRAME nil or omitted means use the selected frame. Value is PROP.")
9186 (prop, frame)
9187 Lisp_Object prop, frame;
9189 struct frame *f = check_x_frame (frame);
9190 Atom prop_atom;
9192 CHECK_STRING (prop, 1);
9193 BLOCK_INPUT;
9194 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9195 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9197 /* Make sure the property is removed when we return. */
9198 XFlush (FRAME_X_DISPLAY (f));
9199 UNBLOCK_INPUT;
9201 return prop;
9205 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9206 1, 2, 0,
9207 "Value is the value of window property PROP on FRAME.\n\
9208 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9209 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9210 value.")
9211 (prop, frame)
9212 Lisp_Object prop, frame;
9214 struct frame *f = check_x_frame (frame);
9215 Atom prop_atom;
9216 int rc;
9217 Lisp_Object prop_value = Qnil;
9218 char *tmp_data = NULL;
9219 Atom actual_type;
9220 int actual_format;
9221 unsigned long actual_size, bytes_remaining;
9223 CHECK_STRING (prop, 1);
9224 BLOCK_INPUT;
9225 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9226 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9227 prop_atom, 0, 0, False, XA_STRING,
9228 &actual_type, &actual_format, &actual_size,
9229 &bytes_remaining, (unsigned char **) &tmp_data);
9230 if (rc == Success)
9232 int size = bytes_remaining;
9234 XFree (tmp_data);
9235 tmp_data = NULL;
9237 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9238 prop_atom, 0, bytes_remaining,
9239 False, XA_STRING,
9240 &actual_type, &actual_format,
9241 &actual_size, &bytes_remaining,
9242 (unsigned char **) &tmp_data);
9243 if (rc == Success)
9244 prop_value = make_string (tmp_data, size);
9246 XFree (tmp_data);
9249 UNBLOCK_INPUT;
9250 return prop_value;
9255 /***********************************************************************
9256 Busy cursor
9257 ***********************************************************************/
9259 /* The implementation partly follows a patch from
9260 F.Pierresteguy@frcl.bull.fr dated 1994. */
9262 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor display until
9263 the next X event is read and we enter XTread_socket again. Setting
9264 it to 1 inhibits busy-cursor display for direct commands. */
9266 int inhibit_busy_cursor;
9268 /* Incremented with each call to x-display-busy-cursor.
9269 Decremented in x-undisplay-busy-cursor. */
9271 static int busy_count;
9274 DEFUN ("x-show-busy-cursor", Fx_show_busy_cursor,
9275 Sx_show_busy_cursor, 0, 0, 0,
9276 "Show a busy cursor, if not already shown.\n\
9277 Each call to this function must be matched by a call to\n\
9278 x-undisplay-busy-cursor to make the busy pointer disappear again.")
9281 ++busy_count;
9282 if (busy_count == 1)
9284 Lisp_Object rest, frame;
9286 FOR_EACH_FRAME (rest, frame)
9287 if (FRAME_X_P (XFRAME (frame)))
9289 struct frame *f = XFRAME (frame);
9291 BLOCK_INPUT;
9292 f->output_data.x->busy_p = 1;
9294 if (!f->output_data.x->busy_window)
9296 unsigned long mask = CWCursor;
9297 XSetWindowAttributes attrs;
9299 attrs.cursor = f->output_data.x->busy_cursor;
9300 f->output_data.x->busy_window
9301 = XCreateWindow (FRAME_X_DISPLAY (f),
9302 FRAME_OUTER_WINDOW (f),
9303 0, 0, 32000, 32000, 0, 0,
9304 InputOnly, CopyFromParent,
9305 mask, &attrs);
9308 XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
9309 UNBLOCK_INPUT;
9313 return Qnil;
9317 DEFUN ("x-hide-busy-cursor", Fx_hide_busy_cursor,
9318 Sx_hide_busy_cursor, 0, 1, 0,
9319 "Hide a busy-cursor.\n\
9320 A busy-cursor will actually be undisplayed when a matching\n\
9321 `x-undisplay-busy-cursor' is called for each `x-display-busy-cursor'\n\
9322 issued. FORCE non-nil means undisplay the busy-cursor forcibly,\n\
9323 not counting calls.")
9324 (force)
9325 Lisp_Object force;
9327 Lisp_Object rest, frame;
9329 if (busy_count == 0)
9330 return Qnil;
9332 if (!NILP (force) && busy_count != 0)
9333 busy_count = 1;
9335 --busy_count;
9336 if (busy_count != 0)
9337 return Qnil;
9339 FOR_EACH_FRAME (rest, frame)
9341 struct frame *f = XFRAME (frame);
9343 if (FRAME_X_P (f)
9344 /* Watch out for newly created frames. */
9345 && f->output_data.x->busy_window)
9348 BLOCK_INPUT;
9349 XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
9350 /* Sync here because XTread_socket looks at the busy_p flag
9351 that is reset to zero below. */
9352 XSync (FRAME_X_DISPLAY (f), False);
9353 UNBLOCK_INPUT;
9354 f->output_data.x->busy_p = 0;
9358 return Qnil;
9363 /***********************************************************************
9364 Tool tips
9365 ***********************************************************************/
9367 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
9368 Lisp_Object));
9370 /* The frame of a currently visible tooltip, or null. */
9372 struct frame *tip_frame;
9374 /* If non-nil, a timer started that hides the last tooltip when it
9375 fires. */
9377 Lisp_Object tip_timer;
9378 Window tip_window;
9380 /* Create a frame for a tooltip on the display described by DPYINFO.
9381 PARMS is a list of frame parameters. Value is the frame. */
9383 static Lisp_Object
9384 x_create_tip_frame (dpyinfo, parms)
9385 struct x_display_info *dpyinfo;
9386 Lisp_Object parms;
9388 struct frame *f;
9389 Lisp_Object frame, tem;
9390 Lisp_Object name;
9391 int minibuffer_only = 0;
9392 long window_prompting = 0;
9393 int width, height;
9394 int count = specpdl_ptr - specpdl;
9395 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9396 struct kboard *kb;
9398 check_x ();
9400 /* Use this general default value to start with until we know if
9401 this frame has a specified name. */
9402 Vx_resource_name = Vinvocation_name;
9404 #ifdef MULTI_KBOARD
9405 kb = dpyinfo->kboard;
9406 #else
9407 kb = &the_only_kboard;
9408 #endif
9410 /* Get the name of the frame to use for resource lookup. */
9411 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
9412 if (!STRINGP (name)
9413 && !EQ (name, Qunbound)
9414 && !NILP (name))
9415 error ("Invalid frame name--not a string or nil");
9416 Vx_resource_name = name;
9418 frame = Qnil;
9419 GCPRO3 (parms, name, frame);
9420 tip_frame = f = make_frame (1);
9421 XSETFRAME (frame, f);
9422 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9424 f->output_method = output_x_window;
9425 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
9426 bzero (f->output_data.x, sizeof (struct x_output));
9427 f->output_data.x->icon_bitmap = -1;
9428 f->output_data.x->fontset = -1;
9429 f->icon_name = Qnil;
9430 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
9431 #ifdef MULTI_KBOARD
9432 FRAME_KBOARD (f) = kb;
9433 #endif
9434 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9435 f->output_data.x->explicit_parent = 0;
9437 /* Set the name; the functions to which we pass f expect the name to
9438 be set. */
9439 if (EQ (name, Qunbound) || NILP (name))
9441 f->name = build_string (dpyinfo->x_id_name);
9442 f->explicit_name = 0;
9444 else
9446 f->name = name;
9447 f->explicit_name = 1;
9448 /* use the frame's title when getting resources for this frame. */
9449 specbind (Qx_resource_name, name);
9452 /* Create fontsets from `global_fontset_alist' before handling fonts. */
9453 for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
9454 fs_register_fontset (f, XCONS (tem)->car);
9456 /* Extract the window parameters from the supplied values
9457 that are needed to determine window geometry. */
9459 Lisp_Object font;
9461 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
9463 BLOCK_INPUT;
9464 /* First, try whatever font the caller has specified. */
9465 if (STRINGP (font))
9467 tem = Fquery_fontset (font, Qnil);
9468 if (STRINGP (tem))
9469 font = x_new_fontset (f, XSTRING (tem)->data);
9470 else
9471 font = x_new_font (f, XSTRING (font)->data);
9474 /* Try out a font which we hope has bold and italic variations. */
9475 if (!STRINGP (font))
9476 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9477 if (!STRINGP (font))
9478 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9479 if (! STRINGP (font))
9480 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9481 if (! STRINGP (font))
9482 /* This was formerly the first thing tried, but it finds too many fonts
9483 and takes too long. */
9484 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9485 /* If those didn't work, look for something which will at least work. */
9486 if (! STRINGP (font))
9487 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9488 UNBLOCK_INPUT;
9489 if (! STRINGP (font))
9490 font = build_string ("fixed");
9492 x_default_parameter (f, parms, Qfont, font,
9493 "font", "Font", RES_TYPE_STRING);
9496 x_default_parameter (f, parms, Qborder_width, make_number (2),
9497 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9499 /* This defaults to 2 in order to match xterm. We recognize either
9500 internalBorderWidth or internalBorder (which is what xterm calls
9501 it). */
9502 if (NILP (Fassq (Qinternal_border_width, parms)))
9504 Lisp_Object value;
9506 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
9507 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9508 if (! EQ (value, Qunbound))
9509 parms = Fcons (Fcons (Qinternal_border_width, value),
9510 parms);
9513 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9514 "internalBorderWidth", "internalBorderWidth",
9515 RES_TYPE_NUMBER);
9517 /* Also do the stuff which must be set before the window exists. */
9518 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9519 "foreground", "Foreground", RES_TYPE_STRING);
9520 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9521 "background", "Background", RES_TYPE_STRING);
9522 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9523 "pointerColor", "Foreground", RES_TYPE_STRING);
9524 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9525 "cursorColor", "Foreground", RES_TYPE_STRING);
9526 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9527 "borderColor", "BorderColor", RES_TYPE_STRING);
9529 /* Init faces before x_default_parameter is called for scroll-bar
9530 parameters because that function calls x_set_scroll_bar_width,
9531 which calls change_frame_size, which calls Fset_window_buffer,
9532 which runs hooks, which call Fvertical_motion. At the end, we
9533 end up in init_iterator with a null face cache, which should not
9534 happen. */
9535 init_frame_faces (f);
9537 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9538 window_prompting = x_figure_window_size (f, parms);
9540 if (window_prompting & XNegative)
9542 if (window_prompting & YNegative)
9543 f->output_data.x->win_gravity = SouthEastGravity;
9544 else
9545 f->output_data.x->win_gravity = NorthEastGravity;
9547 else
9549 if (window_prompting & YNegative)
9550 f->output_data.x->win_gravity = SouthWestGravity;
9551 else
9552 f->output_data.x->win_gravity = NorthWestGravity;
9555 f->output_data.x->size_hint_flags = window_prompting;
9557 XSetWindowAttributes attrs;
9558 unsigned long mask;
9560 BLOCK_INPUT;
9561 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
9562 /* Window managers looks at the override-redirect flag to
9563 determine whether or net to give windows a decoration (Xlib
9564 3.2.8). */
9565 attrs.override_redirect = True;
9566 attrs.save_under = True;
9567 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9568 /* Arrange for getting MapNotify and UnmapNotify events. */
9569 attrs.event_mask = StructureNotifyMask;
9570 tip_window
9571 = FRAME_X_WINDOW (f)
9572 = XCreateWindow (FRAME_X_DISPLAY (f),
9573 FRAME_X_DISPLAY_INFO (f)->root_window,
9574 /* x, y, width, height */
9575 0, 0, 1, 1,
9576 /* Border. */
9578 CopyFromParent, InputOutput, CopyFromParent,
9579 mask, &attrs);
9580 UNBLOCK_INPUT;
9583 x_make_gc (f);
9585 x_default_parameter (f, parms, Qauto_raise, Qnil,
9586 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9587 x_default_parameter (f, parms, Qauto_lower, Qnil,
9588 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9589 x_default_parameter (f, parms, Qcursor_type, Qbox,
9590 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9592 /* Dimensions, especially f->height, must be done via change_frame_size.
9593 Change will not be effected unless different from the current
9594 f->height. */
9595 width = f->width;
9596 height = f->height;
9597 f->height = 0;
9598 SET_FRAME_WIDTH (f, 0);
9599 change_frame_size (f, height, width, 1, 0);
9601 f->no_split = 1;
9603 UNGCPRO;
9605 /* It is now ok to make the frame official even if we get an error
9606 below. And the frame needs to be on Vframe_list or making it
9607 visible won't work. */
9608 Vframe_list = Fcons (frame, Vframe_list);
9610 /* Now that the frame is official, it counts as a reference to
9611 its display. */
9612 FRAME_X_DISPLAY_INFO (f)->reference_count++;
9614 return unbind_to (count, frame);
9618 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 4, 0,
9619 "Show tooltip STRING on frame FRAME.\n\
9620 FRAME nil or omitted means use the selected frame.\n\
9621 PARMS is an optional list of frame parameters which can be\n\
9622 used to change the tooltip's appearance.\n\
9623 Automatically hide the tooltip after TIMEOUT seconds.\n\
9624 TIMEOUT nil means use the default timeout of 5 seconds.")
9625 (string, frame, parms, timeout)
9626 Lisp_Object string, frame, parms;
9628 struct frame *f;
9629 struct window *w;
9630 Window root, child;
9631 struct it it;
9632 Lisp_Object buffer;
9633 struct buffer *old_buffer;
9634 struct text_pos pos;
9635 int i, width, height;
9636 int root_x, root_y, win_x, win_y;
9637 unsigned pmask;
9638 struct gcpro gcpro1, gcpro2, gcpro3;
9639 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9640 int count = specpdl_ptr - specpdl;
9642 specbind (Qinhibit_redisplay, Qt);
9644 GCPRO3 (string, parms, frame);
9646 CHECK_STRING (string, 0);
9647 f = check_x_frame (frame);
9648 if (NILP (timeout))
9649 timeout = make_number (5);
9650 else
9651 CHECK_NATNUM (timeout, 2);
9653 /* Hide a previous tip, if any. */
9654 Fx_hide_tip ();
9656 /* Add default values to frame parameters. */
9657 if (NILP (Fassq (Qname, parms)))
9658 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
9659 if (NILP (Fassq (Qinternal_border_width, parms)))
9660 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
9661 if (NILP (Fassq (Qborder_width, parms)))
9662 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
9663 if (NILP (Fassq (Qborder_color, parms)))
9664 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
9665 if (NILP (Fassq (Qbackground_color, parms)))
9666 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
9667 parms);
9669 /* Create a frame for the tooltip, and record it in the global
9670 variable tip_frame. */
9671 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
9672 tip_frame = f = XFRAME (frame);
9674 /* Set up the frame's root window. Currently we use a size of 80
9675 columns x 40 lines. If someone wants to show a larger tip, he
9676 will loose. I don't think this is a realistic case. */
9677 w = XWINDOW (FRAME_ROOT_WINDOW (f));
9678 w->left = w->top = make_number (0);
9679 w->width = 80;
9680 w->height = 40;
9681 adjust_glyphs (f);
9682 w->pseudo_window_p = 1;
9684 /* Display the tooltip text in a temporary buffer. */
9685 buffer = Fget_buffer_create (build_string (" *tip*"));
9686 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
9687 old_buffer = current_buffer;
9688 set_buffer_internal_1 (XBUFFER (buffer));
9689 Ferase_buffer ();
9690 Finsert (make_number (1), &string);
9691 clear_glyph_matrix (w->desired_matrix);
9692 clear_glyph_matrix (w->current_matrix);
9693 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
9694 try_window (FRAME_ROOT_WINDOW (f), pos);
9696 /* Compute width and height of the tooltip. */
9697 width = height = 0;
9698 for (i = 0; i < w->desired_matrix->nrows; ++i)
9700 struct glyph_row *row = &w->desired_matrix->rows[i];
9701 struct glyph *last;
9702 int row_width;
9704 /* Stop at the first empty row at the end. */
9705 if (!row->enabled_p || !row->displays_text_p)
9706 break;
9708 /* Let the row go over the full width of the frame. */
9709 row->full_width_p = 1;
9711 /* There's a glyph at the end of rows that is use to place
9712 the cursor there. Don't include the width of this glyph. */
9713 if (row->used[TEXT_AREA])
9715 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
9716 row_width = row->pixel_width - last->pixel_width;
9718 else
9719 row_width = row->pixel_width;
9721 height += row->height;
9722 width = max (width, row_width);
9725 /* Add the frame's internal border to the width and height the X
9726 window should have. */
9727 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9728 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9730 /* Move the tooltip window where the mouse pointer is. Resize and
9731 show it. */
9732 BLOCK_INPUT;
9733 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
9734 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
9735 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9736 root_x + 5, root_y - height - 5, width, height);
9737 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9738 UNBLOCK_INPUT;
9740 /* Draw into the window. */
9741 w->must_be_updated_p = 1;
9742 update_single_window (w, 1);
9744 /* Restore original current buffer. */
9745 set_buffer_internal_1 (old_buffer);
9746 windows_or_buffers_changed = old_windows_or_buffers_changed;
9748 /* Let the tip disappear after timeout seconds. */
9749 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
9750 intern ("x-hide-tip"));
9752 return unbind_to (count, Qnil);
9756 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
9757 "Hide the current tooltip, if there is any.\n\
9758 Value is t is tooltip was open, nil otherwise.")
9761 int count = specpdl_ptr - specpdl;
9762 int deleted_p = 0;
9764 specbind (Qinhibit_redisplay, Qt);
9766 if (!NILP (tip_timer))
9768 call1 (intern ("cancel-timer"), tip_timer);
9769 tip_timer = Qnil;
9772 if (tip_frame)
9774 Lisp_Object frame;
9776 XSETFRAME (frame, tip_frame);
9777 Fdelete_frame (frame, Qt);
9778 tip_frame = NULL;
9779 deleted_p = 1;
9782 return unbind_to (count, deleted_p ? Qt : Qnil);
9787 /***********************************************************************
9788 File selection dialog
9789 ***********************************************************************/
9791 #ifdef USE_MOTIF
9793 /* Callback for "OK" and "Cancel" on file selection dialog. */
9795 static void
9796 file_dialog_cb (widget, client_data, call_data)
9797 Widget widget;
9798 XtPointer call_data, client_data;
9800 int *result = (int *) client_data;
9801 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
9802 *result = cb->reason;
9806 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
9807 "Read file name, prompting with PROMPT in directory DIR.\n\
9808 Use a file selection dialog.\n\
9809 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
9810 specified. Don't let the user enter a file name in the file\n\
9811 selection dialog's entry field, if MUSTMATCH is non-nil.")
9812 (prompt, dir, default_filename, mustmatch)
9813 Lisp_Object prompt, dir, default_filename, mustmatch;
9815 int result;
9816 struct frame *f = selected_frame;
9817 Lisp_Object file = Qnil;
9818 Widget dialog, text, list, help;
9819 Arg al[10];
9820 int ac = 0;
9821 extern XtAppContext Xt_app_con;
9822 char *title;
9823 XmString dir_xmstring, pattern_xmstring;
9824 int popup_activated_flag;
9825 int count = specpdl_ptr - specpdl;
9826 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
9828 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
9829 CHECK_STRING (prompt, 0);
9830 CHECK_STRING (dir, 1);
9832 /* Prevent redisplay. */
9833 specbind (Qinhibit_redisplay, Qt);
9835 BLOCK_INPUT;
9837 /* Create the dialog with PROMPT as title, using DIR as initial
9838 directory and using "*" as pattern. */
9839 dir = Fexpand_file_name (dir, Qnil);
9840 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
9841 pattern_xmstring = XmStringCreateLocalized ("*");
9843 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
9844 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
9845 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
9846 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
9847 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
9848 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
9849 "fsb", al, ac);
9850 XmStringFree (dir_xmstring);
9851 XmStringFree (pattern_xmstring);
9853 /* Add callbacks for OK and Cancel. */
9854 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
9855 (XtPointer) &result);
9856 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
9857 (XtPointer) &result);
9859 /* Disable the help button since we can't display help. */
9860 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
9861 XtSetSensitive (help, False);
9863 /* Mark OK button as default. */
9864 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
9865 XmNshowAsDefault, True, NULL);
9867 /* If MUSTMATCH is non-nil, disable the file entry field of the
9868 dialog, so that the user must select a file from the files list
9869 box. We can't remove it because we wouldn't have a way to get at
9870 the result file name, then. */
9871 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
9872 if (!NILP (mustmatch))
9874 Widget label;
9875 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
9876 XtSetSensitive (text, False);
9877 XtSetSensitive (label, False);
9880 /* Manage the dialog, so that list boxes get filled. */
9881 XtManageChild (dialog);
9883 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
9884 must include the path for this to work. */
9885 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
9886 if (STRINGP (default_filename))
9888 XmString default_xmstring;
9889 int item_pos;
9891 default_xmstring
9892 = XmStringCreateLocalized (XSTRING (default_filename)->data);
9894 if (!XmListItemExists (list, default_xmstring))
9896 /* Add a new item if DEFAULT_FILENAME is not in the list. */
9897 XmListAddItem (list, default_xmstring, 0);
9898 item_pos = 0;
9900 else
9901 item_pos = XmListItemPos (list, default_xmstring);
9902 XmStringFree (default_xmstring);
9904 /* Select the item and scroll it into view. */
9905 XmListSelectPos (list, item_pos, True);
9906 XmListSetPos (list, item_pos);
9909 /* Process all events until the user presses Cancel or OK. */
9910 for (result = 0; result == 0;)
9912 XEvent event;
9913 Widget widget, parent;
9915 XtAppNextEvent (Xt_app_con, &event);
9917 /* See if the receiver of the event is one of the widgets of
9918 the file selection dialog. If so, dispatch it. If not,
9919 discard it. */
9920 widget = XtWindowToWidget (event.xany.display, event.xany.window);
9921 parent = widget;
9922 while (parent && parent != dialog)
9923 parent = XtParent (parent);
9925 if (parent == dialog
9926 || (event.type == Expose
9927 && !process_expose_from_menu (event)))
9928 XtDispatchEvent (&event);
9931 /* Get the result. */
9932 if (result == XmCR_OK)
9934 XmString text;
9935 String data;
9937 XtVaGetValues (dialog, XmNtextString, &text, 0);
9938 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
9939 XmStringFree (text);
9940 file = build_string (data);
9941 XtFree (data);
9943 else
9944 file = Qnil;
9946 /* Clean up. */
9947 XtUnmanageChild (dialog);
9948 XtDestroyWidget (dialog);
9949 UNBLOCK_INPUT;
9950 UNGCPRO;
9952 /* Make "Cancel" equivalent to C-g. */
9953 if (NILP (file))
9954 Fsignal (Qquit, Qnil);
9956 return unbind_to (count, file);
9959 #endif /* USE_MOTIF */
9962 /***********************************************************************
9963 Tests
9964 ***********************************************************************/
9966 #if GLYPH_DEBUG
9968 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
9969 "Value is non-nil if SPEC is a valid image specification.")
9970 (spec)
9971 Lisp_Object spec;
9973 return valid_image_p (spec) ? Qt : Qnil;
9977 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
9978 (spec)
9979 Lisp_Object spec;
9981 int id = -1;
9983 if (valid_image_p (spec))
9984 id = lookup_image (selected_frame, spec);
9986 debug_print (spec);
9987 return make_number (id);
9990 #endif /* GLYPH_DEBUG != 0 */
9994 /***********************************************************************
9995 Initialization
9996 ***********************************************************************/
9998 void
9999 syms_of_xfns ()
10001 /* This is zero if not using X windows. */
10002 x_in_use = 0;
10004 /* The section below is built by the lisp expression at the top of the file,
10005 just above where these variables are declared. */
10006 /*&&& init symbols here &&&*/
10007 Qauto_raise = intern ("auto-raise");
10008 staticpro (&Qauto_raise);
10009 Qauto_lower = intern ("auto-lower");
10010 staticpro (&Qauto_lower);
10011 Qbar = intern ("bar");
10012 staticpro (&Qbar);
10013 Qborder_color = intern ("border-color");
10014 staticpro (&Qborder_color);
10015 Qborder_width = intern ("border-width");
10016 staticpro (&Qborder_width);
10017 Qbox = intern ("box");
10018 staticpro (&Qbox);
10019 Qcursor_color = intern ("cursor-color");
10020 staticpro (&Qcursor_color);
10021 Qcursor_type = intern ("cursor-type");
10022 staticpro (&Qcursor_type);
10023 Qgeometry = intern ("geometry");
10024 staticpro (&Qgeometry);
10025 Qicon_left = intern ("icon-left");
10026 staticpro (&Qicon_left);
10027 Qicon_top = intern ("icon-top");
10028 staticpro (&Qicon_top);
10029 Qicon_type = intern ("icon-type");
10030 staticpro (&Qicon_type);
10031 Qicon_name = intern ("icon-name");
10032 staticpro (&Qicon_name);
10033 Qinternal_border_width = intern ("internal-border-width");
10034 staticpro (&Qinternal_border_width);
10035 Qleft = intern ("left");
10036 staticpro (&Qleft);
10037 Qright = intern ("right");
10038 staticpro (&Qright);
10039 Qmouse_color = intern ("mouse-color");
10040 staticpro (&Qmouse_color);
10041 Qnone = intern ("none");
10042 staticpro (&Qnone);
10043 Qparent_id = intern ("parent-id");
10044 staticpro (&Qparent_id);
10045 Qscroll_bar_width = intern ("scroll-bar-width");
10046 staticpro (&Qscroll_bar_width);
10047 Qsuppress_icon = intern ("suppress-icon");
10048 staticpro (&Qsuppress_icon);
10049 Qundefined_color = intern ("undefined-color");
10050 staticpro (&Qundefined_color);
10051 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
10052 staticpro (&Qvertical_scroll_bars);
10053 Qvisibility = intern ("visibility");
10054 staticpro (&Qvisibility);
10055 Qwindow_id = intern ("window-id");
10056 staticpro (&Qwindow_id);
10057 Qouter_window_id = intern ("outer-window-id");
10058 staticpro (&Qouter_window_id);
10059 Qx_frame_parameter = intern ("x-frame-parameter");
10060 staticpro (&Qx_frame_parameter);
10061 Qx_resource_name = intern ("x-resource-name");
10062 staticpro (&Qx_resource_name);
10063 Quser_position = intern ("user-position");
10064 staticpro (&Quser_position);
10065 Quser_size = intern ("user-size");
10066 staticpro (&Quser_size);
10067 Qdisplay = intern ("display");
10068 staticpro (&Qdisplay);
10069 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
10070 staticpro (&Qscroll_bar_foreground);
10071 Qscroll_bar_background = intern ("scroll-bar-background");
10072 staticpro (&Qscroll_bar_background);
10073 /* This is the end of symbol initialization. */
10075 Qlaplace = intern ("laplace");
10076 staticpro (&Qlaplace);
10078 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10079 staticpro (&Qface_set_after_frame_default);
10081 Fput (Qundefined_color, Qerror_conditions,
10082 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10083 Fput (Qundefined_color, Qerror_message,
10084 build_string ("Undefined color"));
10086 init_x_parm_symbols ();
10088 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10089 "List of directories to search for bitmap files for X.");
10090 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
10092 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10093 "The shape of the pointer when over text.\n\
10094 Changing the value does not affect existing frames\n\
10095 unless you set the mouse color.");
10096 Vx_pointer_shape = Qnil;
10098 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
10099 "The name Emacs uses to look up X resources.\n\
10100 `x-get-resource' uses this as the first component of the instance name\n\
10101 when requesting resource values.\n\
10102 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10103 was invoked, or to the value specified with the `-name' or `-rn'\n\
10104 switches, if present.\n\
10106 It may be useful to bind this variable locally around a call\n\
10107 to `x-get-resource'. See also the variable `x-resource-class'.");
10108 Vx_resource_name = Qnil;
10110 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
10111 "The class Emacs uses to look up X resources.\n\
10112 `x-get-resource' uses this as the first component of the instance class\n\
10113 when requesting resource values.\n\
10114 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10116 Setting this variable permanently is not a reasonable thing to do,\n\
10117 but binding this variable locally around a call to `x-get-resource'\n\
10118 is a reasonable practice. See also the variable `x-resource-name'.");
10119 Vx_resource_class = build_string (EMACS_CLASS);
10121 #if 0 /* This doesn't really do anything. */
10122 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
10123 "The shape of the pointer when not over text.\n\
10124 This variable takes effect when you create a new frame\n\
10125 or when you set the mouse color.");
10126 #endif
10127 Vx_nontext_pointer_shape = Qnil;
10129 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
10130 "The shape of the pointer when Emacs is busy.\n\
10131 This variable takes effect when you create a new frame\n\
10132 or when you set the mouse color.");
10133 Vx_busy_pointer_shape = Qnil;
10135 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
10136 "Non-zero means Emacs displays a busy cursor on window systems.");
10137 display_busy_cursor_p = 1;
10139 #if 0 /* This doesn't really do anything. */
10140 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
10141 "The shape of the pointer when over the mode line.\n\
10142 This variable takes effect when you create a new frame\n\
10143 or when you set the mouse color.");
10144 #endif
10145 Vx_mode_pointer_shape = Qnil;
10147 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10148 &Vx_sensitive_text_pointer_shape,
10149 "The shape of the pointer when over mouse-sensitive text.\n\
10150 This variable takes effect when you create a new frame\n\
10151 or when you set the mouse color.");
10152 Vx_sensitive_text_pointer_shape = Qnil;
10154 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10155 "A string indicating the foreground color of the cursor box.");
10156 Vx_cursor_fore_pixel = Qnil;
10158 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10159 "Non-nil if no X window manager is in use.\n\
10160 Emacs doesn't try to figure this out; this is always nil\n\
10161 unless you set it to something else.");
10162 /* We don't have any way to find this out, so set it to nil
10163 and maybe the user would like to set it to t. */
10164 Vx_no_window_manager = Qnil;
10166 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10167 &Vx_pixel_size_width_font_regexp,
10168 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10170 Since Emacs gets width of a font matching with this regexp from\n\
10171 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10172 such a font. This is especially effective for such large fonts as\n\
10173 Chinese, Japanese, and Korean.");
10174 Vx_pixel_size_width_font_regexp = Qnil;
10176 DEFVAR_LISP ("image-eviction-seconds", &Vimage_eviction_seconds,
10177 "Time after which cached images are removed from the cache.\n\
10178 When an image has not been displayed this many seconds, remove it\n\
10179 from the image cache. Value must be an integer or nil with nil\n\
10180 meaning don't clear the cache.");
10181 Vimage_eviction_seconds = make_number (30 * 60);
10183 DEFVAR_LISP ("image-types", &Vimage_types,
10184 "List of supported image types.\n\
10185 Each element of the list is a symbol for a supported image type.");
10186 Vimage_types = Qnil;
10188 #ifdef USE_X_TOOLKIT
10189 Fprovide (intern ("x-toolkit"));
10190 #endif
10191 #ifdef USE_MOTIF
10192 Fprovide (intern ("motif"));
10193 #endif
10195 defsubr (&Sx_get_resource);
10197 /* X window properties. */
10198 defsubr (&Sx_change_window_property);
10199 defsubr (&Sx_delete_window_property);
10200 defsubr (&Sx_window_property);
10202 #if 0
10203 defsubr (&Sx_draw_rectangle);
10204 defsubr (&Sx_erase_rectangle);
10205 defsubr (&Sx_contour_region);
10206 defsubr (&Sx_uncontour_region);
10207 #endif
10208 defsubr (&Sx_display_color_p);
10209 defsubr (&Sx_display_grayscale_p);
10210 defsubr (&Sx_color_defined_p);
10211 defsubr (&Sx_color_values);
10212 defsubr (&Sx_server_max_request_size);
10213 defsubr (&Sx_server_vendor);
10214 defsubr (&Sx_server_version);
10215 defsubr (&Sx_display_pixel_width);
10216 defsubr (&Sx_display_pixel_height);
10217 defsubr (&Sx_display_mm_width);
10218 defsubr (&Sx_display_mm_height);
10219 defsubr (&Sx_display_screens);
10220 defsubr (&Sx_display_planes);
10221 defsubr (&Sx_display_color_cells);
10222 defsubr (&Sx_display_visual_class);
10223 defsubr (&Sx_display_backing_store);
10224 defsubr (&Sx_display_save_under);
10225 #if 0
10226 defsubr (&Sx_rebind_key);
10227 defsubr (&Sx_rebind_keys);
10228 defsubr (&Sx_track_pointer);
10229 defsubr (&Sx_grab_pointer);
10230 defsubr (&Sx_ungrab_pointer);
10231 #endif
10232 defsubr (&Sx_parse_geometry);
10233 defsubr (&Sx_create_frame);
10234 #if 0
10235 defsubr (&Sx_horizontal_line);
10236 #endif
10237 defsubr (&Sx_open_connection);
10238 defsubr (&Sx_close_connection);
10239 defsubr (&Sx_display_list);
10240 defsubr (&Sx_synchronize);
10242 /* Setting callback functions for fontset handler. */
10243 get_font_info_func = x_get_font_info;
10245 #if 0 /* This function pointer doesn't seem to be used anywhere.
10246 And the pointer assigned has the wrong type, anyway. */
10247 list_fonts_func = x_list_fonts;
10248 #endif
10250 load_font_func = x_load_font;
10251 find_ccl_program_func = x_find_ccl_program;
10252 query_font_func = x_query_font;
10253 set_frame_fontset_func = x_set_font;
10254 check_window_system_func = check_x;
10256 /* Images. */
10257 Qxbm = intern ("xbm");
10258 staticpro (&Qxbm);
10259 QCtype = intern (":type");
10260 staticpro (&QCtype);
10261 QCfile = intern (":file");
10262 staticpro (&QCfile);
10263 QCalgorithm = intern (":algorithm");
10264 staticpro (&QCalgorithm);
10265 QCheuristic_mask = intern (":heuristic-mask");
10266 staticpro (&QCheuristic_mask);
10267 QCcolor_symbols = intern (":color-symbols");
10268 staticpro (&QCcolor_symbols);
10269 QCdata = intern (":data");
10270 staticpro (&QCdata);
10271 QCascent = intern (":ascent");
10272 staticpro (&QCascent);
10273 QCmargin = intern (":margin");
10274 staticpro (&QCmargin);
10275 QCrelief = intern (":relief");
10276 staticpro (&QCrelief);
10277 Qghostscript = intern ("ghostscript");
10278 staticpro (&Qghostscript);
10279 QCloader = intern (":loader");
10280 staticpro (&QCloader);
10281 QCbounding_box = intern (":bounding-box");
10282 staticpro (&QCbounding_box);
10283 QCpt_width = intern (":pt-width");
10284 staticpro (&QCpt_width);
10285 QCpt_height = intern (":pt-height");
10286 staticpro (&QCpt_height);
10287 Qpbm = intern ("pbm");
10288 staticpro (&Qpbm);
10290 #if HAVE_XPM
10291 Qxpm = intern ("xpm");
10292 staticpro (&Qxpm);
10293 #endif
10295 #if HAVE_JPEG
10296 Qjpeg = intern ("jpeg");
10297 staticpro (&Qjpeg);
10298 #endif
10300 #if HAVE_TIFF
10301 Qtiff = intern ("tiff");
10302 staticpro (&Qtiff);
10303 #endif
10305 #if HAVE_GIF
10306 Qgif = intern ("gif");
10307 staticpro (&Qgif);
10308 #endif
10310 #if HAVE_PNG
10311 Qpng = intern ("png");
10312 staticpro (&Qpng);
10313 #endif
10315 defsubr (&Sclear_image_cache);
10317 #if GLYPH_DEBUG
10318 defsubr (&Simagep);
10319 defsubr (&Slookup_image);
10320 #endif
10322 /* Busy-cursor. */
10323 defsubr (&Sx_show_busy_cursor);
10324 defsubr (&Sx_hide_busy_cursor);
10325 busy_count = 0;
10326 inhibit_busy_cursor = 0;
10328 defsubr (&Sx_show_tip);
10329 defsubr (&Sx_hide_tip);
10330 staticpro (&tip_timer);
10331 tip_timer = Qnil;
10333 #ifdef USE_MOTIF
10334 defsubr (&Sx_file_dialog);
10335 #endif
10339 void
10340 init_xfns ()
10342 image_types = NULL;
10343 Vimage_types = Qnil;
10345 define_image_type (&xbm_type);
10346 define_image_type (&gs_type);
10347 define_image_type (&pbm_type);
10349 #if HAVE_XPM
10350 define_image_type (&xpm_type);
10351 #endif
10353 #if HAVE_JPEG
10354 define_image_type (&jpeg_type);
10355 #endif
10357 #if HAVE_TIFF
10358 define_image_type (&tiff_type);
10359 #endif
10361 #if HAVE_GIF
10362 define_image_type (&gif_type);
10363 #endif
10365 #if HAVE_PNG
10366 define_image_type (&png_type);
10367 #endif
10370 #endif /* HAVE_X_WINDOWS */