(Ftry_completion, Fall_completions): Add a reference to
[emacs.git] / src / xfns.c
blob7d0459e924e98bb55f7a94f9fe82a8e26f71689f
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
31 #include "lisp.h"
32 #include "xterm.h"
33 #include "frame.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "intervals.h"
37 #include "dispextern.h"
38 #include "keyboard.h"
39 #include "blockinput.h"
40 #include <epaths.h>
41 #include "charset.h"
42 #include "fontset.h"
43 #include "systime.h"
44 #include "termhooks.h"
46 #ifdef HAVE_X_WINDOWS
48 #include <ctype.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
52 /* On some systems, the character-composition stuff is broken in X11R5. */
54 #if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
55 #ifdef X11R5_INHIBIT_I18N
56 #define X_I18N_INHIBITED
57 #endif
58 #endif
60 #ifndef VMS
61 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
62 #include "bitmaps/gray.xbm"
63 #else
64 #include <X11/bitmaps/gray>
65 #endif
66 #else
67 #include "[.bitmaps]gray.xbm"
68 #endif
70 #ifdef USE_X_TOOLKIT
71 #include <X11/Shell.h>
73 #ifndef USE_MOTIF
74 #include <X11/Xaw/Paned.h>
75 #include <X11/Xaw/Label.h>
76 #endif /* USE_MOTIF */
78 #ifdef USG
79 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
80 #include <X11/Xos.h>
81 #define USG
82 #else
83 #include <X11/Xos.h>
84 #endif
86 #include "widget.h"
88 #include "../lwlib/lwlib.h"
90 #ifdef USE_MOTIF
91 #include <Xm/Xm.h>
92 #include <Xm/DialogS.h>
93 #include <Xm/FileSB.h>
94 #endif
96 /* Do the EDITRES protocol if running X11R5
97 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
99 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
100 #define HACK_EDITRES
101 extern void _XEditResCheckMessages ();
102 #endif /* R5 + Athena */
104 /* Unique id counter for widgets created by the Lucid Widget Library. */
106 extern LWLIB_ID widget_id_tick;
108 #ifdef USE_LUCID
109 /* This is part of a kludge--see lwlib/xlwmenu.c. */
110 extern XFontStruct *xlwmenu_default_font;
111 #endif
113 extern void free_frame_menubar ();
114 extern double atof ();
116 #endif /* USE_X_TOOLKIT */
118 #define min(a,b) ((a) < (b) ? (a) : (b))
119 #define max(a,b) ((a) > (b) ? (a) : (b))
121 #ifdef HAVE_X11R4
122 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
123 #else
124 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
125 #endif
127 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
128 it, and including `bitmaps/gray' more than once is a problem when
129 config.h defines `static' as an empty replacement string. */
131 int gray_bitmap_width = gray_width;
132 int gray_bitmap_height = gray_height;
133 unsigned char *gray_bitmap_bits = gray_bits;
135 /* The name we're using in resource queries. Most often "emacs". */
137 Lisp_Object Vx_resource_name;
139 /* The application class we're using in resource queries.
140 Normally "Emacs". */
142 Lisp_Object Vx_resource_class;
144 /* Non-zero means we're allowed to display a busy cursor. */
146 int display_busy_cursor_p;
148 /* The background and shape of the mouse pointer, and shape when not
149 over text or in the modeline. */
151 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
152 Lisp_Object Vx_busy_pointer_shape;
154 /* The shape when over mouse-sensitive text. */
156 Lisp_Object Vx_sensitive_text_pointer_shape;
158 /* Color of chars displayed in cursor box. */
160 Lisp_Object Vx_cursor_fore_pixel;
162 /* Nonzero if using X. */
164 static int x_in_use;
166 /* Non nil if no window manager is in use. */
168 Lisp_Object Vx_no_window_manager;
170 /* Search path for bitmap files. */
172 Lisp_Object Vx_bitmap_file_path;
174 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
176 Lisp_Object Vx_pixel_size_width_font_regexp;
178 /* Evaluate this expression to rebuild the section of syms_of_xfns
179 that initializes and staticpros the symbols declared below. Note
180 that Emacs 18 has a bug that keeps C-x C-e from being able to
181 evaluate this expression.
183 (progn
184 ;; Accumulate a list of the symbols we want to initialize from the
185 ;; declarations at the top of the file.
186 (goto-char (point-min))
187 (search-forward "/\*&&& symbols declared here &&&*\/\n")
188 (let (symbol-list)
189 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
190 (setq symbol-list
191 (cons (buffer-substring (match-beginning 1) (match-end 1))
192 symbol-list))
193 (forward-line 1))
194 (setq symbol-list (nreverse symbol-list))
195 ;; Delete the section of syms_of_... where we initialize the symbols.
196 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
197 (let ((start (point)))
198 (while (looking-at "^ Q")
199 (forward-line 2))
200 (kill-region start (point)))
201 ;; Write a new symbol initialization section.
202 (while symbol-list
203 (insert (format " %s = intern (\"" (car symbol-list)))
204 (let ((start (point)))
205 (insert (substring (car symbol-list) 1))
206 (subst-char-in-region start (point) ?_ ?-))
207 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
208 (setq symbol-list (cdr symbol-list)))))
212 /*&&& symbols declared here &&&*/
213 Lisp_Object Qauto_raise;
214 Lisp_Object Qauto_lower;
215 Lisp_Object Qbar;
216 Lisp_Object Qborder_color;
217 Lisp_Object Qborder_width;
218 Lisp_Object Qbox;
219 Lisp_Object Qcursor_color;
220 Lisp_Object Qcursor_type;
221 Lisp_Object Qgeometry;
222 Lisp_Object Qicon_left;
223 Lisp_Object Qicon_top;
224 Lisp_Object Qicon_type;
225 Lisp_Object Qicon_name;
226 Lisp_Object Qinternal_border_width;
227 Lisp_Object Qleft;
228 Lisp_Object Qright;
229 Lisp_Object Qmouse_color;
230 Lisp_Object Qnone;
231 Lisp_Object Qouter_window_id;
232 Lisp_Object Qparent_id;
233 Lisp_Object Qscroll_bar_width;
234 Lisp_Object Qsuppress_icon;
235 extern Lisp_Object Qtop;
236 Lisp_Object Qundefined_color;
237 Lisp_Object Qvertical_scroll_bars;
238 Lisp_Object Qvisibility;
239 Lisp_Object Qwindow_id;
240 Lisp_Object Qx_frame_parameter;
241 Lisp_Object Qx_resource_name;
242 Lisp_Object Quser_position;
243 Lisp_Object Quser_size;
244 extern Lisp_Object Qdisplay;
245 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
246 Lisp_Object Qscreen_gamma;
248 /* The below are defined in frame.c. */
250 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
251 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
252 extern Lisp_Object Qtool_bar_lines;
254 extern Lisp_Object Vwindow_system_version;
256 Lisp_Object Qface_set_after_frame_default;
259 /* Error if we are not connected to X. */
261 void
262 check_x ()
264 if (! x_in_use)
265 error ("X windows are not in use or not initialized");
268 /* Nonzero if we can use mouse menus.
269 You should not call this unless HAVE_MENUS is defined. */
272 have_menus_p ()
274 return x_in_use;
277 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
278 and checking validity for X. */
280 FRAME_PTR
281 check_x_frame (frame)
282 Lisp_Object frame;
284 FRAME_PTR f;
286 if (NILP (frame))
287 frame = selected_frame;
288 CHECK_LIVE_FRAME (frame, 0);
289 f = XFRAME (frame);
290 if (! FRAME_X_P (f))
291 error ("Non-X frame used");
292 return f;
295 /* Let the user specify an X display with a frame.
296 nil stands for the selected frame--or, if that is not an X frame,
297 the first X display on the list. */
299 static struct x_display_info *
300 check_x_display_info (frame)
301 Lisp_Object frame;
303 if (NILP (frame))
305 struct frame *sf = XFRAME (selected_frame);
307 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
308 return FRAME_X_DISPLAY_INFO (sf);
309 else if (x_display_list != 0)
310 return x_display_list;
311 else
312 error ("X windows are not in use or not initialized");
314 else if (STRINGP (frame))
315 return x_display_info_for_name (frame);
316 else
318 FRAME_PTR f;
320 CHECK_LIVE_FRAME (frame, 0);
321 f = XFRAME (frame);
322 if (! FRAME_X_P (f))
323 error ("Non-X frame used");
324 return FRAME_X_DISPLAY_INFO (f);
329 /* Return the Emacs frame-object corresponding to an X window.
330 It could be the frame's main window or an icon window. */
332 /* This function can be called during GC, so use GC_xxx type test macros. */
334 struct frame *
335 x_window_to_frame (dpyinfo, wdesc)
336 struct x_display_info *dpyinfo;
337 int wdesc;
339 Lisp_Object tail, frame;
340 struct frame *f;
342 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
344 frame = XCAR (tail);
345 if (!GC_FRAMEP (frame))
346 continue;
347 f = XFRAME (frame);
348 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
349 continue;
350 #ifdef USE_X_TOOLKIT
351 if ((f->output_data.x->edit_widget
352 && XtWindow (f->output_data.x->edit_widget) == wdesc)
353 /* A tooltip frame? */
354 || (!f->output_data.x->edit_widget
355 && FRAME_X_WINDOW (f) == wdesc)
356 || f->output_data.x->icon_desc == wdesc)
357 return f;
358 #else /* not USE_X_TOOLKIT */
359 if (FRAME_X_WINDOW (f) == wdesc
360 || f->output_data.x->icon_desc == wdesc)
361 return f;
362 #endif /* not USE_X_TOOLKIT */
364 return 0;
367 #ifdef USE_X_TOOLKIT
368 /* Like x_window_to_frame but also compares the window with the widget's
369 windows. */
371 struct frame *
372 x_any_window_to_frame (dpyinfo, wdesc)
373 struct x_display_info *dpyinfo;
374 int wdesc;
376 Lisp_Object tail, frame;
377 struct frame *f;
378 struct x_output *x;
380 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
382 frame = XCAR (tail);
383 if (!GC_FRAMEP (frame))
384 continue;
385 f = XFRAME (frame);
386 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
387 continue;
388 x = f->output_data.x;
389 /* This frame matches if the window is any of its widgets. */
390 if (x->widget)
392 if (wdesc == XtWindow (x->widget)
393 || wdesc == XtWindow (x->column_widget)
394 || wdesc == XtWindow (x->edit_widget))
395 return f;
396 /* Match if the window is this frame's menubar. */
397 if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
398 return f;
400 else if (FRAME_X_WINDOW (f) == wdesc)
401 /* A tooltip frame. */
402 return f;
404 return 0;
407 /* Likewise, but exclude the menu bar widget. */
409 struct frame *
410 x_non_menubar_window_to_frame (dpyinfo, wdesc)
411 struct x_display_info *dpyinfo;
412 int wdesc;
414 Lisp_Object tail, frame;
415 struct frame *f;
416 struct x_output *x;
418 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
420 frame = XCAR (tail);
421 if (!GC_FRAMEP (frame))
422 continue;
423 f = XFRAME (frame);
424 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
425 continue;
426 x = f->output_data.x;
427 /* This frame matches if the window is any of its widgets. */
428 if (x->widget)
430 if (wdesc == XtWindow (x->widget)
431 || wdesc == XtWindow (x->column_widget)
432 || wdesc == XtWindow (x->edit_widget))
433 return f;
435 else if (FRAME_X_WINDOW (f) == wdesc)
436 /* A tooltip frame. */
437 return f;
439 return 0;
442 /* Likewise, but consider only the menu bar widget. */
444 struct frame *
445 x_menubar_window_to_frame (dpyinfo, wdesc)
446 struct x_display_info *dpyinfo;
447 int wdesc;
449 Lisp_Object tail, frame;
450 struct frame *f;
451 struct x_output *x;
453 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
455 frame = XCAR (tail);
456 if (!GC_FRAMEP (frame))
457 continue;
458 f = XFRAME (frame);
459 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
460 continue;
461 x = f->output_data.x;
462 /* Match if the window is this frame's menubar. */
463 if (x->menubar_widget
464 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
465 return f;
467 return 0;
470 /* Return the frame whose principal (outermost) window is WDESC.
471 If WDESC is some other (smaller) window, we return 0. */
473 struct frame *
474 x_top_window_to_frame (dpyinfo, wdesc)
475 struct x_display_info *dpyinfo;
476 int wdesc;
478 Lisp_Object tail, frame;
479 struct frame *f;
480 struct x_output *x;
482 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
484 frame = XCAR (tail);
485 if (!GC_FRAMEP (frame))
486 continue;
487 f = XFRAME (frame);
488 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
489 continue;
490 x = f->output_data.x;
492 if (x->widget)
494 /* This frame matches if the window is its topmost widget. */
495 if (wdesc == XtWindow (x->widget))
496 return f;
497 #if 0 /* I don't know why it did this,
498 but it seems logically wrong,
499 and it causes trouble for MapNotify events. */
500 /* Match if the window is this frame's menubar. */
501 if (x->menubar_widget
502 && wdesc == XtWindow (x->menubar_widget))
503 return f;
504 #endif
506 else if (FRAME_X_WINDOW (f) == wdesc)
507 /* Tooltip frame. */
508 return f;
510 return 0;
512 #endif /* USE_X_TOOLKIT */
516 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
517 id, which is just an int that this section returns. Bitmaps are
518 reference counted so they can be shared among frames.
520 Bitmap indices are guaranteed to be > 0, so a negative number can
521 be used to indicate no bitmap.
523 If you use x_create_bitmap_from_data, then you must keep track of
524 the bitmaps yourself. That is, creating a bitmap from the same
525 data more than once will not be caught. */
528 /* Functions to access the contents of a bitmap, given an id. */
531 x_bitmap_height (f, id)
532 FRAME_PTR f;
533 int id;
535 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
539 x_bitmap_width (f, id)
540 FRAME_PTR f;
541 int id;
543 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
547 x_bitmap_pixmap (f, id)
548 FRAME_PTR f;
549 int id;
551 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
555 /* Allocate a new bitmap record. Returns index of new record. */
557 static int
558 x_allocate_bitmap_record (f)
559 FRAME_PTR f;
561 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
562 int i;
564 if (dpyinfo->bitmaps == NULL)
566 dpyinfo->bitmaps_size = 10;
567 dpyinfo->bitmaps
568 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
569 dpyinfo->bitmaps_last = 1;
570 return 1;
573 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
574 return ++dpyinfo->bitmaps_last;
576 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
577 if (dpyinfo->bitmaps[i].refcount == 0)
578 return i + 1;
580 dpyinfo->bitmaps_size *= 2;
581 dpyinfo->bitmaps
582 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
583 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
584 return ++dpyinfo->bitmaps_last;
587 /* Add one reference to the reference count of the bitmap with id ID. */
589 void
590 x_reference_bitmap (f, id)
591 FRAME_PTR f;
592 int id;
594 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
597 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
600 x_create_bitmap_from_data (f, bits, width, height)
601 struct frame *f;
602 char *bits;
603 unsigned int width, height;
605 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
606 Pixmap bitmap;
607 int id;
609 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
610 bits, width, height);
612 if (! bitmap)
613 return -1;
615 id = x_allocate_bitmap_record (f);
616 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
617 dpyinfo->bitmaps[id - 1].file = NULL;
618 dpyinfo->bitmaps[id - 1].refcount = 1;
619 dpyinfo->bitmaps[id - 1].depth = 1;
620 dpyinfo->bitmaps[id - 1].height = height;
621 dpyinfo->bitmaps[id - 1].width = width;
623 return id;
626 /* Create bitmap from file FILE for frame F. */
629 x_create_bitmap_from_file (f, file)
630 struct frame *f;
631 Lisp_Object file;
633 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
634 unsigned int width, height;
635 Pixmap bitmap;
636 int xhot, yhot, result, id;
637 Lisp_Object found;
638 int fd;
639 char *filename;
641 /* Look for an existing bitmap with the same name. */
642 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
644 if (dpyinfo->bitmaps[id].refcount
645 && dpyinfo->bitmaps[id].file
646 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
648 ++dpyinfo->bitmaps[id].refcount;
649 return id + 1;
653 /* Search bitmap-file-path for the file, if appropriate. */
654 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
655 if (fd < 0)
656 return -1;
657 /* XReadBitmapFile won't handle magic file names. */
658 if (fd == 0)
659 return -1;
660 emacs_close (fd);
662 filename = (char *) XSTRING (found)->data;
664 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
665 filename, &width, &height, &bitmap, &xhot, &yhot);
666 if (result != BitmapSuccess)
667 return -1;
669 id = x_allocate_bitmap_record (f);
670 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
671 dpyinfo->bitmaps[id - 1].refcount = 1;
672 dpyinfo->bitmaps[id - 1].file
673 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
674 dpyinfo->bitmaps[id - 1].depth = 1;
675 dpyinfo->bitmaps[id - 1].height = height;
676 dpyinfo->bitmaps[id - 1].width = width;
677 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
679 return id;
682 /* Remove reference to bitmap with id number ID. */
684 void
685 x_destroy_bitmap (f, id)
686 FRAME_PTR f;
687 int id;
689 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
691 if (id > 0)
693 --dpyinfo->bitmaps[id - 1].refcount;
694 if (dpyinfo->bitmaps[id - 1].refcount == 0)
696 BLOCK_INPUT;
697 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
698 if (dpyinfo->bitmaps[id - 1].file)
700 xfree (dpyinfo->bitmaps[id - 1].file);
701 dpyinfo->bitmaps[id - 1].file = NULL;
703 UNBLOCK_INPUT;
708 /* Free all the bitmaps for the display specified by DPYINFO. */
710 static void
711 x_destroy_all_bitmaps (dpyinfo)
712 struct x_display_info *dpyinfo;
714 int i;
715 for (i = 0; i < dpyinfo->bitmaps_last; i++)
716 if (dpyinfo->bitmaps[i].refcount > 0)
718 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
719 if (dpyinfo->bitmaps[i].file)
720 xfree (dpyinfo->bitmaps[i].file);
722 dpyinfo->bitmaps_last = 0;
725 /* Connect the frame-parameter names for X frames
726 to the ways of passing the parameter values to the window system.
728 The name of a parameter, as a Lisp symbol,
729 has an `x-frame-parameter' property which is an integer in Lisp
730 that is an index in this table. */
732 struct x_frame_parm_table
734 char *name;
735 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 static void x_create_im P_ ((struct frame *));
739 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
742 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
744 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
745 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
746 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
749 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
750 Lisp_Object));
751 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
752 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
755 Lisp_Object));
756 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
757 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
758 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
759 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
760 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
761 void x_set_tool_bar_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));
771 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
773 static struct x_frame_parm_table x_frame_parms[] =
775 "auto-raise", x_set_autoraise,
776 "auto-lower", x_set_autolower,
777 "background-color", x_set_background_color,
778 "border-color", x_set_border_color,
779 "border-width", x_set_border_width,
780 "cursor-color", x_set_cursor_color,
781 "cursor-type", x_set_cursor_type,
782 "font", x_set_font,
783 "foreground-color", x_set_foreground_color,
784 "icon-name", x_set_icon_name,
785 "icon-type", x_set_icon_type,
786 "internal-border-width", x_set_internal_border_width,
787 "menu-bar-lines", x_set_menu_bar_lines,
788 "mouse-color", x_set_mouse_color,
789 "name", x_explicitly_set_name,
790 "scroll-bar-width", x_set_scroll_bar_width,
791 "title", x_set_title,
792 "unsplittable", x_set_unsplittable,
793 "vertical-scroll-bars", x_set_vertical_scroll_bars,
794 "visibility", x_set_visibility,
795 "tool-bar-lines", x_set_tool_bar_lines,
796 "scroll-bar-foreground", x_set_scroll_bar_foreground,
797 "scroll-bar-background", x_set_scroll_bar_background,
798 "screen-gamma", x_set_screen_gamma
801 /* Attach the `x-frame-parameter' properties to
802 the Lisp symbol names of parameters relevant to X. */
804 void
805 init_x_parm_symbols ()
807 int i;
809 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
810 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
811 make_number (i));
814 /* Change the parameters of frame F as specified by ALIST.
815 If a parameter is not specially recognized, do nothing;
816 otherwise call the `x_set_...' function for that parameter. */
818 void
819 x_set_frame_parameters (f, alist)
820 FRAME_PTR f;
821 Lisp_Object alist;
823 Lisp_Object tail;
825 /* If both of these parameters are present, it's more efficient to
826 set them both at once. So we wait until we've looked at the
827 entire list before we set them. */
828 int width, height;
830 /* Same here. */
831 Lisp_Object left, top;
833 /* Same with these. */
834 Lisp_Object icon_left, icon_top;
836 /* Record in these vectors all the parms specified. */
837 Lisp_Object *parms;
838 Lisp_Object *values;
839 int i, p;
840 int left_no_change = 0, top_no_change = 0;
841 int icon_left_no_change = 0, icon_top_no_change = 0;
843 struct gcpro gcpro1, gcpro2;
845 i = 0;
846 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
847 i++;
849 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
850 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
852 /* Extract parm names and values into those vectors. */
854 i = 0;
855 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
857 Lisp_Object elt;
859 elt = Fcar (tail);
860 parms[i] = Fcar (elt);
861 values[i] = Fcdr (elt);
862 i++;
864 /* TAIL and ALIST are not used again below here. */
865 alist = tail = Qnil;
867 GCPRO2 (*parms, *values);
868 gcpro1.nvars = i;
869 gcpro2.nvars = i;
871 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
872 because their values appear in VALUES and strings are not valid. */
873 top = left = Qunbound;
874 icon_left = icon_top = Qunbound;
876 /* Provide default values for HEIGHT and WIDTH. */
877 if (FRAME_NEW_WIDTH (f))
878 width = FRAME_NEW_WIDTH (f);
879 else
880 width = FRAME_WIDTH (f);
882 if (FRAME_NEW_HEIGHT (f))
883 height = FRAME_NEW_HEIGHT (f);
884 else
885 height = FRAME_HEIGHT (f);
887 /* Process foreground_color and background_color before anything else.
888 They are independent of other properties, but other properties (e.g.,
889 cursor_color) are dependent upon them. */
890 for (p = 0; p < i; p++)
892 Lisp_Object prop, val;
894 prop = parms[p];
895 val = values[p];
896 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
898 register Lisp_Object param_index, old_value;
900 param_index = Fget (prop, Qx_frame_parameter);
901 old_value = get_frame_param (f, prop);
902 store_frame_param (f, prop, val);
903 if (NATNUMP (param_index)
904 && (XFASTINT (param_index)
905 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
906 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
910 /* Now process them in reverse of specified order. */
911 for (i--; i >= 0; i--)
913 Lisp_Object prop, val;
915 prop = parms[i];
916 val = values[i];
918 if (EQ (prop, Qwidth) && NUMBERP (val))
919 width = XFASTINT (val);
920 else if (EQ (prop, Qheight) && NUMBERP (val))
921 height = XFASTINT (val);
922 else if (EQ (prop, Qtop))
923 top = val;
924 else if (EQ (prop, Qleft))
925 left = val;
926 else if (EQ (prop, Qicon_top))
927 icon_top = val;
928 else if (EQ (prop, Qicon_left))
929 icon_left = val;
930 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
931 /* Processed above. */
932 continue;
933 else
935 register Lisp_Object param_index, old_value;
937 param_index = Fget (prop, Qx_frame_parameter);
938 old_value = get_frame_param (f, prop);
939 store_frame_param (f, prop, val);
940 if (NATNUMP (param_index)
941 && (XFASTINT (param_index)
942 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
943 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
947 /* Don't die if just one of these was set. */
948 if (EQ (left, Qunbound))
950 left_no_change = 1;
951 if (f->output_data.x->left_pos < 0)
952 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
953 else
954 XSETINT (left, f->output_data.x->left_pos);
956 if (EQ (top, Qunbound))
958 top_no_change = 1;
959 if (f->output_data.x->top_pos < 0)
960 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
961 else
962 XSETINT (top, f->output_data.x->top_pos);
965 /* If one of the icon positions was not set, preserve or default it. */
966 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
968 icon_left_no_change = 1;
969 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
970 if (NILP (icon_left))
971 XSETINT (icon_left, 0);
973 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
975 icon_top_no_change = 1;
976 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
977 if (NILP (icon_top))
978 XSETINT (icon_top, 0);
981 /* Don't set these parameters unless they've been explicitly
982 specified. The window might be mapped or resized while we're in
983 this function, and we don't want to override that unless the lisp
984 code has asked for it.
986 Don't set these parameters unless they actually differ from the
987 window's current parameters; the window may not actually exist
988 yet. */
990 Lisp_Object frame;
992 check_frame_size (f, &height, &width);
994 XSETFRAME (frame, f);
996 if (width != FRAME_WIDTH (f)
997 || height != FRAME_HEIGHT (f)
998 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
999 Fset_frame_size (frame, make_number (width), make_number (height));
1001 if ((!NILP (left) || !NILP (top))
1002 && ! (left_no_change && top_no_change)
1003 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1004 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1006 int leftpos = 0;
1007 int toppos = 0;
1009 /* Record the signs. */
1010 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1011 if (EQ (left, Qminus))
1012 f->output_data.x->size_hint_flags |= XNegative;
1013 else if (INTEGERP (left))
1015 leftpos = XINT (left);
1016 if (leftpos < 0)
1017 f->output_data.x->size_hint_flags |= XNegative;
1019 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1020 && CONSP (XCDR (left))
1021 && INTEGERP (XCAR (XCDR (left))))
1023 leftpos = - XINT (XCAR (XCDR (left)));
1024 f->output_data.x->size_hint_flags |= XNegative;
1026 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1027 && CONSP (XCDR (left))
1028 && INTEGERP (XCAR (XCDR (left))))
1030 leftpos = XINT (XCAR (XCDR (left)));
1033 if (EQ (top, Qminus))
1034 f->output_data.x->size_hint_flags |= YNegative;
1035 else if (INTEGERP (top))
1037 toppos = XINT (top);
1038 if (toppos < 0)
1039 f->output_data.x->size_hint_flags |= YNegative;
1041 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1042 && CONSP (XCDR (top))
1043 && INTEGERP (XCAR (XCDR (top))))
1045 toppos = - XINT (XCAR (XCDR (top)));
1046 f->output_data.x->size_hint_flags |= YNegative;
1048 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1049 && CONSP (XCDR (top))
1050 && INTEGERP (XCAR (XCDR (top))))
1052 toppos = XINT (XCAR (XCDR (top)));
1056 /* Store the numeric value of the position. */
1057 f->output_data.x->top_pos = toppos;
1058 f->output_data.x->left_pos = leftpos;
1060 f->output_data.x->win_gravity = NorthWestGravity;
1062 /* Actually set that position, and convert to absolute. */
1063 x_set_offset (f, leftpos, toppos, -1);
1066 if ((!NILP (icon_left) || !NILP (icon_top))
1067 && ! (icon_left_no_change && icon_top_no_change))
1068 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1071 UNGCPRO;
1074 /* Store the screen positions of frame F into XPTR and YPTR.
1075 These are the positions of the containing window manager window,
1076 not Emacs's own window. */
1078 void
1079 x_real_positions (f, xptr, yptr)
1080 FRAME_PTR f;
1081 int *xptr, *yptr;
1083 int win_x, win_y;
1084 Window child;
1086 /* This is pretty gross, but seems to be the easiest way out of
1087 the problem that arises when restarting window-managers. */
1089 #ifdef USE_X_TOOLKIT
1090 Window outer = (f->output_data.x->widget
1091 ? XtWindow (f->output_data.x->widget)
1092 : FRAME_X_WINDOW (f));
1093 #else
1094 Window outer = f->output_data.x->window_desc;
1095 #endif
1096 Window tmp_root_window;
1097 Window *tmp_children;
1098 int tmp_nchildren;
1100 while (1)
1102 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1103 Window outer_window;
1105 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1106 &f->output_data.x->parent_desc,
1107 &tmp_children, &tmp_nchildren);
1108 XFree ((char *) tmp_children);
1110 win_x = win_y = 0;
1112 /* Find the position of the outside upper-left corner of
1113 the inner window, with respect to the outer window. */
1114 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1115 outer_window = f->output_data.x->parent_desc;
1116 else
1117 outer_window = outer;
1119 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1121 /* From-window, to-window. */
1122 outer_window,
1123 FRAME_X_DISPLAY_INFO (f)->root_window,
1125 /* From-position, to-position. */
1126 0, 0, &win_x, &win_y,
1128 /* Child of win. */
1129 &child);
1131 /* It is possible for the window returned by the XQueryNotify
1132 to become invalid by the time we call XTranslateCoordinates.
1133 That can happen when you restart some window managers.
1134 If so, we get an error in XTranslateCoordinates.
1135 Detect that and try the whole thing over. */
1136 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1138 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1139 break;
1142 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1145 *xptr = win_x;
1146 *yptr = win_y;
1149 /* Insert a description of internally-recorded parameters of frame X
1150 into the parameter alist *ALISTPTR that is to be given to the user.
1151 Only parameters that are specific to the X window system
1152 and whose values are not correctly recorded in the frame's
1153 param_alist need to be considered here. */
1155 void
1156 x_report_frame_params (f, alistptr)
1157 struct frame *f;
1158 Lisp_Object *alistptr;
1160 char buf[16];
1161 Lisp_Object tem;
1163 /* Represent negative positions (off the top or left screen edge)
1164 in a way that Fmodify_frame_parameters will understand correctly. */
1165 XSETINT (tem, f->output_data.x->left_pos);
1166 if (f->output_data.x->left_pos >= 0)
1167 store_in_alist (alistptr, Qleft, tem);
1168 else
1169 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1171 XSETINT (tem, f->output_data.x->top_pos);
1172 if (f->output_data.x->top_pos >= 0)
1173 store_in_alist (alistptr, Qtop, tem);
1174 else
1175 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1177 store_in_alist (alistptr, Qborder_width,
1178 make_number (f->output_data.x->border_width));
1179 store_in_alist (alistptr, Qinternal_border_width,
1180 make_number (f->output_data.x->internal_border_width));
1181 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1182 store_in_alist (alistptr, Qwindow_id,
1183 build_string (buf));
1184 #ifdef USE_X_TOOLKIT
1185 /* Tooltip frame may not have this widget. */
1186 if (f->output_data.x->widget)
1187 #endif
1188 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1189 store_in_alist (alistptr, Qouter_window_id,
1190 build_string (buf));
1191 store_in_alist (alistptr, Qicon_name, f->icon_name);
1192 FRAME_SAMPLE_VISIBILITY (f);
1193 store_in_alist (alistptr, Qvisibility,
1194 (FRAME_VISIBLE_P (f) ? Qt
1195 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1196 store_in_alist (alistptr, Qdisplay,
1197 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1199 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1200 tem = Qnil;
1201 else
1202 XSETFASTINT (tem, f->output_data.x->parent_desc);
1203 store_in_alist (alistptr, Qparent_id, tem);
1208 /* Gamma-correct COLOR on frame F. */
1210 void
1211 gamma_correct (f, color)
1212 struct frame *f;
1213 XColor *color;
1215 if (f->gamma)
1217 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1218 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1219 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1224 /* Decide if color named COLOR is valid for the display associated with
1225 the selected frame; if so, return the rgb values in COLOR_DEF.
1226 If ALLOC is nonzero, allocate a new colormap cell. */
1229 x_defined_color (f, color, color_def, alloc)
1230 FRAME_PTR f;
1231 char *color;
1232 XColor *color_def;
1233 int alloc;
1235 register int status;
1236 Colormap screen_colormap;
1237 Display *display = FRAME_X_DISPLAY (f);
1239 BLOCK_INPUT;
1240 screen_colormap = DefaultColormap (display, XDefaultScreen (display));
1242 status = XParseColor (display, screen_colormap, color, color_def);
1243 if (status && alloc)
1245 /* Apply gamma correction. */
1246 gamma_correct (f, color_def);
1248 status = XAllocColor (display, screen_colormap, color_def);
1249 if (!status)
1251 /* If we got to this point, the colormap is full, so we're
1252 going to try and get the next closest color.
1253 The algorithm used is a least-squares matching, which is
1254 what X uses for closest color matching with StaticColor visuals. */
1256 XColor *cells;
1257 int no_cells;
1258 int nearest;
1259 long nearest_delta, trial_delta;
1260 int x;
1262 no_cells = XDisplayCells (display, XDefaultScreen (display));
1263 cells = (XColor *) alloca (sizeof (XColor) * no_cells);
1265 for (x = 0; x < no_cells; x++)
1266 cells[x].pixel = x;
1268 XQueryColors (display, screen_colormap, cells, no_cells);
1269 nearest = 0;
1270 /* I'm assuming CSE so I'm not going to condense this. */
1271 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
1272 * ((color_def->red >> 8) - (cells[0].red >> 8)))
1274 (((color_def->green >> 8) - (cells[0].green >> 8))
1275 * ((color_def->green >> 8) - (cells[0].green >> 8)))
1277 (((color_def->blue >> 8) - (cells[0].blue >> 8))
1278 * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
1279 for (x = 1; x < no_cells; x++)
1281 trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
1282 * ((color_def->red >> 8) - (cells[x].red >> 8)))
1284 (((color_def->green >> 8) - (cells[x].green >> 8))
1285 * ((color_def->green >> 8) - (cells[x].green >> 8)))
1287 (((color_def->blue >> 8) - (cells[x].blue >> 8))
1288 * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
1289 if (trial_delta < nearest_delta)
1291 XColor temp;
1292 temp.red = cells[x].red;
1293 temp.green = cells[x].green;
1294 temp.blue = cells[x].blue;
1295 status = XAllocColor (display, screen_colormap, &temp);
1296 if (status)
1298 nearest = x;
1299 nearest_delta = trial_delta;
1303 color_def->red = cells[nearest].red;
1304 color_def->green = cells[nearest].green;
1305 color_def->blue = cells[nearest].blue;
1306 status = XAllocColor (display, screen_colormap, color_def);
1309 UNBLOCK_INPUT;
1311 if (status)
1312 return 1;
1313 else
1314 return 0;
1317 /* Given a string ARG naming a color, compute a pixel value from it
1318 suitable for screen F.
1319 If F is not a color screen, return DEF (default) regardless of what
1320 ARG says. */
1323 x_decode_color (f, arg, def)
1324 FRAME_PTR f;
1325 Lisp_Object arg;
1326 int def;
1328 XColor cdef;
1330 CHECK_STRING (arg, 0);
1332 if (strcmp (XSTRING (arg)->data, "black") == 0)
1333 return BLACK_PIX_DEFAULT (f);
1334 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1335 return WHITE_PIX_DEFAULT (f);
1337 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1338 return def;
1340 /* x_defined_color is responsible for coping with failures
1341 by looking for a near-miss. */
1342 if (x_defined_color (f, XSTRING (arg)->data, &cdef, 1))
1343 return cdef.pixel;
1345 Fsignal (Qerror, Fcons (build_string ("undefined color"),
1346 Fcons (arg, Qnil)));
1349 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1350 the previous value of that parameter, NEW_VALUE is the new value. */
1352 static void
1353 x_set_screen_gamma (f, new_value, old_value)
1354 struct frame *f;
1355 Lisp_Object new_value, old_value;
1357 if (NILP (new_value))
1358 f->gamma = 0;
1359 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1360 /* The value 0.4545 is the normal viewing gamma. */
1361 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1362 else
1363 Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
1364 Fcons (new_value, Qnil)));
1366 clear_face_cache (0);
1370 /* Functions called only from `x_set_frame_param'
1371 to set individual parameters.
1373 If FRAME_X_WINDOW (f) is 0,
1374 the frame is being created and its X-window does not exist yet.
1375 In that case, just record the parameter's new value
1376 in the standard place; do not attempt to change the window. */
1378 void
1379 x_set_foreground_color (f, arg, oldval)
1380 struct frame *f;
1381 Lisp_Object arg, oldval;
1383 unsigned long pixel
1384 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1386 unload_color (f, f->output_data.x->foreground_pixel);
1387 f->output_data.x->foreground_pixel = pixel;
1389 if (FRAME_X_WINDOW (f) != 0)
1391 BLOCK_INPUT;
1392 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1393 f->output_data.x->foreground_pixel);
1394 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1395 f->output_data.x->foreground_pixel);
1396 UNBLOCK_INPUT;
1397 update_face_from_frame_parameter (f, Qforeground_color, arg);
1398 if (FRAME_VISIBLE_P (f))
1399 redraw_frame (f);
1403 void
1404 x_set_background_color (f, arg, oldval)
1405 struct frame *f;
1406 Lisp_Object arg, oldval;
1408 unsigned long pixel
1409 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1411 unload_color (f, f->output_data.x->background_pixel);
1412 f->output_data.x->background_pixel = pixel;
1414 if (FRAME_X_WINDOW (f) != 0)
1416 BLOCK_INPUT;
1417 /* The main frame area. */
1418 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1419 f->output_data.x->background_pixel);
1420 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1421 f->output_data.x->background_pixel);
1422 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1423 f->output_data.x->background_pixel);
1424 XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1425 f->output_data.x->background_pixel);
1427 Lisp_Object bar;
1428 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
1429 bar = XSCROLL_BAR (bar)->next)
1430 XSetWindowBackground (FRAME_X_DISPLAY (f),
1431 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
1432 f->output_data.x->background_pixel);
1434 UNBLOCK_INPUT;
1436 update_face_from_frame_parameter (f, Qbackground_color, arg);
1438 if (FRAME_VISIBLE_P (f))
1439 redraw_frame (f);
1443 void
1444 x_set_mouse_color (f, arg, oldval)
1445 struct frame *f;
1446 Lisp_Object arg, oldval;
1448 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1449 Cursor busy_cursor;
1450 int count;
1451 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1452 unsigned long mask_color = f->output_data.x->background_pixel;
1454 /* Don't let pointers be invisible. */
1455 if (mask_color == pixel
1456 && mask_color == f->output_data.x->background_pixel)
1457 pixel = f->output_data.x->foreground_pixel;
1459 unload_color (f, f->output_data.x->mouse_pixel);
1460 f->output_data.x->mouse_pixel = pixel;
1462 BLOCK_INPUT;
1464 /* It's not okay to crash if the user selects a screwy cursor. */
1465 count = x_catch_errors (FRAME_X_DISPLAY (f));
1467 if (!EQ (Qnil, Vx_pointer_shape))
1469 CHECK_NUMBER (Vx_pointer_shape, 0);
1470 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
1472 else
1473 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1474 x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
1476 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1478 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1479 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1480 XINT (Vx_nontext_pointer_shape));
1482 else
1483 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
1484 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1486 if (!EQ (Qnil, Vx_busy_pointer_shape))
1488 CHECK_NUMBER (Vx_busy_pointer_shape, 0);
1489 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1490 XINT (Vx_busy_pointer_shape));
1492 else
1493 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
1494 x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s");
1496 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1497 if (!EQ (Qnil, Vx_mode_pointer_shape))
1499 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1500 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1501 XINT (Vx_mode_pointer_shape));
1503 else
1504 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1505 x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
1507 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1509 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1510 cross_cursor
1511 = XCreateFontCursor (FRAME_X_DISPLAY (f),
1512 XINT (Vx_sensitive_text_pointer_shape));
1514 else
1515 cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
1517 /* Check and report errors with the above calls. */
1518 x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
1519 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1522 XColor fore_color, back_color;
1524 fore_color.pixel = f->output_data.x->mouse_pixel;
1525 back_color.pixel = mask_color;
1526 XQueryColor (FRAME_X_DISPLAY (f),
1527 DefaultColormap (FRAME_X_DISPLAY (f),
1528 DefaultScreen (FRAME_X_DISPLAY (f))),
1529 &fore_color);
1530 XQueryColor (FRAME_X_DISPLAY (f),
1531 DefaultColormap (FRAME_X_DISPLAY (f),
1532 DefaultScreen (FRAME_X_DISPLAY (f))),
1533 &back_color);
1534 XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
1535 &fore_color, &back_color);
1536 XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
1537 &fore_color, &back_color);
1538 XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
1539 &fore_color, &back_color);
1540 XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
1541 &fore_color, &back_color);
1542 XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
1543 &fore_color, &back_color);
1546 if (FRAME_X_WINDOW (f) != 0)
1547 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
1549 if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
1550 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
1551 f->output_data.x->text_cursor = cursor;
1553 if (nontext_cursor != f->output_data.x->nontext_cursor
1554 && f->output_data.x->nontext_cursor != 0)
1555 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
1556 f->output_data.x->nontext_cursor = nontext_cursor;
1558 if (busy_cursor != f->output_data.x->busy_cursor
1559 && f->output_data.x->busy_cursor != 0)
1560 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
1561 f->output_data.x->busy_cursor = busy_cursor;
1563 if (mode_cursor != f->output_data.x->modeline_cursor
1564 && f->output_data.x->modeline_cursor != 0)
1565 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
1566 f->output_data.x->modeline_cursor = mode_cursor;
1568 if (cross_cursor != f->output_data.x->cross_cursor
1569 && f->output_data.x->cross_cursor != 0)
1570 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
1571 f->output_data.x->cross_cursor = cross_cursor;
1573 XFlush (FRAME_X_DISPLAY (f));
1574 UNBLOCK_INPUT;
1576 update_face_from_frame_parameter (f, Qmouse_color, arg);
1579 void
1580 x_set_cursor_color (f, arg, oldval)
1581 struct frame *f;
1582 Lisp_Object arg, oldval;
1584 unsigned long fore_pixel, pixel;
1586 if (!EQ (Vx_cursor_fore_pixel, Qnil))
1587 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1588 WHITE_PIX_DEFAULT (f));
1589 else
1590 fore_pixel = f->output_data.x->background_pixel;
1591 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1593 /* Make sure that the cursor color differs from the background color. */
1594 if (pixel == f->output_data.x->background_pixel)
1596 pixel = f->output_data.x->mouse_pixel;
1597 if (pixel == fore_pixel)
1598 fore_pixel = f->output_data.x->background_pixel;
1601 unload_color (f, f->output_data.x->cursor_foreground_pixel);
1602 f->output_data.x->cursor_foreground_pixel = fore_pixel;
1604 unload_color (f, f->output_data.x->cursor_pixel);
1605 f->output_data.x->cursor_pixel = pixel;
1607 if (FRAME_X_WINDOW (f) != 0)
1609 BLOCK_INPUT;
1610 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1611 f->output_data.x->cursor_pixel);
1612 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1613 fore_pixel);
1614 UNBLOCK_INPUT;
1616 if (FRAME_VISIBLE_P (f))
1618 x_update_cursor (f, 0);
1619 x_update_cursor (f, 1);
1623 update_face_from_frame_parameter (f, Qcursor_color, arg);
1626 /* Set the border-color of frame F to value described by ARG.
1627 ARG can be a string naming a color.
1628 The border-color is used for the border that is drawn by the X server.
1629 Note that this does not fully take effect if done before
1630 F has an x-window; it must be redone when the window is created.
1632 Note: this is done in two routines because of the way X10 works.
1634 Note: under X11, this is normally the province of the window manager,
1635 and so emacs' border colors may be overridden. */
1637 void
1638 x_set_border_color (f, arg, oldval)
1639 struct frame *f;
1640 Lisp_Object arg, oldval;
1642 int pix;
1644 CHECK_STRING (arg, 0);
1645 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1646 x_set_border_pixel (f, pix);
1647 update_face_from_frame_parameter (f, Qborder_color, arg);
1650 /* Set the border-color of frame F to pixel value PIX.
1651 Note that this does not fully take effect if done before
1652 F has an x-window. */
1654 void
1655 x_set_border_pixel (f, pix)
1656 struct frame *f;
1657 int pix;
1659 unload_color (f, f->output_data.x->border_pixel);
1660 f->output_data.x->border_pixel = pix;
1662 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1664 BLOCK_INPUT;
1665 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1666 (unsigned long)pix);
1667 UNBLOCK_INPUT;
1669 if (FRAME_VISIBLE_P (f))
1670 redraw_frame (f);
1674 void
1675 x_set_cursor_type (f, arg, oldval)
1676 FRAME_PTR f;
1677 Lisp_Object arg, oldval;
1679 if (EQ (arg, Qbar))
1681 FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
1682 f->output_data.x->cursor_width = 2;
1684 else if (CONSP (arg) && EQ (XCAR (arg), Qbar)
1685 && INTEGERP (XCDR (arg)))
1687 FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
1688 f->output_data.x->cursor_width = XINT (XCDR (arg));
1690 else
1691 /* Treat anything unknown as "box cursor".
1692 It was bad to signal an error; people have trouble fixing
1693 .Xdefaults with Emacs, when it has something bad in it. */
1694 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
1696 /* Make sure the cursor gets redrawn. This is overkill, but how
1697 often do people change cursor types? */
1698 update_mode_lines++;
1701 void
1702 x_set_icon_type (f, arg, oldval)
1703 struct frame *f;
1704 Lisp_Object arg, oldval;
1706 int result;
1708 if (STRINGP (arg))
1710 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1711 return;
1713 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1714 return;
1716 BLOCK_INPUT;
1717 if (NILP (arg))
1718 result = x_text_icon (f,
1719 (char *) XSTRING ((!NILP (f->icon_name)
1720 ? f->icon_name
1721 : f->name))->data);
1722 else
1723 result = x_bitmap_icon (f, arg);
1725 if (result)
1727 UNBLOCK_INPUT;
1728 error ("No icon window available");
1731 XFlush (FRAME_X_DISPLAY (f));
1732 UNBLOCK_INPUT;
1735 /* Return non-nil if frame F wants a bitmap icon. */
1737 Lisp_Object
1738 x_icon_type (f)
1739 FRAME_PTR f;
1741 Lisp_Object tem;
1743 tem = assq_no_quit (Qicon_type, f->param_alist);
1744 if (CONSP (tem))
1745 return XCDR (tem);
1746 else
1747 return Qnil;
1750 void
1751 x_set_icon_name (f, arg, oldval)
1752 struct frame *f;
1753 Lisp_Object arg, oldval;
1755 int result;
1757 if (STRINGP (arg))
1759 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1760 return;
1762 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1763 return;
1765 f->icon_name = arg;
1767 if (f->output_data.x->icon_bitmap != 0)
1768 return;
1770 BLOCK_INPUT;
1772 result = x_text_icon (f,
1773 (char *) XSTRING ((!NILP (f->icon_name)
1774 ? f->icon_name
1775 : !NILP (f->title)
1776 ? f->title
1777 : f->name))->data);
1779 if (result)
1781 UNBLOCK_INPUT;
1782 error ("No icon window available");
1785 XFlush (FRAME_X_DISPLAY (f));
1786 UNBLOCK_INPUT;
1789 void
1790 x_set_font (f, arg, oldval)
1791 struct frame *f;
1792 Lisp_Object arg, oldval;
1794 Lisp_Object result;
1795 Lisp_Object fontset_name;
1796 Lisp_Object frame;
1798 CHECK_STRING (arg, 1);
1800 fontset_name = Fquery_fontset (arg, Qnil);
1802 BLOCK_INPUT;
1803 result = (STRINGP (fontset_name)
1804 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1805 : x_new_font (f, XSTRING (arg)->data));
1806 UNBLOCK_INPUT;
1808 if (EQ (result, Qnil))
1809 error ("Font `%s' is not defined", XSTRING (arg)->data);
1810 else if (EQ (result, Qt))
1811 error ("The characters of the given font have varying widths");
1812 else if (STRINGP (result))
1814 store_frame_param (f, Qfont, result);
1815 recompute_basic_faces (f);
1817 else
1818 abort ();
1820 do_pending_window_change (0);
1822 /* Don't call `face-set-after-frame-default' when faces haven't been
1823 initialized yet. This is the case when called from
1824 Fx_create_frame. In that case, the X widget or window doesn't
1825 exist either, and we can end up in x_report_frame_params with a
1826 null widget which gives a segfault. */
1827 if (FRAME_FACE_CACHE (f))
1829 XSETFRAME (frame, f);
1830 call1 (Qface_set_after_frame_default, frame);
1834 void
1835 x_set_border_width (f, arg, oldval)
1836 struct frame *f;
1837 Lisp_Object arg, oldval;
1839 CHECK_NUMBER (arg, 0);
1841 if (XINT (arg) == f->output_data.x->border_width)
1842 return;
1844 if (FRAME_X_WINDOW (f) != 0)
1845 error ("Cannot change the border width of a window");
1847 f->output_data.x->border_width = XINT (arg);
1850 void
1851 x_set_internal_border_width (f, arg, oldval)
1852 struct frame *f;
1853 Lisp_Object arg, oldval;
1855 int old = f->output_data.x->internal_border_width;
1857 CHECK_NUMBER (arg, 0);
1858 f->output_data.x->internal_border_width = XINT (arg);
1859 if (f->output_data.x->internal_border_width < 0)
1860 f->output_data.x->internal_border_width = 0;
1862 #ifdef USE_X_TOOLKIT
1863 if (f->output_data.x->edit_widget)
1864 widget_store_internal_border (f->output_data.x->edit_widget);
1865 #endif
1867 if (f->output_data.x->internal_border_width == old)
1868 return;
1870 if (FRAME_X_WINDOW (f) != 0)
1872 x_set_window_size (f, 0, f->width, f->height);
1873 SET_FRAME_GARBAGED (f);
1874 do_pending_window_change (0);
1878 void
1879 x_set_visibility (f, value, oldval)
1880 struct frame *f;
1881 Lisp_Object value, oldval;
1883 Lisp_Object frame;
1884 XSETFRAME (frame, f);
1886 if (NILP (value))
1887 Fmake_frame_invisible (frame, Qt);
1888 else if (EQ (value, Qicon))
1889 Ficonify_frame (frame);
1890 else
1891 Fmake_frame_visible (frame);
1894 static void
1895 x_set_menu_bar_lines_1 (window, n)
1896 Lisp_Object window;
1897 int n;
1899 struct window *w = XWINDOW (window);
1901 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1902 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1904 /* Handle just the top child in a vertical split. */
1905 if (!NILP (w->vchild))
1906 x_set_menu_bar_lines_1 (w->vchild, n);
1908 /* Adjust all children in a horizontal split. */
1909 for (window = w->hchild; !NILP (window); window = w->next)
1911 w = XWINDOW (window);
1912 x_set_menu_bar_lines_1 (window, n);
1916 void
1917 x_set_menu_bar_lines (f, value, oldval)
1918 struct frame *f;
1919 Lisp_Object value, oldval;
1921 int nlines;
1922 #ifndef USE_X_TOOLKIT
1923 int olines = FRAME_MENU_BAR_LINES (f);
1924 #endif
1926 /* Right now, menu bars don't work properly in minibuf-only frames;
1927 most of the commands try to apply themselves to the minibuffer
1928 frame itself, and get an error because you can't switch buffers
1929 in or split the minibuffer window. */
1930 if (FRAME_MINIBUF_ONLY_P (f))
1931 return;
1933 if (INTEGERP (value))
1934 nlines = XINT (value);
1935 else
1936 nlines = 0;
1938 /* Make sure we redisplay all windows in this frame. */
1939 windows_or_buffers_changed++;
1941 #ifdef USE_X_TOOLKIT
1942 FRAME_MENU_BAR_LINES (f) = 0;
1943 if (nlines)
1945 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1946 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1947 /* Make sure next redisplay shows the menu bar. */
1948 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1950 else
1952 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1953 free_frame_menubar (f);
1954 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1955 if (FRAME_X_P (f))
1956 f->output_data.x->menubar_widget = 0;
1958 #else /* not USE_X_TOOLKIT */
1959 FRAME_MENU_BAR_LINES (f) = nlines;
1960 x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
1961 #endif /* not USE_X_TOOLKIT */
1962 adjust_glyphs (f);
1966 /* Set the number of lines used for the tool bar of frame F to VALUE.
1967 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1968 is the old number of tool bar lines. This function changes the
1969 height of all windows on frame F to match the new tool bar height.
1970 The frame's height doesn't change. */
1972 void
1973 x_set_tool_bar_lines (f, value, oldval)
1974 struct frame *f;
1975 Lisp_Object value, oldval;
1977 int delta, nlines;
1979 /* Use VALUE only if an integer >= 0. */
1980 if (INTEGERP (value) && XINT (value) >= 0)
1981 nlines = XFASTINT (value);
1982 else
1983 nlines = 0;
1985 /* Make sure we redisplay all windows in this frame. */
1986 ++windows_or_buffers_changed;
1988 delta = nlines - FRAME_TOOL_BAR_LINES (f);
1989 FRAME_TOOL_BAR_LINES (f) = nlines;
1990 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
1991 adjust_glyphs (f);
1995 /* Set the foreground color for scroll bars on frame F to VALUE.
1996 VALUE should be a string, a color name. If it isn't a string or
1997 isn't a valid color name, do nothing. OLDVAL is the old value of
1998 the frame parameter. */
2000 void
2001 x_set_scroll_bar_foreground (f, value, oldval)
2002 struct frame *f;
2003 Lisp_Object value, oldval;
2005 unsigned long pixel;
2007 if (STRINGP (value))
2008 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2009 else
2010 pixel = -1;
2012 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2013 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2015 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2016 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2018 /* Remove all scroll bars because they have wrong colors. */
2019 if (condemn_scroll_bars_hook)
2020 (*condemn_scroll_bars_hook) (f);
2021 if (judge_scroll_bars_hook)
2022 (*judge_scroll_bars_hook) (f);
2024 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2025 redraw_frame (f);
2030 /* Set the background color for scroll bars on frame F to VALUE VALUE
2031 should be a string, a color name. If it isn't a string or isn't a
2032 valid color name, do nothing. OLDVAL is the old value of the frame
2033 parameter. */
2035 void
2036 x_set_scroll_bar_background (f, value, oldval)
2037 struct frame *f;
2038 Lisp_Object value, oldval;
2040 unsigned long pixel;
2042 if (STRINGP (value))
2043 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2044 else
2045 pixel = -1;
2047 if (f->output_data.x->scroll_bar_background_pixel != -1)
2048 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2050 f->output_data.x->scroll_bar_background_pixel = pixel;
2051 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2053 /* Remove all scroll bars because they have wrong colors. */
2054 if (condemn_scroll_bars_hook)
2055 (*condemn_scroll_bars_hook) (f);
2056 if (judge_scroll_bars_hook)
2057 (*judge_scroll_bars_hook) (f);
2059 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2060 redraw_frame (f);
2065 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2066 x_id_name.
2068 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2069 name; if NAME is a string, set F's name to NAME and set
2070 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2072 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2073 suggesting a new name, which lisp code should override; if
2074 F->explicit_name is set, ignore the new name; otherwise, set it. */
2076 void
2077 x_set_name (f, name, explicit)
2078 struct frame *f;
2079 Lisp_Object name;
2080 int explicit;
2082 /* Make sure that requests from lisp code override requests from
2083 Emacs redisplay code. */
2084 if (explicit)
2086 /* If we're switching from explicit to implicit, we had better
2087 update the mode lines and thereby update the title. */
2088 if (f->explicit_name && NILP (name))
2089 update_mode_lines = 1;
2091 f->explicit_name = ! NILP (name);
2093 else if (f->explicit_name)
2094 return;
2096 /* If NAME is nil, set the name to the x_id_name. */
2097 if (NILP (name))
2099 /* Check for no change needed in this very common case
2100 before we do any consing. */
2101 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2102 XSTRING (f->name)->data))
2103 return;
2104 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2106 else
2107 CHECK_STRING (name, 0);
2109 /* Don't change the name if it's already NAME. */
2110 if (! NILP (Fstring_equal (name, f->name)))
2111 return;
2113 f->name = name;
2115 /* For setting the frame title, the title parameter should override
2116 the name parameter. */
2117 if (! NILP (f->title))
2118 name = f->title;
2120 if (FRAME_X_WINDOW (f))
2122 BLOCK_INPUT;
2123 #ifdef HAVE_X11R4
2125 XTextProperty text, icon;
2126 Lisp_Object icon_name;
2128 text.value = XSTRING (name)->data;
2129 text.encoding = XA_STRING;
2130 text.format = 8;
2131 text.nitems = STRING_BYTES (XSTRING (name));
2133 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
2135 icon.value = XSTRING (icon_name)->data;
2136 icon.encoding = XA_STRING;
2137 icon.format = 8;
2138 icon.nitems = STRING_BYTES (XSTRING (icon_name));
2139 #ifdef USE_X_TOOLKIT
2140 XSetWMName (FRAME_X_DISPLAY (f),
2141 XtWindow (f->output_data.x->widget), &text);
2142 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2143 &icon);
2144 #else /* not USE_X_TOOLKIT */
2145 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2146 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2147 #endif /* not USE_X_TOOLKIT */
2149 #else /* not HAVE_X11R4 */
2150 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2151 XSTRING (name)->data);
2152 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2153 XSTRING (name)->data);
2154 #endif /* not HAVE_X11R4 */
2155 UNBLOCK_INPUT;
2159 /* This function should be called when the user's lisp code has
2160 specified a name for the frame; the name will override any set by the
2161 redisplay code. */
2162 void
2163 x_explicitly_set_name (f, arg, oldval)
2164 FRAME_PTR f;
2165 Lisp_Object arg, oldval;
2167 x_set_name (f, arg, 1);
2170 /* This function should be called by Emacs redisplay code to set the
2171 name; names set this way will never override names set by the user's
2172 lisp code. */
2173 void
2174 x_implicitly_set_name (f, arg, oldval)
2175 FRAME_PTR f;
2176 Lisp_Object arg, oldval;
2178 x_set_name (f, arg, 0);
2181 /* Change the title of frame F to NAME.
2182 If NAME is nil, use the frame name as the title.
2184 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2185 name; if NAME is a string, set F's name to NAME and set
2186 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2188 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2189 suggesting a new name, which lisp code should override; if
2190 F->explicit_name is set, ignore the new name; otherwise, set it. */
2192 void
2193 x_set_title (f, name, old_name)
2194 struct frame *f;
2195 Lisp_Object name, old_name;
2197 /* Don't change the title if it's already NAME. */
2198 if (EQ (name, f->title))
2199 return;
2201 update_mode_lines = 1;
2203 f->title = name;
2205 if (NILP (name))
2206 name = f->name;
2207 else
2208 CHECK_STRING (name, 0);
2210 if (FRAME_X_WINDOW (f))
2212 BLOCK_INPUT;
2213 #ifdef HAVE_X11R4
2215 XTextProperty text, icon;
2216 Lisp_Object icon_name;
2218 text.value = XSTRING (name)->data;
2219 text.encoding = XA_STRING;
2220 text.format = 8;
2221 text.nitems = STRING_BYTES (XSTRING (name));
2223 icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
2225 icon.value = XSTRING (icon_name)->data;
2226 icon.encoding = XA_STRING;
2227 icon.format = 8;
2228 icon.nitems = STRING_BYTES (XSTRING (icon_name));
2229 #ifdef USE_X_TOOLKIT
2230 XSetWMName (FRAME_X_DISPLAY (f),
2231 XtWindow (f->output_data.x->widget), &text);
2232 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2233 &icon);
2234 #else /* not USE_X_TOOLKIT */
2235 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2236 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2237 #endif /* not USE_X_TOOLKIT */
2239 #else /* not HAVE_X11R4 */
2240 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2241 XSTRING (name)->data);
2242 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2243 XSTRING (name)->data);
2244 #endif /* not HAVE_X11R4 */
2245 UNBLOCK_INPUT;
2249 void
2250 x_set_autoraise (f, arg, oldval)
2251 struct frame *f;
2252 Lisp_Object arg, oldval;
2254 f->auto_raise = !EQ (Qnil, arg);
2257 void
2258 x_set_autolower (f, arg, oldval)
2259 struct frame *f;
2260 Lisp_Object arg, oldval;
2262 f->auto_lower = !EQ (Qnil, arg);
2265 void
2266 x_set_unsplittable (f, arg, oldval)
2267 struct frame *f;
2268 Lisp_Object arg, oldval;
2270 f->no_split = !NILP (arg);
2273 void
2274 x_set_vertical_scroll_bars (f, arg, oldval)
2275 struct frame *f;
2276 Lisp_Object arg, oldval;
2278 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2279 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2280 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2281 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2283 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2284 = (NILP (arg)
2285 ? vertical_scroll_bar_none
2286 : EQ (Qright, arg)
2287 ? vertical_scroll_bar_right
2288 : vertical_scroll_bar_left);
2290 /* We set this parameter before creating the X window for the
2291 frame, so we can get the geometry right from the start.
2292 However, if the window hasn't been created yet, we shouldn't
2293 call x_set_window_size. */
2294 if (FRAME_X_WINDOW (f))
2295 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2296 do_pending_window_change (0);
2300 void
2301 x_set_scroll_bar_width (f, arg, oldval)
2302 struct frame *f;
2303 Lisp_Object arg, oldval;
2305 int wid = FONT_WIDTH (f->output_data.x->font);
2307 if (NILP (arg))
2309 #ifdef USE_TOOLKIT_SCROLL_BARS
2310 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2311 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2312 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2313 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2314 #else
2315 /* Make the actual width at least 14 pixels and a multiple of a
2316 character width. */
2317 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2319 /* Use all of that space (aside from required margins) for the
2320 scroll bar. */
2321 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2322 #endif
2324 if (FRAME_X_WINDOW (f))
2325 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2326 do_pending_window_change (0);
2328 else if (INTEGERP (arg) && XINT (arg) > 0
2329 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2331 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2332 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2334 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2335 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2336 if (FRAME_X_WINDOW (f))
2337 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2340 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2341 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2342 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2347 /* Subroutines of creating an X frame. */
2349 /* Make sure that Vx_resource_name is set to a reasonable value.
2350 Fix it up, or set it to `emacs' if it is too hopeless. */
2352 static void
2353 validate_x_resource_name ()
2355 int len = 0;
2356 /* Number of valid characters in the resource name. */
2357 int good_count = 0;
2358 /* Number of invalid characters in the resource name. */
2359 int bad_count = 0;
2360 Lisp_Object new;
2361 int i;
2363 if (!STRINGP (Vx_resource_class))
2364 Vx_resource_class = build_string (EMACS_CLASS);
2366 if (STRINGP (Vx_resource_name))
2368 unsigned char *p = XSTRING (Vx_resource_name)->data;
2369 int i;
2371 len = STRING_BYTES (XSTRING (Vx_resource_name));
2373 /* Only letters, digits, - and _ are valid in resource names.
2374 Count the valid characters and count the invalid ones. */
2375 for (i = 0; i < len; i++)
2377 int c = p[i];
2378 if (! ((c >= 'a' && c <= 'z')
2379 || (c >= 'A' && c <= 'Z')
2380 || (c >= '0' && c <= '9')
2381 || c == '-' || c == '_'))
2382 bad_count++;
2383 else
2384 good_count++;
2387 else
2388 /* Not a string => completely invalid. */
2389 bad_count = 5, good_count = 0;
2391 /* If name is valid already, return. */
2392 if (bad_count == 0)
2393 return;
2395 /* If name is entirely invalid, or nearly so, use `emacs'. */
2396 if (good_count == 0
2397 || (good_count == 1 && bad_count > 0))
2399 Vx_resource_name = build_string ("emacs");
2400 return;
2403 /* Name is partly valid. Copy it and replace the invalid characters
2404 with underscores. */
2406 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2408 for (i = 0; i < len; i++)
2410 int c = XSTRING (new)->data[i];
2411 if (! ((c >= 'a' && c <= 'z')
2412 || (c >= 'A' && c <= 'Z')
2413 || (c >= '0' && c <= '9')
2414 || c == '-' || c == '_'))
2415 XSTRING (new)->data[i] = '_';
2420 extern char *x_get_string_resource ();
2422 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2423 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2424 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2425 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2426 the name specified by the `-name' or `-rn' command-line arguments.\n\
2428 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2429 class, respectively. You must specify both of them or neither.\n\
2430 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2431 and the class is `Emacs.CLASS.SUBCLASS'.")
2432 (attribute, class, component, subclass)
2433 Lisp_Object attribute, class, component, subclass;
2435 register char *value;
2436 char *name_key;
2437 char *class_key;
2439 check_x ();
2441 CHECK_STRING (attribute, 0);
2442 CHECK_STRING (class, 0);
2444 if (!NILP (component))
2445 CHECK_STRING (component, 1);
2446 if (!NILP (subclass))
2447 CHECK_STRING (subclass, 2);
2448 if (NILP (component) != NILP (subclass))
2449 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2451 validate_x_resource_name ();
2453 /* Allocate space for the components, the dots which separate them,
2454 and the final '\0'. Make them big enough for the worst case. */
2455 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2456 + (STRINGP (component)
2457 ? STRING_BYTES (XSTRING (component)) : 0)
2458 + STRING_BYTES (XSTRING (attribute))
2459 + 3);
2461 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2462 + STRING_BYTES (XSTRING (class))
2463 + (STRINGP (subclass)
2464 ? STRING_BYTES (XSTRING (subclass)) : 0)
2465 + 3);
2467 /* Start with emacs.FRAMENAME for the name (the specific one)
2468 and with `Emacs' for the class key (the general one). */
2469 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2470 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2472 strcat (class_key, ".");
2473 strcat (class_key, XSTRING (class)->data);
2475 if (!NILP (component))
2477 strcat (class_key, ".");
2478 strcat (class_key, XSTRING (subclass)->data);
2480 strcat (name_key, ".");
2481 strcat (name_key, XSTRING (component)->data);
2484 strcat (name_key, ".");
2485 strcat (name_key, XSTRING (attribute)->data);
2487 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2488 name_key, class_key);
2490 if (value != (char *) 0)
2491 return build_string (value);
2492 else
2493 return Qnil;
2496 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2498 Lisp_Object
2499 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2500 struct x_display_info *dpyinfo;
2501 Lisp_Object attribute, class, component, subclass;
2503 register char *value;
2504 char *name_key;
2505 char *class_key;
2507 check_x ();
2509 CHECK_STRING (attribute, 0);
2510 CHECK_STRING (class, 0);
2512 if (!NILP (component))
2513 CHECK_STRING (component, 1);
2514 if (!NILP (subclass))
2515 CHECK_STRING (subclass, 2);
2516 if (NILP (component) != NILP (subclass))
2517 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2519 validate_x_resource_name ();
2521 /* Allocate space for the components, the dots which separate them,
2522 and the final '\0'. Make them big enough for the worst case. */
2523 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2524 + (STRINGP (component)
2525 ? STRING_BYTES (XSTRING (component)) : 0)
2526 + STRING_BYTES (XSTRING (attribute))
2527 + 3);
2529 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2530 + STRING_BYTES (XSTRING (class))
2531 + (STRINGP (subclass)
2532 ? STRING_BYTES (XSTRING (subclass)) : 0)
2533 + 3);
2535 /* Start with emacs.FRAMENAME for the name (the specific one)
2536 and with `Emacs' for the class key (the general one). */
2537 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2538 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2540 strcat (class_key, ".");
2541 strcat (class_key, XSTRING (class)->data);
2543 if (!NILP (component))
2545 strcat (class_key, ".");
2546 strcat (class_key, XSTRING (subclass)->data);
2548 strcat (name_key, ".");
2549 strcat (name_key, XSTRING (component)->data);
2552 strcat (name_key, ".");
2553 strcat (name_key, XSTRING (attribute)->data);
2555 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2557 if (value != (char *) 0)
2558 return build_string (value);
2559 else
2560 return Qnil;
2563 /* Used when C code wants a resource value. */
2565 char *
2566 x_get_resource_string (attribute, class)
2567 char *attribute, *class;
2569 char *name_key;
2570 char *class_key;
2571 struct frame *sf = SELECTED_FRAME ();
2573 /* Allocate space for the components, the dots which separate them,
2574 and the final '\0'. */
2575 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2576 + strlen (attribute) + 2);
2577 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2578 + strlen (class) + 2);
2580 sprintf (name_key, "%s.%s",
2581 XSTRING (Vinvocation_name)->data,
2582 attribute);
2583 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2585 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2586 name_key, class_key);
2589 /* Types we might convert a resource string into. */
2590 enum resource_types
2592 RES_TYPE_NUMBER,
2593 RES_TYPE_FLOAT,
2594 RES_TYPE_BOOLEAN,
2595 RES_TYPE_STRING,
2596 RES_TYPE_SYMBOL
2599 /* Return the value of parameter PARAM.
2601 First search ALIST, then Vdefault_frame_alist, then the X defaults
2602 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2604 Convert the resource to the type specified by desired_type.
2606 If no default is specified, return Qunbound. If you call
2607 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2608 and don't let it get stored in any Lisp-visible variables! */
2610 static Lisp_Object
2611 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2612 struct x_display_info *dpyinfo;
2613 Lisp_Object alist, param;
2614 char *attribute;
2615 char *class;
2616 enum resource_types type;
2618 register Lisp_Object tem;
2620 tem = Fassq (param, alist);
2621 if (EQ (tem, Qnil))
2622 tem = Fassq (param, Vdefault_frame_alist);
2623 if (EQ (tem, Qnil))
2626 if (attribute)
2628 tem = display_x_get_resource (dpyinfo,
2629 build_string (attribute),
2630 build_string (class),
2631 Qnil, Qnil);
2633 if (NILP (tem))
2634 return Qunbound;
2636 switch (type)
2638 case RES_TYPE_NUMBER:
2639 return make_number (atoi (XSTRING (tem)->data));
2641 case RES_TYPE_FLOAT:
2642 return make_float (atof (XSTRING (tem)->data));
2644 case RES_TYPE_BOOLEAN:
2645 tem = Fdowncase (tem);
2646 if (!strcmp (XSTRING (tem)->data, "on")
2647 || !strcmp (XSTRING (tem)->data, "true"))
2648 return Qt;
2649 else
2650 return Qnil;
2652 case RES_TYPE_STRING:
2653 return tem;
2655 case RES_TYPE_SYMBOL:
2656 /* As a special case, we map the values `true' and `on'
2657 to Qt, and `false' and `off' to Qnil. */
2659 Lisp_Object lower;
2660 lower = Fdowncase (tem);
2661 if (!strcmp (XSTRING (lower)->data, "on")
2662 || !strcmp (XSTRING (lower)->data, "true"))
2663 return Qt;
2664 else if (!strcmp (XSTRING (lower)->data, "off")
2665 || !strcmp (XSTRING (lower)->data, "false"))
2666 return Qnil;
2667 else
2668 return Fintern (tem, Qnil);
2671 default:
2672 abort ();
2675 else
2676 return Qunbound;
2678 return Fcdr (tem);
2681 /* Like x_get_arg, but also record the value in f->param_alist. */
2683 static Lisp_Object
2684 x_get_and_record_arg (f, alist, param, attribute, class, type)
2685 struct frame *f;
2686 Lisp_Object alist, param;
2687 char *attribute;
2688 char *class;
2689 enum resource_types type;
2691 Lisp_Object value;
2693 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2694 attribute, class, type);
2695 if (! NILP (value))
2696 store_frame_param (f, param, value);
2698 return value;
2701 /* Record in frame F the specified or default value according to ALIST
2702 of the parameter named PROP (a Lisp symbol).
2703 If no value is specified for PROP, look for an X default for XPROP
2704 on the frame named NAME.
2705 If that is not found either, use the value DEFLT. */
2707 static Lisp_Object
2708 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2709 struct frame *f;
2710 Lisp_Object alist;
2711 Lisp_Object prop;
2712 Lisp_Object deflt;
2713 char *xprop;
2714 char *xclass;
2715 enum resource_types type;
2717 Lisp_Object tem;
2719 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2720 if (EQ (tem, Qunbound))
2721 tem = deflt;
2722 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2723 return tem;
2727 /* Record in frame F the specified or default value according to ALIST
2728 of the parameter named PROP (a Lisp symbol). If no value is
2729 specified for PROP, look for an X default for XPROP on the frame
2730 named NAME. If that is not found either, use the value DEFLT. */
2732 static Lisp_Object
2733 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2734 foreground_p)
2735 struct frame *f;
2736 Lisp_Object alist;
2737 Lisp_Object prop;
2738 char *xprop;
2739 char *xclass;
2740 int foreground_p;
2742 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2743 Lisp_Object tem;
2745 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2746 if (EQ (tem, Qunbound))
2748 #ifdef USE_TOOLKIT_SCROLL_BARS
2750 /* See if an X resource for the scroll bar color has been
2751 specified. */
2752 tem = display_x_get_resource (dpyinfo,
2753 build_string (foreground_p
2754 ? "foreground"
2755 : "background"),
2756 build_string (""),
2757 build_string ("verticalScrollBar"),
2758 build_string (""));
2759 if (!STRINGP (tem))
2761 /* If nothing has been specified, scroll bars will use a
2762 toolkit-dependent default. Because these defaults are
2763 difficult to get at without actually creating a scroll
2764 bar, use nil to indicate that no color has been
2765 specified. */
2766 tem = Qnil;
2769 #else /* not USE_TOOLKIT_SCROLL_BARS */
2771 tem = Qnil;
2773 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2776 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2777 return tem;
2782 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2783 "Parse an X-style geometry string STRING.\n\
2784 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2785 The properties returned may include `top', `left', `height', and `width'.\n\
2786 The value of `left' or `top' may be an integer,\n\
2787 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2788 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2789 (string)
2790 Lisp_Object string;
2792 int geometry, x, y;
2793 unsigned int width, height;
2794 Lisp_Object result;
2796 CHECK_STRING (string, 0);
2798 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2799 &x, &y, &width, &height);
2801 #if 0
2802 if (!!(geometry & XValue) != !!(geometry & YValue))
2803 error ("Must specify both x and y position, or neither");
2804 #endif
2806 result = Qnil;
2807 if (geometry & XValue)
2809 Lisp_Object element;
2811 if (x >= 0 && (geometry & XNegative))
2812 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2813 else if (x < 0 && ! (geometry & XNegative))
2814 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2815 else
2816 element = Fcons (Qleft, make_number (x));
2817 result = Fcons (element, result);
2820 if (geometry & YValue)
2822 Lisp_Object element;
2824 if (y >= 0 && (geometry & YNegative))
2825 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2826 else if (y < 0 && ! (geometry & YNegative))
2827 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2828 else
2829 element = Fcons (Qtop, make_number (y));
2830 result = Fcons (element, result);
2833 if (geometry & WidthValue)
2834 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2835 if (geometry & HeightValue)
2836 result = Fcons (Fcons (Qheight, make_number (height)), result);
2838 return result;
2841 /* Calculate the desired size and position of this window,
2842 and return the flags saying which aspects were specified.
2844 This function does not make the coordinates positive. */
2846 #define DEFAULT_ROWS 40
2847 #define DEFAULT_COLS 80
2849 static int
2850 x_figure_window_size (f, parms)
2851 struct frame *f;
2852 Lisp_Object parms;
2854 register Lisp_Object tem0, tem1, tem2;
2855 long window_prompting = 0;
2856 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2858 /* Default values if we fall through.
2859 Actually, if that happens we should get
2860 window manager prompting. */
2861 SET_FRAME_WIDTH (f, DEFAULT_COLS);
2862 f->height = DEFAULT_ROWS;
2863 /* Window managers expect that if program-specified
2864 positions are not (0,0), they're intentional, not defaults. */
2865 f->output_data.x->top_pos = 0;
2866 f->output_data.x->left_pos = 0;
2868 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
2869 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
2870 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
2871 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2873 if (!EQ (tem0, Qunbound))
2875 CHECK_NUMBER (tem0, 0);
2876 f->height = XINT (tem0);
2878 if (!EQ (tem1, Qunbound))
2880 CHECK_NUMBER (tem1, 0);
2881 SET_FRAME_WIDTH (f, XINT (tem1));
2883 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2884 window_prompting |= USSize;
2885 else
2886 window_prompting |= PSize;
2889 f->output_data.x->vertical_scroll_bar_extra
2890 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2892 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2893 f->output_data.x->flags_areas_extra
2894 = FRAME_FLAGS_AREA_WIDTH (f);
2895 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2896 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2898 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
2899 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
2900 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
2901 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2903 if (EQ (tem0, Qminus))
2905 f->output_data.x->top_pos = 0;
2906 window_prompting |= YNegative;
2908 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
2909 && CONSP (XCDR (tem0))
2910 && INTEGERP (XCAR (XCDR (tem0))))
2912 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
2913 window_prompting |= YNegative;
2915 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
2916 && CONSP (XCDR (tem0))
2917 && INTEGERP (XCAR (XCDR (tem0))))
2919 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
2921 else if (EQ (tem0, Qunbound))
2922 f->output_data.x->top_pos = 0;
2923 else
2925 CHECK_NUMBER (tem0, 0);
2926 f->output_data.x->top_pos = XINT (tem0);
2927 if (f->output_data.x->top_pos < 0)
2928 window_prompting |= YNegative;
2931 if (EQ (tem1, Qminus))
2933 f->output_data.x->left_pos = 0;
2934 window_prompting |= XNegative;
2936 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
2937 && CONSP (XCDR (tem1))
2938 && INTEGERP (XCAR (XCDR (tem1))))
2940 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
2941 window_prompting |= XNegative;
2943 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
2944 && CONSP (XCDR (tem1))
2945 && INTEGERP (XCAR (XCDR (tem1))))
2947 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
2949 else if (EQ (tem1, Qunbound))
2950 f->output_data.x->left_pos = 0;
2951 else
2953 CHECK_NUMBER (tem1, 0);
2954 f->output_data.x->left_pos = XINT (tem1);
2955 if (f->output_data.x->left_pos < 0)
2956 window_prompting |= XNegative;
2959 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2960 window_prompting |= USPosition;
2961 else
2962 window_prompting |= PPosition;
2965 return window_prompting;
2968 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2970 Status
2971 XSetWMProtocols (dpy, w, protocols, count)
2972 Display *dpy;
2973 Window w;
2974 Atom *protocols;
2975 int count;
2977 Atom prop;
2978 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2979 if (prop == None) return False;
2980 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2981 (unsigned char *) protocols, count);
2982 return True;
2984 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2986 #ifdef USE_X_TOOLKIT
2988 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2989 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2990 already be present because of the toolkit (Motif adds some of them,
2991 for example, but Xt doesn't). */
2993 static void
2994 hack_wm_protocols (f, widget)
2995 FRAME_PTR f;
2996 Widget widget;
2998 Display *dpy = XtDisplay (widget);
2999 Window w = XtWindow (widget);
3000 int need_delete = 1;
3001 int need_focus = 1;
3002 int need_save = 1;
3004 BLOCK_INPUT;
3006 Atom type, *atoms = 0;
3007 int format = 0;
3008 unsigned long nitems = 0;
3009 unsigned long bytes_after;
3011 if ((XGetWindowProperty (dpy, w,
3012 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3013 (long)0, (long)100, False, XA_ATOM,
3014 &type, &format, &nitems, &bytes_after,
3015 (unsigned char **) &atoms)
3016 == Success)
3017 && format == 32 && type == XA_ATOM)
3018 while (nitems > 0)
3020 nitems--;
3021 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3022 need_delete = 0;
3023 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3024 need_focus = 0;
3025 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3026 need_save = 0;
3028 if (atoms) XFree ((char *) atoms);
3031 Atom props [10];
3032 int count = 0;
3033 if (need_delete)
3034 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3035 if (need_focus)
3036 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3037 if (need_save)
3038 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3039 if (count)
3040 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3041 XA_ATOM, 32, PropModeAppend,
3042 (unsigned char *) props, count);
3044 UNBLOCK_INPUT;
3046 #endif
3050 /* Support routines for XIC (X Input Context). */
3052 #ifdef HAVE_X_I18N
3054 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3055 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3058 /* Supported XIM styles, ordered by preferenc. */
3060 static XIMStyle supported_xim_styles[] =
3062 XIMPreeditPosition | XIMStatusArea,
3063 XIMPreeditPosition | XIMStatusNothing,
3064 XIMPreeditPosition | XIMStatusNone,
3065 XIMPreeditNothing | XIMStatusArea,
3066 XIMPreeditNothing | XIMStatusNothing,
3067 XIMPreeditNothing | XIMStatusNone,
3068 XIMPreeditNone | XIMStatusArea,
3069 XIMPreeditNone | XIMStatusNothing,
3070 XIMPreeditNone | XIMStatusNone,
3075 /* Create an X fontset on frame F with base font name
3076 BASE_FONTNAME.. */
3078 static XFontSet
3079 xic_create_xfontset (f, base_fontname)
3080 struct frame *f;
3081 char *base_fontname;
3083 XFontSet xfs;
3084 char **missing_list;
3085 int missing_count;
3086 char *def_string;
3088 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3089 base_fontname, &missing_list,
3090 &missing_count, &def_string);
3091 if (missing_list)
3092 XFreeStringList (missing_list);
3094 /* No need to free def_string. */
3095 return xfs;
3099 /* Value is the best input style, given user preferences USER (already
3100 checked to be supported by Emacs), and styles supported by the
3101 input method XIM. */
3103 static XIMStyle
3104 best_xim_style (user, xim)
3105 XIMStyles *user;
3106 XIMStyles *xim;
3108 int i, j;
3110 for (i = 0; i < user->count_styles; ++i)
3111 for (j = 0; j < xim->count_styles; ++j)
3112 if (user->supported_styles[i] == xim->supported_styles[j])
3113 return user->supported_styles[i];
3115 /* Return the default style. */
3116 return XIMPreeditNothing | XIMStatusNothing;
3119 /* Create XIC for frame F. */
3121 void
3122 create_frame_xic (f)
3123 struct frame *f;
3125 #ifndef X_I18N_INHIBITED
3126 XIM xim;
3127 XIC xic = NULL;
3128 XFontSet xfs = NULL;
3129 static XIMStyle xic_style;
3131 if (FRAME_XIC (f))
3132 return;
3134 xim = FRAME_X_XIM (f);
3135 if (xim)
3137 XRectangle s_area;
3138 XPoint spot;
3139 XVaNestedList preedit_attr;
3140 XVaNestedList status_attr;
3141 char *base_fontname;
3142 int fontset;
3144 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3145 spot.x = 0; spot.y = 1;
3146 /* Create X fontset. */
3147 fontset = FRAME_FONTSET (f);
3148 if (fontset < 0)
3149 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3150 else
3152 struct fontset_info *fontsetp;
3153 int len = 0;
3154 int i;
3156 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
3157 for (i = 0; i <= MAX_CHARSET; i++)
3158 if (fontsetp->fontname[i])
3159 len += strlen (fontsetp->fontname[i]) + 1;
3160 base_fontname = alloca (len);
3161 strcpy (base_fontname, fontsetp->fontname[CHARSET_ASCII]);
3162 for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
3163 if (fontsetp->fontname[i])
3165 strcat (base_fontname, ",");
3166 strcat (base_fontname, fontsetp->fontname[i]);
3169 xfs = xic_create_xfontset (f, base_fontname);
3171 /* Determine XIC style. */
3172 if (xic_style == 0)
3174 XIMStyles supported_list;
3175 supported_list.count_styles = (sizeof supported_xim_styles
3176 / sizeof supported_xim_styles[0]);
3177 supported_list.supported_styles = supported_xim_styles;
3178 xic_style = best_xim_style (&supported_list,
3179 FRAME_X_XIM_STYLES (f));
3182 preedit_attr = XVaCreateNestedList (0,
3183 XNFontSet, xfs,
3184 XNForeground,
3185 FRAME_FOREGROUND_PIXEL (f),
3186 XNBackground,
3187 FRAME_BACKGROUND_PIXEL (f),
3188 (xic_style & XIMPreeditPosition
3189 ? XNSpotLocation
3190 : NULL),
3191 &spot,
3192 NULL);
3193 status_attr = XVaCreateNestedList (0,
3194 XNArea,
3195 &s_area,
3196 XNFontSet,
3197 xfs,
3198 XNForeground,
3199 FRAME_FOREGROUND_PIXEL (f),
3200 XNBackground,
3201 FRAME_BACKGROUND_PIXEL (f),
3202 NULL);
3204 xic = XCreateIC (xim,
3205 XNInputStyle, xic_style,
3206 XNClientWindow, FRAME_X_WINDOW(f),
3207 XNFocusWindow, FRAME_X_WINDOW(f),
3208 XNStatusAttributes, status_attr,
3209 XNPreeditAttributes, preedit_attr,
3210 NULL);
3211 XFree (preedit_attr);
3212 XFree (status_attr);
3215 FRAME_XIC (f) = xic;
3216 FRAME_XIC_STYLE (f) = xic_style;
3217 FRAME_XIC_FONTSET (f) = xfs;
3218 #else /* X_I18N_INHIBITED */
3219 FRAME_XIC (f) = NULL;
3220 FRAME_XIC_STYLE (f) = 0;
3221 FRAME_XIC_FONTSET (f) = NULL;
3222 #endif /* X_I18N_INHIBITED */
3226 /* Destroy XIC and free XIC fontset of frame F, if any. */
3228 void
3229 free_frame_xic (f)
3230 struct frame *f;
3232 if (FRAME_XIC (f) == NULL)
3233 return;
3235 XDestroyIC (FRAME_XIC (f));
3236 if (FRAME_XIC_FONTSET (f))
3237 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3239 FRAME_XIC (f) = NULL;
3240 FRAME_XIC_FONTSET (f) = NULL;
3244 /* Place preedit area for XIC of window W's frame to specified
3245 pixel position X/Y. X and Y are relative to window W. */
3247 void
3248 xic_set_preeditarea (w, x, y)
3249 struct window *w;
3250 int x, y;
3252 struct frame *f = XFRAME (w->frame);
3253 XVaNestedList attr;
3254 XPoint spot;
3256 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3257 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3258 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3259 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3260 XFree (attr);
3264 /* Place status area for XIC in bottom right corner of frame F.. */
3266 void
3267 xic_set_statusarea (f)
3268 struct frame *f;
3270 XIC xic = FRAME_XIC (f);
3271 XVaNestedList attr;
3272 XRectangle area;
3273 XRectangle *needed;
3275 /* Negotiate geometry of status area. If input method has existing
3276 status area, use its current size. */
3277 area.x = area.y = area.width = area.height = 0;
3278 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3279 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3280 XFree (attr);
3282 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3283 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3284 XFree (attr);
3286 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3288 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3289 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3290 XFree (attr);
3293 area.width = needed->width;
3294 area.height = needed->height;
3295 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3296 area.y = (PIXEL_HEIGHT (f) - area.height
3297 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3298 XFree (needed);
3300 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3301 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3302 XFree (attr);
3306 /* Set X fontset for XIC of frame F, using base font name
3307 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3309 void
3310 xic_set_xfontset (f, base_fontname)
3311 struct frame *f;
3312 char *base_fontname;
3314 XVaNestedList attr;
3315 XFontSet xfs;
3317 xfs = xic_create_xfontset (f, base_fontname);
3319 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3320 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3321 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3322 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3323 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3324 XFree (attr);
3326 if (FRAME_XIC_FONTSET (f))
3327 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3328 FRAME_XIC_FONTSET (f) = xfs;
3331 #endif /* HAVE_X_I18N */
3335 #ifdef USE_X_TOOLKIT
3337 /* Create and set up the X widget for frame F. */
3339 static void
3340 x_window (f, window_prompting, minibuffer_only)
3341 struct frame *f;
3342 long window_prompting;
3343 int minibuffer_only;
3345 XClassHint class_hints;
3346 XSetWindowAttributes attributes;
3347 unsigned long attribute_mask;
3349 Widget shell_widget;
3350 Widget pane_widget;
3351 Widget frame_widget;
3352 Arg al [25];
3353 int ac;
3355 BLOCK_INPUT;
3357 /* Use the resource name as the top-level widget name
3358 for looking up resources. Make a non-Lisp copy
3359 for the window manager, so GC relocation won't bother it.
3361 Elsewhere we specify the window name for the window manager. */
3364 char *str = (char *) XSTRING (Vx_resource_name)->data;
3365 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3366 strcpy (f->namebuf, str);
3369 ac = 0;
3370 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3371 XtSetArg (al[ac], XtNinput, 1); ac++;
3372 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3373 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3374 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3375 applicationShellWidgetClass,
3376 FRAME_X_DISPLAY (f), al, ac);
3378 f->output_data.x->widget = shell_widget;
3379 /* maybe_set_screen_title_format (shell_widget); */
3381 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3382 (widget_value *) NULL,
3383 shell_widget, False,
3384 (lw_callback) NULL,
3385 (lw_callback) NULL,
3386 (lw_callback) NULL,
3387 (lw_callback) NULL);
3389 f->output_data.x->column_widget = pane_widget;
3391 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3392 the emacs screen when changing menubar. This reduces flickering. */
3394 ac = 0;
3395 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3396 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3397 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3398 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3399 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3400 frame_widget = XtCreateWidget (f->namebuf,
3401 emacsFrameClass,
3402 pane_widget, al, ac);
3404 f->output_data.x->edit_widget = frame_widget;
3406 XtManageChild (frame_widget);
3408 /* Do some needed geometry management. */
3410 int len;
3411 char *tem, shell_position[32];
3412 Arg al[2];
3413 int ac = 0;
3414 int extra_borders = 0;
3415 int menubar_size
3416 = (f->output_data.x->menubar_widget
3417 ? (f->output_data.x->menubar_widget->core.height
3418 + f->output_data.x->menubar_widget->core.border_width)
3419 : 0);
3421 #if 0 /* Experimentally, we now get the right results
3422 for -geometry -0-0 without this. 24 Aug 96, rms. */
3423 if (FRAME_EXTERNAL_MENU_BAR (f))
3425 Dimension ibw = 0;
3426 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3427 menubar_size += ibw;
3429 #endif
3431 f->output_data.x->menubar_height = menubar_size;
3433 #ifndef USE_LUCID
3434 /* Motif seems to need this amount added to the sizes
3435 specified for the shell widget. The Athena/Lucid widgets don't.
3436 Both conclusions reached experimentally. -- rms. */
3437 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3438 &extra_borders, NULL);
3439 extra_borders *= 2;
3440 #endif
3442 /* Convert our geometry parameters into a geometry string
3443 and specify it.
3444 Note that we do not specify here whether the position
3445 is a user-specified or program-specified one.
3446 We pass that information later, in x_wm_set_size_hints. */
3448 int left = f->output_data.x->left_pos;
3449 int xneg = window_prompting & XNegative;
3450 int top = f->output_data.x->top_pos;
3451 int yneg = window_prompting & YNegative;
3452 if (xneg)
3453 left = -left;
3454 if (yneg)
3455 top = -top;
3457 if (window_prompting & USPosition)
3458 sprintf (shell_position, "=%dx%d%c%d%c%d",
3459 PIXEL_WIDTH (f) + extra_borders,
3460 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3461 (xneg ? '-' : '+'), left,
3462 (yneg ? '-' : '+'), top);
3463 else
3464 sprintf (shell_position, "=%dx%d",
3465 PIXEL_WIDTH (f) + extra_borders,
3466 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3469 len = strlen (shell_position) + 1;
3470 /* We don't free this because we don't know whether
3471 it is safe to free it while the frame exists.
3472 It isn't worth the trouble of arranging to free it
3473 when the frame is deleted. */
3474 tem = (char *) xmalloc (len);
3475 strncpy (tem, shell_position, len);
3476 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3477 XtSetValues (shell_widget, al, ac);
3480 XtManageChild (pane_widget);
3481 XtRealizeWidget (shell_widget);
3483 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3485 validate_x_resource_name ();
3487 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3488 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3489 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3491 #ifdef HAVE_X_I18N
3492 FRAME_XIC (f) = NULL;
3493 create_frame_xic (f);
3494 #endif
3496 f->output_data.x->wm_hints.input = True;
3497 f->output_data.x->wm_hints.flags |= InputHint;
3498 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3499 &f->output_data.x->wm_hints);
3501 hack_wm_protocols (f, shell_widget);
3503 #ifdef HACK_EDITRES
3504 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3505 #endif
3507 /* Do a stupid property change to force the server to generate a
3508 PropertyNotify event so that the event_stream server timestamp will
3509 be initialized to something relevant to the time we created the window.
3511 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3512 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3513 XA_ATOM, 32, PropModeAppend,
3514 (unsigned char*) NULL, 0);
3516 /* Make all the standard events reach the Emacs frame. */
3517 attributes.event_mask = STANDARD_EVENT_SET;
3519 #ifdef HAVE_X_I18N
3520 if (FRAME_XIC (f))
3522 /* XIM server might require some X events. */
3523 unsigned long fevent = NoEventMask;
3524 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3525 attributes.event_mask |= fevent;
3527 #endif /* HAVE_X_I18N */
3529 attribute_mask = CWEventMask;
3530 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3531 attribute_mask, &attributes);
3533 XtMapWidget (frame_widget);
3535 /* x_set_name normally ignores requests to set the name if the
3536 requested name is the same as the current name. This is the one
3537 place where that assumption isn't correct; f->name is set, but
3538 the X server hasn't been told. */
3540 Lisp_Object name;
3541 int explicit = f->explicit_name;
3543 f->explicit_name = 0;
3544 name = f->name;
3545 f->name = Qnil;
3546 x_set_name (f, name, explicit);
3549 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3550 f->output_data.x->text_cursor);
3552 UNBLOCK_INPUT;
3554 /* This is a no-op, except under Motif. Make sure main areas are
3555 set to something reasonable, in case we get an error later. */
3556 lw_set_main_areas (pane_widget, 0, frame_widget);
3559 #else /* not USE_X_TOOLKIT */
3561 /* Create and set up the X window for frame F. */
3563 void
3564 x_window (f)
3565 struct frame *f;
3568 XClassHint class_hints;
3569 XSetWindowAttributes attributes;
3570 unsigned long attribute_mask;
3572 attributes.background_pixel = f->output_data.x->background_pixel;
3573 attributes.border_pixel = f->output_data.x->border_pixel;
3574 attributes.bit_gravity = StaticGravity;
3575 attributes.backing_store = NotUseful;
3576 attributes.save_under = True;
3577 attributes.event_mask = STANDARD_EVENT_SET;
3578 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
3579 #if 0
3580 | CWBackingStore | CWSaveUnder
3581 #endif
3582 | CWEventMask);
3584 BLOCK_INPUT;
3585 FRAME_X_WINDOW (f)
3586 = XCreateWindow (FRAME_X_DISPLAY (f),
3587 f->output_data.x->parent_desc,
3588 f->output_data.x->left_pos,
3589 f->output_data.x->top_pos,
3590 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3591 f->output_data.x->border_width,
3592 CopyFromParent, /* depth */
3593 InputOutput, /* class */
3594 FRAME_X_DISPLAY_INFO (f)->visual,
3595 attribute_mask, &attributes);
3597 #ifdef HAVE_X_I18N
3598 create_frame_xic (f);
3599 if (FRAME_XIC (f))
3601 /* XIM server might require some X events. */
3602 unsigned long fevent = NoEventMask;
3603 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3604 attributes.event_mask |= fevent;
3605 attribute_mask = CWEventMask;
3606 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3607 attribute_mask, &attributes);
3609 #endif /* HAVE_X_I18N */
3611 validate_x_resource_name ();
3613 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3614 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3615 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3617 /* The menubar is part of the ordinary display;
3618 it does not count in addition to the height of the window. */
3619 f->output_data.x->menubar_height = 0;
3621 /* This indicates that we use the "Passive Input" input model.
3622 Unless we do this, we don't get the Focus{In,Out} events that we
3623 need to draw the cursor correctly. Accursed bureaucrats.
3624 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3626 f->output_data.x->wm_hints.input = True;
3627 f->output_data.x->wm_hints.flags |= InputHint;
3628 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3629 &f->output_data.x->wm_hints);
3630 f->output_data.x->wm_hints.icon_pixmap = None;
3632 /* Request "save yourself" and "delete window" commands from wm. */
3634 Atom protocols[2];
3635 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3636 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3637 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3640 /* x_set_name normally ignores requests to set the name if the
3641 requested name is the same as the current name. This is the one
3642 place where that assumption isn't correct; f->name is set, but
3643 the X server hasn't been told. */
3645 Lisp_Object name;
3646 int explicit = f->explicit_name;
3648 f->explicit_name = 0;
3649 name = f->name;
3650 f->name = Qnil;
3651 x_set_name (f, name, explicit);
3654 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3655 f->output_data.x->text_cursor);
3657 UNBLOCK_INPUT;
3659 if (FRAME_X_WINDOW (f) == 0)
3660 error ("Unable to create window");
3663 #endif /* not USE_X_TOOLKIT */
3665 /* Handle the icon stuff for this window. Perhaps later we might
3666 want an x_set_icon_position which can be called interactively as
3667 well. */
3669 static void
3670 x_icon (f, parms)
3671 struct frame *f;
3672 Lisp_Object parms;
3674 Lisp_Object icon_x, icon_y;
3675 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3677 /* Set the position of the icon. Note that twm groups all
3678 icons in an icon window. */
3679 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3680 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3681 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3683 CHECK_NUMBER (icon_x, 0);
3684 CHECK_NUMBER (icon_y, 0);
3686 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3687 error ("Both left and top icon corners of icon must be specified");
3689 BLOCK_INPUT;
3691 if (! EQ (icon_x, Qunbound))
3692 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3694 /* Start up iconic or window? */
3695 x_wm_set_window_state
3696 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3697 Qicon)
3698 ? IconicState
3699 : NormalState));
3701 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3702 ? f->icon_name
3703 : f->name))->data);
3705 UNBLOCK_INPUT;
3708 /* Make the GC's needed for this window, setting the
3709 background, border and mouse colors; also create the
3710 mouse cursor and the gray border tile. */
3712 static char cursor_bits[] =
3714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3720 static void
3721 x_make_gc (f)
3722 struct frame *f;
3724 XGCValues gc_values;
3726 BLOCK_INPUT;
3728 /* Create the GC's of this frame.
3729 Note that many default values are used. */
3731 /* Normal video */
3732 gc_values.font = f->output_data.x->font->fid;
3733 gc_values.foreground = f->output_data.x->foreground_pixel;
3734 gc_values.background = f->output_data.x->background_pixel;
3735 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3736 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
3737 FRAME_X_WINDOW (f),
3738 GCLineWidth | GCFont
3739 | GCForeground | GCBackground,
3740 &gc_values);
3742 /* Reverse video style. */
3743 gc_values.foreground = f->output_data.x->background_pixel;
3744 gc_values.background = f->output_data.x->foreground_pixel;
3745 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
3746 FRAME_X_WINDOW (f),
3747 GCFont | GCForeground | GCBackground
3748 | GCLineWidth,
3749 &gc_values);
3751 /* Cursor has cursor-color background, background-color foreground. */
3752 gc_values.foreground = f->output_data.x->background_pixel;
3753 gc_values.background = f->output_data.x->cursor_pixel;
3754 gc_values.fill_style = FillOpaqueStippled;
3755 gc_values.stipple
3756 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3757 FRAME_X_DISPLAY_INFO (f)->root_window,
3758 cursor_bits, 16, 16);
3759 f->output_data.x->cursor_gc
3760 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3761 (GCFont | GCForeground | GCBackground
3762 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3763 &gc_values);
3765 /* Reliefs. */
3766 f->output_data.x->white_relief.gc = 0;
3767 f->output_data.x->black_relief.gc = 0;
3769 /* Create the gray border tile used when the pointer is not in
3770 the frame. Since this depends on the frame's pixel values,
3771 this must be done on a per-frame basis. */
3772 f->output_data.x->border_tile
3773 = (XCreatePixmapFromBitmapData
3774 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3775 gray_bits, gray_width, gray_height,
3776 f->output_data.x->foreground_pixel,
3777 f->output_data.x->background_pixel,
3778 DefaultDepth (FRAME_X_DISPLAY (f),
3779 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3781 UNBLOCK_INPUT;
3784 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3785 1, 1, 0,
3786 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3787 Returns an Emacs frame object.\n\
3788 ALIST is an alist of frame parameters.\n\
3789 If the parameters specify that the frame should not have a minibuffer,\n\
3790 and do not specify a specific minibuffer window to use,\n\
3791 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3792 be shared by the new frame.\n\
3794 This function is an internal primitive--use `make-frame' instead.")
3795 (parms)
3796 Lisp_Object parms;
3798 struct frame *f;
3799 Lisp_Object frame, tem;
3800 Lisp_Object name;
3801 int minibuffer_only = 0;
3802 long window_prompting = 0;
3803 int width, height;
3804 int count = specpdl_ptr - specpdl;
3805 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3806 Lisp_Object display;
3807 struct x_display_info *dpyinfo = NULL;
3808 Lisp_Object parent;
3809 struct kboard *kb;
3811 check_x ();
3813 /* Use this general default value to start with
3814 until we know if this frame has a specified name. */
3815 Vx_resource_name = Vinvocation_name;
3817 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3818 if (EQ (display, Qunbound))
3819 display = Qnil;
3820 dpyinfo = check_x_display_info (display);
3821 #ifdef MULTI_KBOARD
3822 kb = dpyinfo->kboard;
3823 #else
3824 kb = &the_only_kboard;
3825 #endif
3827 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3828 if (!STRINGP (name)
3829 && ! EQ (name, Qunbound)
3830 && ! NILP (name))
3831 error ("Invalid frame name--not a string or nil");
3833 if (STRINGP (name))
3834 Vx_resource_name = name;
3836 /* See if parent window is specified. */
3837 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3838 if (EQ (parent, Qunbound))
3839 parent = Qnil;
3840 if (! NILP (parent))
3841 CHECK_NUMBER (parent, 0);
3843 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3844 /* No need to protect DISPLAY because that's not used after passing
3845 it to make_frame_without_minibuffer. */
3846 frame = Qnil;
3847 GCPRO4 (parms, parent, name, frame);
3848 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3849 RES_TYPE_SYMBOL);
3850 if (EQ (tem, Qnone) || NILP (tem))
3851 f = make_frame_without_minibuffer (Qnil, kb, display);
3852 else if (EQ (tem, Qonly))
3854 f = make_minibuffer_frame ();
3855 minibuffer_only = 1;
3857 else if (WINDOWP (tem))
3858 f = make_frame_without_minibuffer (tem, kb, display);
3859 else
3860 f = make_frame (1);
3862 XSETFRAME (frame, f);
3864 /* Note that X Windows does support scroll bars. */
3865 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3867 f->output_method = output_x_window;
3868 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3869 bzero (f->output_data.x, sizeof (struct x_output));
3870 f->output_data.x->icon_bitmap = -1;
3871 f->output_data.x->fontset = -1;
3872 f->output_data.x->scroll_bar_foreground_pixel = -1;
3873 f->output_data.x->scroll_bar_background_pixel = -1;
3875 f->icon_name
3876 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3877 RES_TYPE_STRING);
3878 if (! STRINGP (f->icon_name))
3879 f->icon_name = Qnil;
3881 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3882 #ifdef MULTI_KBOARD
3883 FRAME_KBOARD (f) = kb;
3884 #endif
3886 /* Specify the parent under which to make this X window. */
3888 if (!NILP (parent))
3890 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3891 f->output_data.x->explicit_parent = 1;
3893 else
3895 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3896 f->output_data.x->explicit_parent = 0;
3899 /* Set the name; the functions to which we pass f expect the name to
3900 be set. */
3901 if (EQ (name, Qunbound) || NILP (name))
3903 f->name = build_string (dpyinfo->x_id_name);
3904 f->explicit_name = 0;
3906 else
3908 f->name = name;
3909 f->explicit_name = 1;
3910 /* use the frame's title when getting resources for this frame. */
3911 specbind (Qx_resource_name, name);
3914 /* Create fontsets from `global_fontset_alist' before handling fonts. */
3915 for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
3916 fs_register_fontset (f, XCAR (tem));
3918 /* Extract the window parameters from the supplied values
3919 that are needed to determine window geometry. */
3921 Lisp_Object font;
3923 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3925 BLOCK_INPUT;
3926 /* First, try whatever font the caller has specified. */
3927 if (STRINGP (font))
3929 tem = Fquery_fontset (font, Qnil);
3930 if (STRINGP (tem))
3931 font = x_new_fontset (f, XSTRING (tem)->data);
3932 else
3933 font = x_new_font (f, XSTRING (font)->data);
3936 /* Try out a font which we hope has bold and italic variations. */
3937 if (!STRINGP (font))
3938 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3939 if (!STRINGP (font))
3940 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3941 if (! STRINGP (font))
3942 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3943 if (! STRINGP (font))
3944 /* This was formerly the first thing tried, but it finds too many fonts
3945 and takes too long. */
3946 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3947 /* If those didn't work, look for something which will at least work. */
3948 if (! STRINGP (font))
3949 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3950 UNBLOCK_INPUT;
3951 if (! STRINGP (font))
3952 font = build_string ("fixed");
3954 x_default_parameter (f, parms, Qfont, font,
3955 "font", "Font", RES_TYPE_STRING);
3958 #ifdef USE_LUCID
3959 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3960 whereby it fails to get any font. */
3961 xlwmenu_default_font = f->output_data.x->font;
3962 #endif
3964 x_default_parameter (f, parms, Qborder_width, make_number (2),
3965 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3967 /* This defaults to 2 in order to match xterm. We recognize either
3968 internalBorderWidth or internalBorder (which is what xterm calls
3969 it). */
3970 if (NILP (Fassq (Qinternal_border_width, parms)))
3972 Lisp_Object value;
3974 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3975 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3976 if (! EQ (value, Qunbound))
3977 parms = Fcons (Fcons (Qinternal_border_width, value),
3978 parms);
3980 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3981 "internalBorderWidth", "internalBorderWidth",
3982 RES_TYPE_NUMBER);
3983 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3984 "verticalScrollBars", "ScrollBars",
3985 RES_TYPE_SYMBOL);
3987 /* Also do the stuff which must be set before the window exists. */
3988 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3989 "foreground", "Foreground", RES_TYPE_STRING);
3990 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3991 "background", "Background", RES_TYPE_STRING);
3992 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3993 "pointerColor", "Foreground", RES_TYPE_STRING);
3994 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3995 "cursorColor", "Foreground", RES_TYPE_STRING);
3996 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3997 "borderColor", "BorderColor", RES_TYPE_STRING);
3998 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3999 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4001 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4002 "scrollBarForeground",
4003 "ScrollBarForeground", 1);
4004 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4005 "scrollBarBackground",
4006 "ScrollBarBackground", 0);
4008 /* Init faces before x_default_parameter is called for scroll-bar
4009 parameters because that function calls x_set_scroll_bar_width,
4010 which calls change_frame_size, which calls Fset_window_buffer,
4011 which runs hooks, which call Fvertical_motion. At the end, we
4012 end up in init_iterator with a null face cache, which should not
4013 happen. */
4014 init_frame_faces (f);
4016 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4017 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4018 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
4019 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4020 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4021 "bufferPredicate", "BufferPredicate",
4022 RES_TYPE_SYMBOL);
4023 x_default_parameter (f, parms, Qtitle, Qnil,
4024 "title", "Title", RES_TYPE_STRING);
4026 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4027 window_prompting = x_figure_window_size (f, parms);
4029 if (window_prompting & XNegative)
4031 if (window_prompting & YNegative)
4032 f->output_data.x->win_gravity = SouthEastGravity;
4033 else
4034 f->output_data.x->win_gravity = NorthEastGravity;
4036 else
4038 if (window_prompting & YNegative)
4039 f->output_data.x->win_gravity = SouthWestGravity;
4040 else
4041 f->output_data.x->win_gravity = NorthWestGravity;
4044 f->output_data.x->size_hint_flags = window_prompting;
4046 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4047 f->no_split = minibuffer_only || EQ (tem, Qt);
4049 /* Create the X widget or window. Add the tool-bar height to the
4050 initial frame height so that the user gets a text display area of
4051 the size he specified with -g or via .Xdefaults. Later changes
4052 of the tool-bar height don't change the frame size. This is done
4053 so that users can create tall Emacs frames without having to
4054 guess how tall the tool-bar will get. */
4055 f->height += FRAME_TOOL_BAR_LINES (f);
4057 #ifdef USE_X_TOOLKIT
4058 x_window (f, window_prompting, minibuffer_only);
4059 #else
4060 x_window (f);
4061 #endif
4063 x_icon (f, parms);
4064 x_make_gc (f);
4066 /* Now consider the frame official. */
4067 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4068 Vframe_list = Fcons (frame, Vframe_list);
4070 /* We need to do this after creating the X window, so that the
4071 icon-creation functions can say whose icon they're describing. */
4072 x_default_parameter (f, parms, Qicon_type, Qnil,
4073 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4075 x_default_parameter (f, parms, Qauto_raise, Qnil,
4076 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4077 x_default_parameter (f, parms, Qauto_lower, Qnil,
4078 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4079 x_default_parameter (f, parms, Qcursor_type, Qbox,
4080 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4081 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4082 "scrollBarWidth", "ScrollBarWidth",
4083 RES_TYPE_NUMBER);
4085 /* Dimensions, especially f->height, must be done via change_frame_size.
4086 Change will not be effected unless different from the current
4087 f->height. */
4088 width = f->width;
4089 height = f->height;
4090 f->height = 0;
4091 SET_FRAME_WIDTH (f, 0);
4092 change_frame_size (f, height, width, 1, 0, 0);
4094 /* Set up faces after all frame parameters are known. */
4095 call1 (Qface_set_after_frame_default, frame);
4097 #ifdef USE_X_TOOLKIT
4098 /* Create the menu bar. */
4099 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4101 /* If this signals an error, we haven't set size hints for the
4102 frame and we didn't make it visible. */
4103 initialize_frame_menubar (f);
4105 /* This is a no-op, except under Motif where it arranges the
4106 main window for the widgets on it. */
4107 lw_set_main_areas (f->output_data.x->column_widget,
4108 f->output_data.x->menubar_widget,
4109 f->output_data.x->edit_widget);
4111 #endif /* USE_X_TOOLKIT */
4113 /* Tell the server what size and position, etc, we want, and how
4114 badly we want them. This should be done after we have the menu
4115 bar so that its size can be taken into account. */
4116 BLOCK_INPUT;
4117 x_wm_set_size_hint (f, window_prompting, 0);
4118 UNBLOCK_INPUT;
4120 /* Make the window appear on the frame and enable display, unless
4121 the caller says not to. However, with explicit parent, Emacs
4122 cannot control visibility, so don't try. */
4123 if (! f->output_data.x->explicit_parent)
4125 Lisp_Object visibility;
4127 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4128 RES_TYPE_SYMBOL);
4129 if (EQ (visibility, Qunbound))
4130 visibility = Qt;
4132 if (EQ (visibility, Qicon))
4133 x_iconify_frame (f);
4134 else if (! NILP (visibility))
4135 x_make_frame_visible (f);
4136 else
4137 /* Must have been Qnil. */
4141 UNGCPRO;
4142 return unbind_to (count, frame);
4145 /* FRAME is used only to get a handle on the X display. We don't pass the
4146 display info directly because we're called from frame.c, which doesn't
4147 know about that structure. */
4149 Lisp_Object
4150 x_get_focus_frame (frame)
4151 struct frame *frame;
4153 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4154 Lisp_Object xfocus;
4155 if (! dpyinfo->x_focus_frame)
4156 return Qnil;
4158 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4159 return xfocus;
4163 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4164 "Internal function called by `color-defined-p', which see.")
4165 (color, frame)
4166 Lisp_Object color, frame;
4168 XColor foo;
4169 FRAME_PTR f = check_x_frame (frame);
4171 CHECK_STRING (color, 1);
4173 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4174 return Qt;
4175 else
4176 return Qnil;
4179 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4180 "Internal function called by `color-values', which see.")
4181 (color, frame)
4182 Lisp_Object color, frame;
4184 XColor foo;
4185 FRAME_PTR f = check_x_frame (frame);
4187 CHECK_STRING (color, 1);
4189 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4191 Lisp_Object rgb[3];
4193 rgb[0] = make_number (foo.red);
4194 rgb[1] = make_number (foo.green);
4195 rgb[2] = make_number (foo.blue);
4196 return Flist (3, rgb);
4198 else
4199 return Qnil;
4202 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4203 "Internal function called by `display-color-p', which see.")
4204 (display)
4205 Lisp_Object display;
4207 struct x_display_info *dpyinfo = check_x_display_info (display);
4209 if (dpyinfo->n_planes <= 2)
4210 return Qnil;
4212 switch (dpyinfo->visual->class)
4214 case StaticColor:
4215 case PseudoColor:
4216 case TrueColor:
4217 case DirectColor:
4218 return Qt;
4220 default:
4221 return Qnil;
4225 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4226 0, 1, 0,
4227 "Return t if the X display supports shades of gray.\n\
4228 Note that color displays do support shades of gray.\n\
4229 The optional argument DISPLAY specifies which display to ask about.\n\
4230 DISPLAY should be either a frame or a display name (a string).\n\
4231 If omitted or nil, that stands for the selected frame's display.")
4232 (display)
4233 Lisp_Object display;
4235 struct x_display_info *dpyinfo = check_x_display_info (display);
4237 if (dpyinfo->n_planes <= 1)
4238 return Qnil;
4240 switch (dpyinfo->visual->class)
4242 case StaticColor:
4243 case PseudoColor:
4244 case TrueColor:
4245 case DirectColor:
4246 case StaticGray:
4247 case GrayScale:
4248 return Qt;
4250 default:
4251 return Qnil;
4255 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4256 0, 1, 0,
4257 "Returns the width in pixels of the X display DISPLAY.\n\
4258 The optional argument DISPLAY specifies which display to ask about.\n\
4259 DISPLAY should be either a frame or a display name (a string).\n\
4260 If omitted or nil, that stands for the selected frame's display.")
4261 (display)
4262 Lisp_Object display;
4264 struct x_display_info *dpyinfo = check_x_display_info (display);
4266 return make_number (dpyinfo->width);
4269 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4270 Sx_display_pixel_height, 0, 1, 0,
4271 "Returns the height in pixels of the X display DISPLAY.\n\
4272 The optional argument DISPLAY specifies which display to ask about.\n\
4273 DISPLAY should be either a frame or a display name (a string).\n\
4274 If omitted or nil, that stands for the selected frame's display.")
4275 (display)
4276 Lisp_Object display;
4278 struct x_display_info *dpyinfo = check_x_display_info (display);
4280 return make_number (dpyinfo->height);
4283 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4284 0, 1, 0,
4285 "Returns the number of bitplanes of the X display DISPLAY.\n\
4286 The optional argument DISPLAY specifies which display to ask about.\n\
4287 DISPLAY should be either a frame or a display name (a string).\n\
4288 If omitted or nil, that stands for the selected frame's display.")
4289 (display)
4290 Lisp_Object display;
4292 struct x_display_info *dpyinfo = check_x_display_info (display);
4294 return make_number (dpyinfo->n_planes);
4297 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4298 0, 1, 0,
4299 "Returns the number of color cells of the X display DISPLAY.\n\
4300 The optional argument DISPLAY specifies which display to ask about.\n\
4301 DISPLAY should be either a frame or a display name (a string).\n\
4302 If omitted or nil, that stands for the selected frame's display.")
4303 (display)
4304 Lisp_Object display;
4306 struct x_display_info *dpyinfo = check_x_display_info (display);
4308 return make_number (DisplayCells (dpyinfo->display,
4309 XScreenNumberOfScreen (dpyinfo->screen)));
4312 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4313 Sx_server_max_request_size,
4314 0, 1, 0,
4315 "Returns the maximum request size of the X server of display DISPLAY.\n\
4316 The optional argument DISPLAY specifies which display to ask about.\n\
4317 DISPLAY should be either a frame or a display name (a string).\n\
4318 If omitted or nil, that stands for the selected frame's display.")
4319 (display)
4320 Lisp_Object display;
4322 struct x_display_info *dpyinfo = check_x_display_info (display);
4324 return make_number (MAXREQUEST (dpyinfo->display));
4327 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4328 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4329 The optional argument DISPLAY specifies which display to ask about.\n\
4330 DISPLAY should be either a frame or a display name (a string).\n\
4331 If omitted or nil, that stands for the selected frame's display.")
4332 (display)
4333 Lisp_Object display;
4335 struct x_display_info *dpyinfo = check_x_display_info (display);
4336 char *vendor = ServerVendor (dpyinfo->display);
4338 if (! vendor) vendor = "";
4339 return build_string (vendor);
4342 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4343 "Returns the version numbers of the X server of display DISPLAY.\n\
4344 The value is a list of three integers: the major and minor\n\
4345 version numbers of the X Protocol in use, and the vendor-specific release\n\
4346 number. See also the function `x-server-vendor'.\n\n\
4347 The optional argument DISPLAY specifies which display to ask about.\n\
4348 DISPLAY should be either a frame or a display name (a string).\n\
4349 If omitted or nil, that stands for the selected frame's display.")
4350 (display)
4351 Lisp_Object display;
4353 struct x_display_info *dpyinfo = check_x_display_info (display);
4354 Display *dpy = dpyinfo->display;
4356 return Fcons (make_number (ProtocolVersion (dpy)),
4357 Fcons (make_number (ProtocolRevision (dpy)),
4358 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4361 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4362 "Returns the number of screens on the X server of display DISPLAY.\n\
4363 The optional argument DISPLAY specifies which display to ask about.\n\
4364 DISPLAY should be either a frame or a display name (a string).\n\
4365 If omitted or nil, that stands for the selected frame's display.")
4366 (display)
4367 Lisp_Object display;
4369 struct x_display_info *dpyinfo = check_x_display_info (display);
4371 return make_number (ScreenCount (dpyinfo->display));
4374 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4375 "Returns the height in millimeters of the X display DISPLAY.\n\
4376 The optional argument DISPLAY specifies which display to ask about.\n\
4377 DISPLAY should be either a frame or a display name (a string).\n\
4378 If omitted or nil, that stands for the selected frame's display.")
4379 (display)
4380 Lisp_Object display;
4382 struct x_display_info *dpyinfo = check_x_display_info (display);
4384 return make_number (HeightMMOfScreen (dpyinfo->screen));
4387 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4388 "Returns the width in millimeters of the X display DISPLAY.\n\
4389 The optional argument DISPLAY specifies which display to ask about.\n\
4390 DISPLAY should be either a frame or a display name (a string).\n\
4391 If omitted or nil, that stands for the selected frame's display.")
4392 (display)
4393 Lisp_Object display;
4395 struct x_display_info *dpyinfo = check_x_display_info (display);
4397 return make_number (WidthMMOfScreen (dpyinfo->screen));
4400 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4401 Sx_display_backing_store, 0, 1, 0,
4402 "Returns an indication of whether X display DISPLAY does backing store.\n\
4403 The value may be `always', `when-mapped', or `not-useful'.\n\
4404 The optional argument DISPLAY specifies which display to ask about.\n\
4405 DISPLAY should be either a frame or a display name (a string).\n\
4406 If omitted or nil, that stands for the selected frame's display.")
4407 (display)
4408 Lisp_Object display;
4410 struct x_display_info *dpyinfo = check_x_display_info (display);
4412 switch (DoesBackingStore (dpyinfo->screen))
4414 case Always:
4415 return intern ("always");
4417 case WhenMapped:
4418 return intern ("when-mapped");
4420 case NotUseful:
4421 return intern ("not-useful");
4423 default:
4424 error ("Strange value for BackingStore parameter of screen");
4428 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4429 Sx_display_visual_class, 0, 1, 0,
4430 "Returns the visual class of the X display DISPLAY.\n\
4431 The value is one of the symbols `static-gray', `gray-scale',\n\
4432 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4433 The optional argument DISPLAY specifies which display to ask about.\n\
4434 DISPLAY should be either a frame or a display name (a string).\n\
4435 If omitted or nil, that stands for the selected frame's display.")
4436 (display)
4437 Lisp_Object display;
4439 struct x_display_info *dpyinfo = check_x_display_info (display);
4441 switch (dpyinfo->visual->class)
4443 case StaticGray: return (intern ("static-gray"));
4444 case GrayScale: return (intern ("gray-scale"));
4445 case StaticColor: return (intern ("static-color"));
4446 case PseudoColor: return (intern ("pseudo-color"));
4447 case TrueColor: return (intern ("true-color"));
4448 case DirectColor: return (intern ("direct-color"));
4449 default:
4450 error ("Display has an unknown visual class");
4454 DEFUN ("x-display-save-under", Fx_display_save_under,
4455 Sx_display_save_under, 0, 1, 0,
4456 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4457 The optional argument DISPLAY specifies which display to ask about.\n\
4458 DISPLAY should be either a frame or a display name (a string).\n\
4459 If omitted or nil, that stands for the selected frame's display.")
4460 (display)
4461 Lisp_Object display;
4463 struct x_display_info *dpyinfo = check_x_display_info (display);
4465 if (DoesSaveUnders (dpyinfo->screen) == True)
4466 return Qt;
4467 else
4468 return Qnil;
4472 x_pixel_width (f)
4473 register struct frame *f;
4475 return PIXEL_WIDTH (f);
4479 x_pixel_height (f)
4480 register struct frame *f;
4482 return PIXEL_HEIGHT (f);
4486 x_char_width (f)
4487 register struct frame *f;
4489 return FONT_WIDTH (f->output_data.x->font);
4493 x_char_height (f)
4494 register struct frame *f;
4496 return f->output_data.x->line_height;
4500 x_screen_planes (f)
4501 register struct frame *f;
4503 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4506 #if 0 /* These no longer seem like the right way to do things. */
4508 /* Draw a rectangle on the frame with left top corner including
4509 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
4510 CHARS by LINES wide and long and is the color of the cursor. */
4512 void
4513 x_rectangle (f, gc, left_char, top_char, chars, lines)
4514 register struct frame *f;
4515 GC gc;
4516 register int top_char, left_char, chars, lines;
4518 int width;
4519 int height;
4520 int left = (left_char * FONT_WIDTH (f->output_data.x->font)
4521 + f->output_data.x->internal_border_width);
4522 int top = (top_char * f->output_data.x->line_height
4523 + f->output_data.x->internal_border_width);
4525 if (chars < 0)
4526 width = FONT_WIDTH (f->output_data.x->font) / 2;
4527 else
4528 width = FONT_WIDTH (f->output_data.x->font) * chars;
4529 if (lines < 0)
4530 height = f->output_data.x->line_height / 2;
4531 else
4532 height = f->output_data.x->line_height * lines;
4534 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4535 gc, left, top, width, height);
4538 DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
4539 "Draw a rectangle on FRAME between coordinates specified by\n\
4540 numbers X0, Y0, X1, Y1 in the cursor pixel.")
4541 (frame, X0, Y0, X1, Y1)
4542 register Lisp_Object frame, X0, X1, Y0, Y1;
4544 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
4546 CHECK_LIVE_FRAME (frame, 0);
4547 CHECK_NUMBER (X0, 0);
4548 CHECK_NUMBER (Y0, 1);
4549 CHECK_NUMBER (X1, 2);
4550 CHECK_NUMBER (Y1, 3);
4552 x0 = XINT (X0);
4553 x1 = XINT (X1);
4554 y0 = XINT (Y0);
4555 y1 = XINT (Y1);
4557 if (y1 > y0)
4559 top = y0;
4560 n_lines = y1 - y0 + 1;
4562 else
4564 top = y1;
4565 n_lines = y0 - y1 + 1;
4568 if (x1 > x0)
4570 left = x0;
4571 n_chars = x1 - x0 + 1;
4573 else
4575 left = x1;
4576 n_chars = x0 - x1 + 1;
4579 BLOCK_INPUT;
4580 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
4581 left, top, n_chars, n_lines);
4582 UNBLOCK_INPUT;
4584 return Qt;
4587 DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
4588 "Draw a rectangle drawn on FRAME between coordinates\n\
4589 X0, Y0, X1, Y1 in the regular background-pixel.")
4590 (frame, X0, Y0, X1, Y1)
4591 register Lisp_Object frame, X0, Y0, X1, Y1;
4593 register int x0, y0, x1, y1, top, left, n_chars, n_lines;
4595 CHECK_LIVE_FRAME (frame, 0);
4596 CHECK_NUMBER (X0, 0);
4597 CHECK_NUMBER (Y0, 1);
4598 CHECK_NUMBER (X1, 2);
4599 CHECK_NUMBER (Y1, 3);
4601 x0 = XINT (X0);
4602 x1 = XINT (X1);
4603 y0 = XINT (Y0);
4604 y1 = XINT (Y1);
4606 if (y1 > y0)
4608 top = y0;
4609 n_lines = y1 - y0 + 1;
4611 else
4613 top = y1;
4614 n_lines = y0 - y1 + 1;
4617 if (x1 > x0)
4619 left = x0;
4620 n_chars = x1 - x0 + 1;
4622 else
4624 left = x1;
4625 n_chars = x0 - x1 + 1;
4628 BLOCK_INPUT;
4629 x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
4630 left, top, n_chars, n_lines);
4631 UNBLOCK_INPUT;
4633 return Qt;
4636 /* Draw lines around the text region beginning at the character position
4637 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4638 pixel and line characteristics. */
4640 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4642 static void
4643 outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
4644 register struct frame *f;
4645 GC gc;
4646 int top_x, top_y, bottom_x, bottom_y;
4648 register int ibw = f->output_data.x->internal_border_width;
4649 register int font_w = FONT_WIDTH (f->output_data.x->font);
4650 register int font_h = f->output_data.x->line_height;
4651 int y = top_y;
4652 int x = line_len (y);
4653 XPoint *pixel_points
4654 = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
4655 register XPoint *this_point = pixel_points;
4657 /* Do the horizontal top line/lines */
4658 if (top_x == 0)
4660 this_point->x = ibw;
4661 this_point->y = ibw + (font_h * top_y);
4662 this_point++;
4663 if (x == 0)
4664 this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
4665 else
4666 this_point->x = ibw + (font_w * x);
4667 this_point->y = (this_point - 1)->y;
4669 else
4671 this_point->x = ibw;
4672 this_point->y = ibw + (font_h * (top_y + 1));
4673 this_point++;
4674 this_point->x = ibw + (font_w * top_x);
4675 this_point->y = (this_point - 1)->y;
4676 this_point++;
4677 this_point->x = (this_point - 1)->x;
4678 this_point->y = ibw + (font_h * top_y);
4679 this_point++;
4680 this_point->x = ibw + (font_w * x);
4681 this_point->y = (this_point - 1)->y;
4684 /* Now do the right side. */
4685 while (y < bottom_y)
4686 { /* Right vertical edge */
4687 this_point++;
4688 this_point->x = (this_point - 1)->x;
4689 this_point->y = ibw + (font_h * (y + 1));
4690 this_point++;
4692 y++; /* Horizontal connection to next line */
4693 x = line_len (y);
4694 if (x == 0)
4695 this_point->x = ibw + (font_w / 2);
4696 else
4697 this_point->x = ibw + (font_w * x);
4699 this_point->y = (this_point - 1)->y;
4702 /* Now do the bottom and connect to the top left point. */
4703 this_point->x = ibw + (font_w * (bottom_x + 1));
4705 this_point++;
4706 this_point->x = (this_point - 1)->x;
4707 this_point->y = ibw + (font_h * (bottom_y + 1));
4708 this_point++;
4709 this_point->x = ibw;
4710 this_point->y = (this_point - 1)->y;
4711 this_point++;
4712 this_point->x = pixel_points->x;
4713 this_point->y = pixel_points->y;
4715 XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4716 gc, pixel_points,
4717 (this_point - pixel_points + 1), CoordModeOrigin);
4720 DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
4721 "Highlight the region between point and the character under the mouse\n\
4722 selected frame.")
4723 (event)
4724 register Lisp_Object event;
4726 register int x0, y0, x1, y1;
4727 register struct frame *f = selected_frame;
4728 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
4729 register int p1, p2;
4731 CHECK_CONS (event, 0);
4733 BLOCK_INPUT;
4734 x0 = XINT (Fcar (Fcar (event)));
4735 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4737 /* If the mouse is past the end of the line, don't that area. */
4738 /* ReWrite this... */
4740 /* Where the cursor is. */
4741 x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
4742 y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
4744 if (y1 > y0) /* point below mouse */
4745 outline_region (f, f->output_data.x->cursor_gc,
4746 x0, y0, x1, y1);
4747 else if (y1 < y0) /* point above mouse */
4748 outline_region (f, f->output_data.x->cursor_gc,
4749 x1, y1, x0, y0);
4750 else /* same line: draw horizontal rectangle */
4752 if (x1 > x0)
4753 x_rectangle (f, f->output_data.x->cursor_gc,
4754 x0, y0, (x1 - x0 + 1), 1);
4755 else if (x1 < x0)
4756 x_rectangle (f, f->output_data.x->cursor_gc,
4757 x1, y1, (x0 - x1 + 1), 1);
4760 XFlush (FRAME_X_DISPLAY (f));
4761 UNBLOCK_INPUT;
4763 return Qnil;
4766 DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
4767 "Erase any highlighting of the region between point and the character\n\
4768 at X, Y on the selected frame.")
4769 (event)
4770 register Lisp_Object event;
4772 register int x0, y0, x1, y1;
4773 register struct frame *f = selected_frame;
4774 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
4776 BLOCK_INPUT;
4777 x0 = XINT (Fcar (Fcar (event)));
4778 y0 = XINT (Fcar (Fcdr (Fcar (event))));
4779 x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
4780 y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
4782 if (y1 > y0) /* point below mouse */
4783 outline_region (f, f->output_data.x->reverse_gc,
4784 x0, y0, x1, y1);
4785 else if (y1 < y0) /* point above mouse */
4786 outline_region (f, f->output_data.x->reverse_gc,
4787 x1, y1, x0, y0);
4788 else /* same line: draw horizontal rectangle */
4790 if (x1 > x0)
4791 x_rectangle (f, f->output_data.x->reverse_gc,
4792 x0, y0, (x1 - x0 + 1), 1);
4793 else if (x1 < x0)
4794 x_rectangle (f, f->output_data.x->reverse_gc,
4795 x1, y1, (x0 - x1 + 1), 1);
4797 UNBLOCK_INPUT;
4799 return Qnil;
4802 #if 0
4803 int contour_begin_x, contour_begin_y;
4804 int contour_end_x, contour_end_y;
4805 int contour_npoints;
4807 /* Clip the top part of the contour lines down (and including) line Y_POS.
4808 If X_POS is in the middle (rather than at the end) of the line, drop
4809 down a line at that character. */
4811 static void
4812 clip_contour_top (y_pos, x_pos)
4814 register XPoint *begin = contour_lines[y_pos].top_left;
4815 register XPoint *end;
4816 register int npoints;
4817 register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
4819 if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
4821 end = contour_lines[y_pos].top_right;
4822 npoints = (end - begin + 1);
4823 XDrawLines (x_current_display, contour_window,
4824 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4826 bcopy (end, begin + 1, contour_last_point - end + 1);
4827 contour_last_point -= (npoints - 2);
4828 XDrawLines (x_current_display, contour_window,
4829 contour_erase_gc, begin, 2, CoordModeOrigin);
4830 XFlush (x_current_display);
4832 /* Now, update contour_lines structure. */
4834 /* ______. */
4835 else /* |________*/
4837 register XPoint *p = begin + 1;
4838 end = contour_lines[y_pos].bottom_right;
4839 npoints = (end - begin + 1);
4840 XDrawLines (x_current_display, contour_window,
4841 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
4843 p->y = begin->y;
4844 p->x = ibw + (font_w * (x_pos + 1));
4845 p++;
4846 p->y = begin->y + font_h;
4847 p->x = (p - 1)->x;
4848 bcopy (end, begin + 3, contour_last_point - end + 1);
4849 contour_last_point -= (npoints - 5);
4850 XDrawLines (x_current_display, contour_window,
4851 contour_erase_gc, begin, 4, CoordModeOrigin);
4852 XFlush (x_current_display);
4854 /* Now, update contour_lines structure. */
4858 /* Erase the top horizontal lines of the contour, and then extend
4859 the contour upwards. */
4861 static void
4862 extend_contour_top (line)
4866 static void
4867 clip_contour_bottom (x_pos, y_pos)
4868 int x_pos, y_pos;
4872 static void
4873 extend_contour_bottom (x_pos, y_pos)
4877 DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
4879 (event)
4880 Lisp_Object event;
4882 register struct frame *f = selected_frame;
4883 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
4884 register int point_x = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
4885 register int point_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
4886 register int mouse_below_point;
4887 register Lisp_Object obj;
4888 register int x_contour_x, x_contour_y;
4890 x_contour_x = x_mouse_x;
4891 x_contour_y = x_mouse_y;
4892 if (x_contour_y > point_y || (x_contour_y == point_y
4893 && x_contour_x > point_x))
4895 mouse_below_point = 1;
4896 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4897 x_contour_x, x_contour_y);
4899 else
4901 mouse_below_point = 0;
4902 outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
4903 point_x, point_y);
4906 while (1)
4908 obj = read_char (-1, 0, 0, Qnil, 0);
4909 if (!CONSP (obj))
4910 break;
4912 if (mouse_below_point)
4914 if (x_mouse_y <= point_y) /* Flipped. */
4916 mouse_below_point = 0;
4918 outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
4919 x_contour_x, x_contour_y);
4920 outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
4921 point_x, point_y);
4923 else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
4925 clip_contour_bottom (x_mouse_y);
4927 else if (x_mouse_y > x_contour_y) /* Bottom extended. */
4929 extend_bottom_contour (x_mouse_y);
4932 x_contour_x = x_mouse_x;
4933 x_contour_y = x_mouse_y;
4935 else /* mouse above or same line as point */
4937 if (x_mouse_y >= point_y) /* Flipped. */
4939 mouse_below_point = 1;
4941 outline_region (f, f->output_data.x->reverse_gc,
4942 x_contour_x, x_contour_y, point_x, point_y);
4943 outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
4944 x_mouse_x, x_mouse_y);
4946 else if (x_mouse_y > x_contour_y) /* Top clipped. */
4948 clip_contour_top (x_mouse_y);
4950 else if (x_mouse_y < x_contour_y) /* Top extended. */
4952 extend_contour_top (x_mouse_y);
4957 unread_command_event = obj;
4958 if (mouse_below_point)
4960 contour_begin_x = point_x;
4961 contour_begin_y = point_y;
4962 contour_end_x = x_contour_x;
4963 contour_end_y = x_contour_y;
4965 else
4967 contour_begin_x = x_contour_x;
4968 contour_begin_y = x_contour_y;
4969 contour_end_x = point_x;
4970 contour_end_y = point_y;
4973 #endif
4975 DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
4977 (event)
4978 Lisp_Object event;
4980 register Lisp_Object obj;
4981 struct frame *f = selected_frame;
4982 register struct window *w = XWINDOW (selected_window);
4983 register GC line_gc = f->output_data.x->cursor_gc;
4984 register GC erase_gc = f->output_data.x->reverse_gc;
4985 #if 0
4986 char dash_list[] = {6, 4, 6, 4};
4987 int dashes = 4;
4988 XGCValues gc_values;
4989 #endif
4990 register int previous_y;
4991 register int line = (x_mouse_y + 1) * f->output_data.x->line_height
4992 + f->output_data.x->internal_border_width;
4993 register int left = f->output_data.x->internal_border_width
4994 + (WINDOW_LEFT_MARGIN (w)
4995 * FONT_WIDTH (f->output_data.x->font));
4996 register int right = left + (w->width
4997 * FONT_WIDTH (f->output_data.x->font))
4998 - f->output_data.x->internal_border_width;
5000 #if 0
5001 BLOCK_INPUT;
5002 gc_values.foreground = f->output_data.x->cursor_pixel;
5003 gc_values.background = f->output_data.x->background_pixel;
5004 gc_values.line_width = 1;
5005 gc_values.line_style = LineOnOffDash;
5006 gc_values.cap_style = CapRound;
5007 gc_values.join_style = JoinRound;
5009 line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5010 GCLineStyle | GCJoinStyle | GCCapStyle
5011 | GCLineWidth | GCForeground | GCBackground,
5012 &gc_values);
5013 XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
5014 gc_values.foreground = f->output_data.x->background_pixel;
5015 gc_values.background = f->output_data.x->foreground_pixel;
5016 erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5017 GCLineStyle | GCJoinStyle | GCCapStyle
5018 | GCLineWidth | GCForeground | GCBackground,
5019 &gc_values);
5020 XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
5021 UNBLOCK_INPUT;
5022 #endif
5024 while (1)
5026 BLOCK_INPUT;
5027 if (x_mouse_y >= XINT (w->top)
5028 && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
5030 previous_y = x_mouse_y;
5031 line = (x_mouse_y + 1) * f->output_data.x->line_height
5032 + f->output_data.x->internal_border_width;
5033 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5034 line_gc, left, line, right, line);
5036 XFlush (FRAME_X_DISPLAY (f));
5037 UNBLOCK_INPUT;
5041 obj = read_char (-1, 0, 0, Qnil, 0);
5042 if (!CONSP (obj)
5043 || (! EQ (Fcar (Fcdr (Fcdr (obj))),
5044 Qvertical_scroll_bar))
5045 || x_mouse_grabbed)
5047 BLOCK_INPUT;
5048 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5049 erase_gc, left, line, right, line);
5050 unread_command_event = obj;
5051 #if 0
5052 XFreeGC (FRAME_X_DISPLAY (f), line_gc);
5053 XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
5054 #endif
5055 UNBLOCK_INPUT;
5056 return Qnil;
5059 while (x_mouse_y == previous_y);
5061 BLOCK_INPUT;
5062 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5063 erase_gc, left, line, right, line);
5064 UNBLOCK_INPUT;
5067 #endif
5069 #if 0
5070 /* These keep track of the rectangle following the pointer. */
5071 int mouse_track_top, mouse_track_left, mouse_track_width;
5073 /* Offset in buffer of character under the pointer, or 0. */
5074 int mouse_buffer_offset;
5076 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
5077 "Track the pointer.")
5080 static Cursor current_pointer_shape;
5081 FRAME_PTR f = x_mouse_frame;
5083 BLOCK_INPUT;
5084 if (EQ (Vmouse_frame_part, Qtext_part)
5085 && (current_pointer_shape != f->output_data.x->nontext_cursor))
5087 unsigned char c;
5088 struct buffer *buf;
5090 current_pointer_shape = f->output_data.x->nontext_cursor;
5091 XDefineCursor (FRAME_X_DISPLAY (f),
5092 FRAME_X_WINDOW (f),
5093 current_pointer_shape);
5095 buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
5096 c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
5098 else if (EQ (Vmouse_frame_part, Qmodeline_part)
5099 && (current_pointer_shape != f->output_data.x->modeline_cursor))
5101 current_pointer_shape = f->output_data.x->modeline_cursor;
5102 XDefineCursor (FRAME_X_DISPLAY (f),
5103 FRAME_X_WINDOW (f),
5104 current_pointer_shape);
5107 XFlush (FRAME_X_DISPLAY (f));
5108 UNBLOCK_INPUT;
5110 #endif
5112 #if 0
5113 DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
5114 "Draw rectangle around character under mouse pointer, if there is one.")
5115 (event)
5116 Lisp_Object event;
5118 struct window *w = XWINDOW (Vmouse_window);
5119 struct frame *f = XFRAME (WINDOW_FRAME (w));
5120 struct buffer *b = XBUFFER (w->buffer);
5121 Lisp_Object obj;
5123 if (! EQ (Vmouse_window, selected_window))
5124 return Qnil;
5126 if (EQ (event, Qnil))
5128 int x, y;
5130 x_read_mouse_position (selected_frame, &x, &y);
5133 BLOCK_INPUT;
5134 mouse_track_width = 0;
5135 mouse_track_left = mouse_track_top = -1;
5139 if ((x_mouse_x != mouse_track_left
5140 && (x_mouse_x < mouse_track_left
5141 || x_mouse_x > (mouse_track_left + mouse_track_width)))
5142 || x_mouse_y != mouse_track_top)
5144 int hp = 0; /* Horizontal position */
5145 int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
5146 int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
5147 int tab_width = XINT (b->tab_width);
5148 int ctl_arrow_p = !NILP (b->ctl_arrow);
5149 unsigned char c;
5150 int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
5151 int in_mode_line = 0;
5153 if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
5154 break;
5156 /* Erase previous rectangle. */
5157 if (mouse_track_width)
5159 x_rectangle (f, f->output_data.x->reverse_gc,
5160 mouse_track_left, mouse_track_top,
5161 mouse_track_width, 1);
5163 if ((mouse_track_left == f->phys_cursor_x
5164 || mouse_track_left == f->phys_cursor_x - 1)
5165 && mouse_track_top == f->phys_cursor_y)
5167 x_display_cursor (f, 1);
5171 mouse_track_left = x_mouse_x;
5172 mouse_track_top = x_mouse_y;
5173 mouse_track_width = 0;
5175 if (mouse_track_left > len) /* Past the end of line. */
5176 goto draw_or_not;
5178 if (mouse_track_top == mode_line_vpos)
5180 in_mode_line = 1;
5181 goto draw_or_not;
5184 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
5187 c = FETCH_BYTE (p);
5188 if (len == f->width && hp == len - 1 && c != '\n')
5189 goto draw_or_not;
5191 switch (c)
5193 case '\t':
5194 mouse_track_width = tab_width - (hp % tab_width);
5195 p++;
5196 hp += mouse_track_width;
5197 if (hp > x_mouse_x)
5199 mouse_track_left = hp - mouse_track_width;
5200 goto draw_or_not;
5202 continue;
5204 case '\n':
5205 mouse_track_width = -1;
5206 goto draw_or_not;
5208 default:
5209 if (ctl_arrow_p && (c < 040 || c == 0177))
5211 if (p > ZV)
5212 goto draw_or_not;
5214 mouse_track_width = 2;
5215 p++;
5216 hp +=2;
5217 if (hp > x_mouse_x)
5219 mouse_track_left = hp - mouse_track_width;
5220 goto draw_or_not;
5223 else
5225 mouse_track_width = 1;
5226 p++;
5227 hp++;
5229 continue;
5232 while (hp <= x_mouse_x);
5234 draw_or_not:
5235 if (mouse_track_width) /* Over text; use text pointer shape. */
5237 XDefineCursor (FRAME_X_DISPLAY (f),
5238 FRAME_X_WINDOW (f),
5239 f->output_data.x->text_cursor);
5240 x_rectangle (f, f->output_data.x->cursor_gc,
5241 mouse_track_left, mouse_track_top,
5242 mouse_track_width, 1);
5244 else if (in_mode_line)
5245 XDefineCursor (FRAME_X_DISPLAY (f),
5246 FRAME_X_WINDOW (f),
5247 f->output_data.x->modeline_cursor);
5248 else
5249 XDefineCursor (FRAME_X_DISPLAY (f),
5250 FRAME_X_WINDOW (f),
5251 f->output_data.x->nontext_cursor);
5254 XFlush (FRAME_X_DISPLAY (f));
5255 UNBLOCK_INPUT;
5257 obj = read_char (-1, 0, 0, Qnil, 0);
5258 BLOCK_INPUT;
5260 while (CONSP (obj) /* Mouse event */
5261 && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
5262 && EQ (Vmouse_depressed, Qnil) /* Only motion events */
5263 && EQ (Vmouse_window, selected_window) /* In this window */
5264 && x_mouse_frame);
5266 unread_command_event = obj;
5268 if (mouse_track_width)
5270 x_rectangle (f, f->output_data.x->reverse_gc,
5271 mouse_track_left, mouse_track_top,
5272 mouse_track_width, 1);
5273 mouse_track_width = 0;
5274 if ((mouse_track_left == f->phys_cursor_x
5275 || mouse_track_left - 1 == f->phys_cursor_x)
5276 && mouse_track_top == f->phys_cursor_y)
5278 x_display_cursor (f, 1);
5281 XDefineCursor (FRAME_X_DISPLAY (f),
5282 FRAME_X_WINDOW (f),
5283 f->output_data.x->nontext_cursor);
5284 XFlush (FRAME_X_DISPLAY (f));
5285 UNBLOCK_INPUT;
5287 return Qnil;
5289 #endif
5291 #if 0
5292 #include "glyphs.h"
5294 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
5295 on the frame F at position X, Y. */
5297 x_draw_pixmap (f, x, y, image_data, width, height)
5298 struct frame *f;
5299 int x, y, width, height;
5300 char *image_data;
5302 Pixmap image;
5304 image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
5305 FRAME_X_WINDOW (f), image_data,
5306 width, height);
5307 XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
5308 f->output_data.x->normal_gc, 0, 0, width, height, x, y);
5310 #endif
5312 #if 0 /* I'm told these functions are superfluous
5313 given the ability to bind function keys. */
5315 #ifdef HAVE_X11
5316 DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
5317 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
5318 KEYSYM is a string which conforms to the X keysym definitions found\n\
5319 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
5320 list of strings specifying modifier keys such as Control_L, which must\n\
5321 also be depressed for NEWSTRING to appear.")
5322 (x_keysym, modifiers, newstring)
5323 register Lisp_Object x_keysym;
5324 register Lisp_Object modifiers;
5325 register Lisp_Object newstring;
5327 char *rawstring;
5328 register KeySym keysym;
5329 KeySym modifier_list[16];
5331 check_x ();
5332 CHECK_STRING (x_keysym, 1);
5333 CHECK_STRING (newstring, 3);
5335 keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
5336 if (keysym == NoSymbol)
5337 error ("Keysym does not exist");
5339 if (NILP (modifiers))
5340 XRebindKeysym (x_current_display, keysym, modifier_list, 0,
5341 XSTRING (newstring)->data,
5342 STRING_BYTES (XSTRING (newstring)));
5343 else
5345 register Lisp_Object rest, mod;
5346 register int i = 0;
5348 for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
5350 if (i == 16)
5351 error ("Can't have more than 16 modifiers");
5353 mod = Fcar (rest);
5354 CHECK_STRING (mod, 3);
5355 modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
5356 #ifndef HAVE_X11R5
5357 if (modifier_list[i] == NoSymbol
5358 || !(IsModifierKey (modifier_list[i])
5359 || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
5360 || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
5361 #else
5362 if (modifier_list[i] == NoSymbol
5363 || !IsModifierKey (modifier_list[i]))
5364 #endif
5365 error ("Element is not a modifier keysym");
5366 i++;
5369 XRebindKeysym (x_current_display, keysym, modifier_list, i,
5370 XSTRING (newstring)->data,
5371 STRING_BYTES (XSTRING (newstring)));
5374 return Qnil;
5377 DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
5378 "Rebind KEYCODE to list of strings STRINGS.\n\
5379 STRINGS should be a list of 16 elements, one for each shift combination.\n\
5380 nil as element means don't change.\n\
5381 See the documentation of `x-rebind-key' for more information.")
5382 (keycode, strings)
5383 register Lisp_Object keycode;
5384 register Lisp_Object strings;
5386 register Lisp_Object item;
5387 register unsigned char *rawstring;
5388 KeySym rawkey, modifier[1];
5389 int strsize;
5390 register unsigned i;
5392 check_x ();
5393 CHECK_NUMBER (keycode, 1);
5394 CHECK_CONS (strings, 2);
5395 rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
5396 for (i = 0; i <= 15; strings = Fcdr (strings), i++)
5398 item = Fcar (strings);
5399 if (!NILP (item))
5401 CHECK_STRING (item, 2);
5402 strsize = STRING_BYTES (XSTRING (item));
5403 rawstring = (unsigned char *) xmalloc (strsize);
5404 bcopy (XSTRING (item)->data, rawstring, strsize);
5405 modifier[1] = 1 << i;
5406 XRebindKeysym (x_current_display, rawkey, modifier, 1,
5407 rawstring, strsize);
5410 return Qnil;
5412 #endif /* HAVE_X11 */
5413 #endif /* 0 */
5415 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5417 XScreenNumberOfScreen (scr)
5418 register Screen *scr;
5420 register Display *dpy;
5421 register Screen *dpyscr;
5422 register int i;
5424 dpy = scr->display;
5425 dpyscr = dpy->screens;
5427 for (i = 0; i < dpy->nscreens; i++, dpyscr++)
5428 if (scr == dpyscr)
5429 return i;
5431 return -1;
5433 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5435 Visual *
5436 select_visual (dpy, screen, depth)
5437 Display *dpy;
5438 Screen *screen;
5439 unsigned int *depth;
5441 Visual *v;
5442 XVisualInfo *vinfo, vinfo_template;
5443 int n_visuals;
5445 v = DefaultVisualOfScreen (screen);
5447 #ifdef HAVE_X11R4
5448 vinfo_template.visualid = XVisualIDFromVisual (v);
5449 #else
5450 vinfo_template.visualid = v->visualid;
5451 #endif
5453 vinfo_template.screen = XScreenNumberOfScreen (screen);
5455 vinfo = XGetVisualInfo (dpy,
5456 VisualIDMask | VisualScreenMask, &vinfo_template,
5457 &n_visuals);
5458 if (n_visuals != 1)
5459 fatal ("Can't get proper X visual info");
5461 if ((1 << vinfo->depth) == vinfo->colormap_size)
5462 *depth = vinfo->depth;
5463 else
5465 int i = 0;
5466 int n = vinfo->colormap_size - 1;
5467 while (n)
5469 n = n >> 1;
5470 i++;
5472 *depth = i;
5475 XFree ((char *) vinfo);
5476 return v;
5479 /* Return the X display structure for the display named NAME.
5480 Open a new connection if necessary. */
5482 struct x_display_info *
5483 x_display_info_for_name (name)
5484 Lisp_Object name;
5486 Lisp_Object names;
5487 struct x_display_info *dpyinfo;
5489 CHECK_STRING (name, 0);
5491 if (! EQ (Vwindow_system, intern ("x")))
5492 error ("Not using X Windows");
5494 for (dpyinfo = x_display_list, names = x_display_name_list;
5495 dpyinfo;
5496 dpyinfo = dpyinfo->next, names = XCDR (names))
5498 Lisp_Object tem;
5499 tem = Fstring_equal (XCAR (XCAR (names)), name);
5500 if (!NILP (tem))
5501 return dpyinfo;
5504 /* Use this general default value to start with. */
5505 Vx_resource_name = Vinvocation_name;
5507 validate_x_resource_name ();
5509 dpyinfo = x_term_init (name, (unsigned char *)0,
5510 (char *) XSTRING (Vx_resource_name)->data);
5512 if (dpyinfo == 0)
5513 error ("Cannot connect to X server %s", XSTRING (name)->data);
5515 x_in_use = 1;
5516 XSETFASTINT (Vwindow_system_version, 11);
5518 return dpyinfo;
5521 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5522 1, 3, 0, "Open a connection to an X server.\n\
5523 DISPLAY is the name of the display to connect to.\n\
5524 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5525 If the optional third arg MUST-SUCCEED is non-nil,\n\
5526 terminate Emacs if we can't open the connection.")
5527 (display, xrm_string, must_succeed)
5528 Lisp_Object display, xrm_string, must_succeed;
5530 unsigned char *xrm_option;
5531 struct x_display_info *dpyinfo;
5533 CHECK_STRING (display, 0);
5534 if (! NILP (xrm_string))
5535 CHECK_STRING (xrm_string, 1);
5537 if (! EQ (Vwindow_system, intern ("x")))
5538 error ("Not using X Windows");
5540 if (! NILP (xrm_string))
5541 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5542 else
5543 xrm_option = (unsigned char *) 0;
5545 validate_x_resource_name ();
5547 /* This is what opens the connection and sets x_current_display.
5548 This also initializes many symbols, such as those used for input. */
5549 dpyinfo = x_term_init (display, xrm_option,
5550 (char *) XSTRING (Vx_resource_name)->data);
5552 if (dpyinfo == 0)
5554 if (!NILP (must_succeed))
5555 fatal ("Cannot connect to X server %s.\n\
5556 Check the DISPLAY environment variable or use `-d'.\n\
5557 Also use the `xhost' program to verify that it is set to permit\n\
5558 connections from your machine.\n",
5559 XSTRING (display)->data);
5560 else
5561 error ("Cannot connect to X server %s", XSTRING (display)->data);
5564 x_in_use = 1;
5566 XSETFASTINT (Vwindow_system_version, 11);
5567 return Qnil;
5570 DEFUN ("x-close-connection", Fx_close_connection,
5571 Sx_close_connection, 1, 1, 0,
5572 "Close the connection to DISPLAY's X server.\n\
5573 For DISPLAY, specify either a frame or a display name (a string).\n\
5574 If DISPLAY is nil, that stands for the selected frame's display.")
5575 (display)
5576 Lisp_Object display;
5578 struct x_display_info *dpyinfo = check_x_display_info (display);
5579 int i;
5581 if (dpyinfo->reference_count > 0)
5582 error ("Display still has frames on it");
5584 BLOCK_INPUT;
5585 /* Free the fonts in the font table. */
5586 for (i = 0; i < dpyinfo->n_fonts; i++)
5587 if (dpyinfo->font_table[i].name)
5589 xfree (dpyinfo->font_table[i].name);
5590 /* Don't free the full_name string;
5591 it is always shared with something else. */
5592 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5595 x_destroy_all_bitmaps (dpyinfo);
5596 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5598 #ifdef USE_X_TOOLKIT
5599 XtCloseDisplay (dpyinfo->display);
5600 #else
5601 XCloseDisplay (dpyinfo->display);
5602 #endif
5604 x_delete_display (dpyinfo);
5605 UNBLOCK_INPUT;
5607 return Qnil;
5610 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5611 "Return the list of display names that Emacs has connections to.")
5614 Lisp_Object tail, result;
5616 result = Qnil;
5617 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5618 result = Fcons (XCAR (XCAR (tail)), result);
5620 return result;
5623 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5624 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5625 If ON is nil, allow buffering of requests.\n\
5626 Turning on synchronization prohibits the Xlib routines from buffering\n\
5627 requests and seriously degrades performance, but makes debugging much\n\
5628 easier.\n\
5629 The optional second argument DISPLAY specifies which display to act on.\n\
5630 DISPLAY should be either a frame or a display name (a string).\n\
5631 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5632 (on, display)
5633 Lisp_Object display, on;
5635 struct x_display_info *dpyinfo = check_x_display_info (display);
5637 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5639 return Qnil;
5642 /* Wait for responses to all X commands issued so far for frame F. */
5644 void
5645 x_sync (f)
5646 FRAME_PTR f;
5648 BLOCK_INPUT;
5649 XSync (FRAME_X_DISPLAY (f), False);
5650 UNBLOCK_INPUT;
5654 /***********************************************************************
5655 Image types
5656 ***********************************************************************/
5658 /* Value is the number of elements of vector VECTOR. */
5660 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5662 /* List of supported image types. Use define_image_type to add new
5663 types. Use lookup_image_type to find a type for a given symbol. */
5665 static struct image_type *image_types;
5667 /* A list of symbols, one for each supported image type. */
5669 Lisp_Object Vimage_types;
5671 /* The symbol `image' which is the car of the lists used to represent
5672 images in Lisp. */
5674 extern Lisp_Object Qimage;
5676 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5678 Lisp_Object Qxbm;
5680 /* Keywords. */
5682 Lisp_Object QCtype, QCdata, QCascent, QCmargin, QCrelief;
5683 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5684 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
5685 Lisp_Object QCindex;
5687 /* Other symbols. */
5689 Lisp_Object Qlaplace;
5691 /* Time in seconds after which images should be removed from the cache
5692 if not displayed. */
5694 Lisp_Object Vimage_cache_eviction_delay;
5696 /* Function prototypes. */
5698 static void define_image_type P_ ((struct image_type *type));
5699 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5700 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5701 static void x_laplace P_ ((struct frame *, struct image *));
5702 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5703 Lisp_Object));
5706 /* Define a new image type from TYPE. This adds a copy of TYPE to
5707 image_types and adds the symbol *TYPE->type to Vimage_types. */
5709 static void
5710 define_image_type (type)
5711 struct image_type *type;
5713 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5714 The initialized data segment is read-only. */
5715 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5716 bcopy (type, p, sizeof *p);
5717 p->next = image_types;
5718 image_types = p;
5719 Vimage_types = Fcons (*p->type, Vimage_types);
5723 /* Look up image type SYMBOL, and return a pointer to its image_type
5724 structure. Value is null if SYMBOL is not a known image type. */
5726 static INLINE struct image_type *
5727 lookup_image_type (symbol)
5728 Lisp_Object symbol;
5730 struct image_type *type;
5732 for (type = image_types; type; type = type->next)
5733 if (EQ (symbol, *type->type))
5734 break;
5736 return type;
5740 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5741 valid image specification is a list whose car is the symbol
5742 `image', and whose rest is a property list. The property list must
5743 contain a value for key `:type'. That value must be the name of a
5744 supported image type. The rest of the property list depends on the
5745 image type. */
5748 valid_image_p (object)
5749 Lisp_Object object;
5751 int valid_p = 0;
5753 if (CONSP (object) && EQ (XCAR (object), Qimage))
5755 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
5756 struct image_type *type = lookup_image_type (symbol);
5758 if (type)
5759 valid_p = type->valid_p (object);
5762 return valid_p;
5766 /* Log error message with format string FORMAT and argument ARG.
5767 Signaling an error, e.g. when an image cannot be loaded, is not a
5768 good idea because this would interrupt redisplay, and the error
5769 message display would lead to another redisplay. This function
5770 therefore simply displays a message. */
5772 static void
5773 image_error (format, arg1, arg2)
5774 char *format;
5775 Lisp_Object arg1, arg2;
5777 add_to_log (format, arg1, arg2);
5782 /***********************************************************************
5783 Image specifications
5784 ***********************************************************************/
5786 enum image_value_type
5788 IMAGE_DONT_CHECK_VALUE_TYPE,
5789 IMAGE_STRING_VALUE,
5790 IMAGE_SYMBOL_VALUE,
5791 IMAGE_POSITIVE_INTEGER_VALUE,
5792 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5793 IMAGE_INTEGER_VALUE,
5794 IMAGE_FUNCTION_VALUE,
5795 IMAGE_NUMBER_VALUE,
5796 IMAGE_BOOL_VALUE
5799 /* Structure used when parsing image specifications. */
5801 struct image_keyword
5803 /* Name of keyword. */
5804 char *name;
5806 /* The type of value allowed. */
5807 enum image_value_type type;
5809 /* Non-zero means key must be present. */
5810 int mandatory_p;
5812 /* Used to recognize duplicate keywords in a property list. */
5813 int count;
5815 /* The value that was found. */
5816 Lisp_Object value;
5820 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5821 int, Lisp_Object));
5822 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5825 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5826 has the format (image KEYWORD VALUE ...). One of the keyword/
5827 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5828 image_keywords structures of size NKEYWORDS describing other
5829 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5831 static int
5832 parse_image_spec (spec, keywords, nkeywords, type)
5833 Lisp_Object spec;
5834 struct image_keyword *keywords;
5835 int nkeywords;
5836 Lisp_Object type;
5838 int i;
5839 Lisp_Object plist;
5841 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5842 return 0;
5844 plist = XCDR (spec);
5845 while (CONSP (plist))
5847 Lisp_Object key, value;
5849 /* First element of a pair must be a symbol. */
5850 key = XCAR (plist);
5851 plist = XCDR (plist);
5852 if (!SYMBOLP (key))
5853 return 0;
5855 /* There must follow a value. */
5856 if (!CONSP (plist))
5857 return 0;
5858 value = XCAR (plist);
5859 plist = XCDR (plist);
5861 /* Find key in KEYWORDS. Error if not found. */
5862 for (i = 0; i < nkeywords; ++i)
5863 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5864 break;
5866 if (i == nkeywords)
5867 continue;
5869 /* Record that we recognized the keyword. If a keywords
5870 was found more than once, it's an error. */
5871 keywords[i].value = value;
5872 ++keywords[i].count;
5874 if (keywords[i].count > 1)
5875 return 0;
5877 /* Check type of value against allowed type. */
5878 switch (keywords[i].type)
5880 case IMAGE_STRING_VALUE:
5881 if (!STRINGP (value))
5882 return 0;
5883 break;
5885 case IMAGE_SYMBOL_VALUE:
5886 if (!SYMBOLP (value))
5887 return 0;
5888 break;
5890 case IMAGE_POSITIVE_INTEGER_VALUE:
5891 if (!INTEGERP (value) || XINT (value) <= 0)
5892 return 0;
5893 break;
5895 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5896 if (!INTEGERP (value) || XINT (value) < 0)
5897 return 0;
5898 break;
5900 case IMAGE_DONT_CHECK_VALUE_TYPE:
5901 break;
5903 case IMAGE_FUNCTION_VALUE:
5904 value = indirect_function (value);
5905 if (SUBRP (value)
5906 || COMPILEDP (value)
5907 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5908 break;
5909 return 0;
5911 case IMAGE_NUMBER_VALUE:
5912 if (!INTEGERP (value) && !FLOATP (value))
5913 return 0;
5914 break;
5916 case IMAGE_INTEGER_VALUE:
5917 if (!INTEGERP (value))
5918 return 0;
5919 break;
5921 case IMAGE_BOOL_VALUE:
5922 if (!NILP (value) && !EQ (value, Qt))
5923 return 0;
5924 break;
5926 default:
5927 abort ();
5928 break;
5931 if (EQ (key, QCtype) && !EQ (type, value))
5932 return 0;
5935 /* Check that all mandatory fields are present. */
5936 for (i = 0; i < nkeywords; ++i)
5937 if (keywords[i].mandatory_p && keywords[i].count == 0)
5938 return 0;
5940 return NILP (plist);
5944 /* Return the value of KEY in image specification SPEC. Value is nil
5945 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5946 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5948 static Lisp_Object
5949 image_spec_value (spec, key, found)
5950 Lisp_Object spec, key;
5951 int *found;
5953 Lisp_Object tail;
5955 xassert (valid_image_p (spec));
5957 for (tail = XCDR (spec);
5958 CONSP (tail) && CONSP (XCDR (tail));
5959 tail = XCDR (XCDR (tail)))
5961 if (EQ (XCAR (tail), key))
5963 if (found)
5964 *found = 1;
5965 return XCAR (XCDR (tail));
5969 if (found)
5970 *found = 0;
5971 return Qnil;
5977 /***********************************************************************
5978 Image type independent image structures
5979 ***********************************************************************/
5981 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5982 static void free_image P_ ((struct frame *f, struct image *img));
5985 /* Allocate and return a new image structure for image specification
5986 SPEC. SPEC has a hash value of HASH. */
5988 static struct image *
5989 make_image (spec, hash)
5990 Lisp_Object spec;
5991 unsigned hash;
5993 struct image *img = (struct image *) xmalloc (sizeof *img);
5995 xassert (valid_image_p (spec));
5996 bzero (img, sizeof *img);
5997 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5998 xassert (img->type != NULL);
5999 img->spec = spec;
6000 img->data.lisp_val = Qnil;
6001 img->ascent = DEFAULT_IMAGE_ASCENT;
6002 img->hash = hash;
6003 return img;
6007 /* Free image IMG which was used on frame F, including its resources. */
6009 static void
6010 free_image (f, img)
6011 struct frame *f;
6012 struct image *img;
6014 if (img)
6016 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6018 /* Remove IMG from the hash table of its cache. */
6019 if (img->prev)
6020 img->prev->next = img->next;
6021 else
6022 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
6024 if (img->next)
6025 img->next->prev = img->prev;
6027 c->images[img->id] = NULL;
6029 /* Free resources, then free IMG. */
6030 img->type->free (f, img);
6031 xfree (img);
6036 /* Prepare image IMG for display on frame F. Must be called before
6037 drawing an image. */
6039 void
6040 prepare_image_for_display (f, img)
6041 struct frame *f;
6042 struct image *img;
6044 EMACS_TIME t;
6046 /* We're about to display IMG, so set its timestamp to `now'. */
6047 EMACS_GET_TIME (t);
6048 img->timestamp = EMACS_SECS (t);
6050 /* If IMG doesn't have a pixmap yet, load it now, using the image
6051 type dependent loader function. */
6052 if (img->pixmap == 0 && !img->load_failed_p)
6053 img->load_failed_p = img->type->load (f, img) == 0;
6058 /***********************************************************************
6059 Helper functions for X image types
6060 ***********************************************************************/
6062 static void x_clear_image P_ ((struct frame *f, struct image *img));
6063 static unsigned long x_alloc_image_color P_ ((struct frame *f,
6064 struct image *img,
6065 Lisp_Object color_name,
6066 unsigned long dflt));
6068 /* Free X resources of image IMG which is used on frame F. */
6070 static void
6071 x_clear_image (f, img)
6072 struct frame *f;
6073 struct image *img;
6075 if (img->pixmap)
6077 BLOCK_INPUT;
6078 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
6079 img->pixmap = 0;
6080 UNBLOCK_INPUT;
6083 if (img->ncolors)
6085 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
6087 /* If display has an immutable color map, freeing colors is not
6088 necessary and some servers don't allow it. So don't do it. */
6089 if (class != StaticColor
6090 && class != StaticGray
6091 && class != TrueColor)
6093 Colormap cmap;
6094 BLOCK_INPUT;
6095 cmap = DefaultColormapOfScreen (FRAME_X_DISPLAY_INFO (f)->screen);
6096 XFreeColors (FRAME_X_DISPLAY (f), cmap, img->colors,
6097 img->ncolors, 0);
6098 UNBLOCK_INPUT;
6101 xfree (img->colors);
6102 img->colors = NULL;
6103 img->ncolors = 0;
6108 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6109 cannot be allocated, use DFLT. Add a newly allocated color to
6110 IMG->colors, so that it can be freed again. Value is the pixel
6111 color. */
6113 static unsigned long
6114 x_alloc_image_color (f, img, color_name, dflt)
6115 struct frame *f;
6116 struct image *img;
6117 Lisp_Object color_name;
6118 unsigned long dflt;
6120 XColor color;
6121 unsigned long result;
6123 xassert (STRINGP (color_name));
6125 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
6127 /* This isn't called frequently so we get away with simply
6128 reallocating the color vector to the needed size, here. */
6129 ++img->ncolors;
6130 img->colors =
6131 (unsigned long *) xrealloc (img->colors,
6132 img->ncolors * sizeof *img->colors);
6133 img->colors[img->ncolors - 1] = color.pixel;
6134 result = color.pixel;
6136 else
6137 result = dflt;
6139 return result;
6144 /***********************************************************************
6145 Image Cache
6146 ***********************************************************************/
6148 static void cache_image P_ ((struct frame *f, struct image *img));
6151 /* Return a new, initialized image cache that is allocated from the
6152 heap. Call free_image_cache to free an image cache. */
6154 struct image_cache *
6155 make_image_cache ()
6157 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
6158 int size;
6160 bzero (c, sizeof *c);
6161 c->size = 50;
6162 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
6163 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
6164 c->buckets = (struct image **) xmalloc (size);
6165 bzero (c->buckets, size);
6166 return c;
6170 /* Free image cache of frame F. Be aware that X frames share images
6171 caches. */
6173 void
6174 free_image_cache (f)
6175 struct frame *f;
6177 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6178 if (c)
6180 int i;
6182 /* Cache should not be referenced by any frame when freed. */
6183 xassert (c->refcount == 0);
6185 for (i = 0; i < c->used; ++i)
6186 free_image (f, c->images[i]);
6187 xfree (c->images);
6188 xfree (c);
6189 xfree (c->buckets);
6190 FRAME_X_IMAGE_CACHE (f) = NULL;
6195 /* Clear image cache of frame F. FORCE_P non-zero means free all
6196 images. FORCE_P zero means clear only images that haven't been
6197 displayed for some time. Should be called from time to time to
6198 reduce the number of loaded images. If image-eviction-seconds is
6199 non-nil, this frees images in the cache which weren't displayed for
6200 at least that many seconds. */
6202 void
6203 clear_image_cache (f, force_p)
6204 struct frame *f;
6205 int force_p;
6207 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6209 if (c && INTEGERP (Vimage_cache_eviction_delay))
6211 EMACS_TIME t;
6212 unsigned long old;
6213 int i, any_freed_p = 0;
6215 EMACS_GET_TIME (t);
6216 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
6218 for (i = 0; i < c->used; ++i)
6220 struct image *img = c->images[i];
6221 if (img != NULL
6222 && (force_p
6223 || (img->timestamp > old)))
6225 free_image (f, img);
6226 any_freed_p = 1;
6230 /* We may be clearing the image cache because, for example,
6231 Emacs was iconified for a longer period of time. In that
6232 case, current matrices may still contain references to
6233 images freed above. So, clear these matrices. */
6234 if (any_freed_p)
6236 clear_current_matrices (f);
6237 ++windows_or_buffers_changed;
6243 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
6244 0, 1, 0,
6245 "Clear the image cache of FRAME.\n\
6246 FRAME nil or omitted means use the selected frame.\n\
6247 FRAME t means clear the image caches of all frames.")
6248 (frame)
6249 Lisp_Object frame;
6251 if (EQ (frame, Qt))
6253 Lisp_Object tail;
6255 FOR_EACH_FRAME (tail, frame)
6256 if (FRAME_X_P (XFRAME (frame)))
6257 clear_image_cache (XFRAME (frame), 1);
6259 else
6260 clear_image_cache (check_x_frame (frame), 1);
6262 return Qnil;
6266 /* Return the id of image with Lisp specification SPEC on frame F.
6267 SPEC must be a valid Lisp image specification (see valid_image_p). */
6270 lookup_image (f, spec)
6271 struct frame *f;
6272 Lisp_Object spec;
6274 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6275 struct image *img;
6276 int i;
6277 unsigned hash;
6278 struct gcpro gcpro1;
6279 EMACS_TIME now;
6281 /* F must be a window-system frame, and SPEC must be a valid image
6282 specification. */
6283 xassert (FRAME_WINDOW_P (f));
6284 xassert (valid_image_p (spec));
6286 GCPRO1 (spec);
6288 /* Look up SPEC in the hash table of the image cache. */
6289 hash = sxhash (spec, 0);
6290 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6292 for (img = c->buckets[i]; img; img = img->next)
6293 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6294 break;
6296 /* If not found, create a new image and cache it. */
6297 if (img == NULL)
6299 img = make_image (spec, hash);
6300 cache_image (f, img);
6301 img->load_failed_p = img->type->load (f, img) == 0;
6302 xassert (!interrupt_input_blocked);
6304 /* If we can't load the image, and we don't have a width and
6305 height, use some arbitrary width and height so that we can
6306 draw a rectangle for it. */
6307 if (img->load_failed_p)
6309 Lisp_Object value;
6311 value = image_spec_value (spec, QCwidth, NULL);
6312 img->width = (INTEGERP (value)
6313 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6314 value = image_spec_value (spec, QCheight, NULL);
6315 img->height = (INTEGERP (value)
6316 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6318 else
6320 /* Handle image type independent image attributes
6321 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
6322 Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
6323 Lisp_Object file;
6325 ascent = image_spec_value (spec, QCascent, NULL);
6326 if (INTEGERP (ascent))
6327 img->ascent = XFASTINT (ascent);
6329 margin = image_spec_value (spec, QCmargin, NULL);
6330 if (INTEGERP (margin) && XINT (margin) >= 0)
6331 img->margin = XFASTINT (margin);
6333 relief = image_spec_value (spec, QCrelief, NULL);
6334 if (INTEGERP (relief))
6336 img->relief = XINT (relief);
6337 img->margin += abs (img->relief);
6340 /* Should we apply a Laplace edge-detection algorithm? */
6341 algorithm = image_spec_value (spec, QCalgorithm, NULL);
6342 if (img->pixmap && EQ (algorithm, Qlaplace))
6343 x_laplace (f, img);
6345 /* Should we built a mask heuristically? */
6346 heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
6347 if (img->pixmap && !img->mask && !NILP (heuristic_mask))
6348 x_build_heuristic_mask (f, img, heuristic_mask);
6352 /* We're using IMG, so set its timestamp to `now'. */
6353 EMACS_GET_TIME (now);
6354 img->timestamp = EMACS_SECS (now);
6356 UNGCPRO;
6358 /* Value is the image id. */
6359 return img->id;
6363 /* Cache image IMG in the image cache of frame F. */
6365 static void
6366 cache_image (f, img)
6367 struct frame *f;
6368 struct image *img;
6370 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6371 int i;
6373 /* Find a free slot in c->images. */
6374 for (i = 0; i < c->used; ++i)
6375 if (c->images[i] == NULL)
6376 break;
6378 /* If no free slot found, maybe enlarge c->images. */
6379 if (i == c->used && c->used == c->size)
6381 c->size *= 2;
6382 c->images = (struct image **) xrealloc (c->images,
6383 c->size * sizeof *c->images);
6386 /* Add IMG to c->images, and assign IMG an id. */
6387 c->images[i] = img;
6388 img->id = i;
6389 if (i == c->used)
6390 ++c->used;
6392 /* Add IMG to the cache's hash table. */
6393 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6394 img->next = c->buckets[i];
6395 if (img->next)
6396 img->next->prev = img;
6397 img->prev = NULL;
6398 c->buckets[i] = img;
6402 /* Call FN on every image in the image cache of frame F. Used to mark
6403 Lisp Objects in the image cache. */
6405 void
6406 forall_images_in_image_cache (f, fn)
6407 struct frame *f;
6408 void (*fn) P_ ((struct image *img));
6410 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6412 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6413 if (c)
6415 int i;
6416 for (i = 0; i < c->used; ++i)
6417 if (c->images[i])
6418 fn (c->images[i]);
6425 /***********************************************************************
6426 X support code
6427 ***********************************************************************/
6429 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6430 XImage **, Pixmap *));
6431 static void x_destroy_x_image P_ ((XImage *));
6432 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6435 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6436 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6437 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6438 via xmalloc. Print error messages via image_error if an error
6439 occurs. Value is non-zero if successful. */
6441 static int
6442 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6443 struct frame *f;
6444 int width, height, depth;
6445 XImage **ximg;
6446 Pixmap *pixmap;
6448 Display *display = FRAME_X_DISPLAY (f);
6449 Screen *screen = FRAME_X_SCREEN (f);
6450 Window window = FRAME_X_WINDOW (f);
6452 xassert (interrupt_input_blocked);
6454 if (depth <= 0)
6455 depth = DefaultDepthOfScreen (screen);
6456 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6457 depth, ZPixmap, 0, NULL, width, height,
6458 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6459 if (*ximg == NULL)
6461 image_error ("Unable to allocate X image", Qnil, Qnil);
6462 return 0;
6465 /* Allocate image raster. */
6466 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6468 /* Allocate a pixmap of the same size. */
6469 *pixmap = XCreatePixmap (display, window, width, height, depth);
6470 if (*pixmap == 0)
6472 x_destroy_x_image (*ximg);
6473 *ximg = NULL;
6474 image_error ("Unable to create X pixmap", Qnil, Qnil);
6475 return 0;
6478 return 1;
6482 /* Destroy XImage XIMG. Free XIMG->data. */
6484 static void
6485 x_destroy_x_image (ximg)
6486 XImage *ximg;
6488 xassert (interrupt_input_blocked);
6489 if (ximg)
6491 xfree (ximg->data);
6492 ximg->data = NULL;
6493 XDestroyImage (ximg);
6498 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6499 are width and height of both the image and pixmap. */
6501 static void
6502 x_put_x_image (f, ximg, pixmap, width, height)
6503 struct frame *f;
6504 XImage *ximg;
6505 Pixmap pixmap;
6507 GC gc;
6509 xassert (interrupt_input_blocked);
6510 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6511 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6512 XFreeGC (FRAME_X_DISPLAY (f), gc);
6517 /***********************************************************************
6518 Searching files
6519 ***********************************************************************/
6521 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6523 /* Find image file FILE. Look in data-directory, then
6524 x-bitmap-file-path. Value is the full name of the file found, or
6525 nil if not found. */
6527 static Lisp_Object
6528 x_find_image_file (file)
6529 Lisp_Object file;
6531 Lisp_Object file_found, search_path;
6532 struct gcpro gcpro1, gcpro2;
6533 int fd;
6535 file_found = Qnil;
6536 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6537 GCPRO2 (file_found, search_path);
6539 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6540 fd = openp (search_path, file, "", &file_found, 0);
6542 if (fd < 0)
6543 file_found = Qnil;
6544 else
6545 close (fd);
6547 UNGCPRO;
6548 return file_found;
6553 /***********************************************************************
6554 XBM images
6555 ***********************************************************************/
6557 static int xbm_load P_ ((struct frame *f, struct image *img));
6558 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
6559 Lisp_Object file));
6560 static int xbm_image_p P_ ((Lisp_Object object));
6561 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
6562 unsigned char **));
6565 /* Indices of image specification fields in xbm_format, below. */
6567 enum xbm_keyword_index
6569 XBM_TYPE,
6570 XBM_FILE,
6571 XBM_WIDTH,
6572 XBM_HEIGHT,
6573 XBM_DATA,
6574 XBM_FOREGROUND,
6575 XBM_BACKGROUND,
6576 XBM_ASCENT,
6577 XBM_MARGIN,
6578 XBM_RELIEF,
6579 XBM_ALGORITHM,
6580 XBM_HEURISTIC_MASK,
6581 XBM_LAST
6584 /* Vector of image_keyword structures describing the format
6585 of valid XBM image specifications. */
6587 static struct image_keyword xbm_format[XBM_LAST] =
6589 {":type", IMAGE_SYMBOL_VALUE, 1},
6590 {":file", IMAGE_STRING_VALUE, 0},
6591 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6592 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6593 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6594 {":foreground", IMAGE_STRING_VALUE, 0},
6595 {":background", IMAGE_STRING_VALUE, 0},
6596 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6597 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6598 {":relief", IMAGE_INTEGER_VALUE, 0},
6599 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6600 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6603 /* Structure describing the image type XBM. */
6605 static struct image_type xbm_type =
6607 &Qxbm,
6608 xbm_image_p,
6609 xbm_load,
6610 x_clear_image,
6611 NULL
6614 /* Tokens returned from xbm_scan. */
6616 enum xbm_token
6618 XBM_TK_IDENT = 256,
6619 XBM_TK_NUMBER
6623 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6624 A valid specification is a list starting with the symbol `image'
6625 The rest of the list is a property list which must contain an
6626 entry `:type xbm..
6628 If the specification specifies a file to load, it must contain
6629 an entry `:file FILENAME' where FILENAME is a string.
6631 If the specification is for a bitmap loaded from memory it must
6632 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6633 WIDTH and HEIGHT are integers > 0. DATA may be:
6635 1. a string large enough to hold the bitmap data, i.e. it must
6636 have a size >= (WIDTH + 7) / 8 * HEIGHT
6638 2. a bool-vector of size >= WIDTH * HEIGHT
6640 3. a vector of strings or bool-vectors, one for each line of the
6641 bitmap.
6643 Both the file and data forms may contain the additional entries
6644 `:background COLOR' and `:foreground COLOR'. If not present,
6645 foreground and background of the frame on which the image is
6646 displayed, is used. */
6648 static int
6649 xbm_image_p (object)
6650 Lisp_Object object;
6652 struct image_keyword kw[XBM_LAST];
6654 bcopy (xbm_format, kw, sizeof kw);
6655 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6656 return 0;
6658 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6660 if (kw[XBM_FILE].count)
6662 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6663 return 0;
6665 else
6667 Lisp_Object data;
6668 int width, height;
6670 /* Entries for `:width', `:height' and `:data' must be present. */
6671 if (!kw[XBM_WIDTH].count
6672 || !kw[XBM_HEIGHT].count
6673 || !kw[XBM_DATA].count)
6674 return 0;
6676 data = kw[XBM_DATA].value;
6677 width = XFASTINT (kw[XBM_WIDTH].value);
6678 height = XFASTINT (kw[XBM_HEIGHT].value);
6680 /* Check type of data, and width and height against contents of
6681 data. */
6682 if (VECTORP (data))
6684 int i;
6686 /* Number of elements of the vector must be >= height. */
6687 if (XVECTOR (data)->size < height)
6688 return 0;
6690 /* Each string or bool-vector in data must be large enough
6691 for one line of the image. */
6692 for (i = 0; i < height; ++i)
6694 Lisp_Object elt = XVECTOR (data)->contents[i];
6696 if (STRINGP (elt))
6698 if (XSTRING (elt)->size
6699 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6700 return 0;
6702 else if (BOOL_VECTOR_P (elt))
6704 if (XBOOL_VECTOR (elt)->size < width)
6705 return 0;
6707 else
6708 return 0;
6711 else if (STRINGP (data))
6713 if (XSTRING (data)->size
6714 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6715 return 0;
6717 else if (BOOL_VECTOR_P (data))
6719 if (XBOOL_VECTOR (data)->size < width * height)
6720 return 0;
6722 else
6723 return 0;
6726 /* Baseline must be a value between 0 and 100 (a percentage). */
6727 if (kw[XBM_ASCENT].count
6728 && XFASTINT (kw[XBM_ASCENT].value) > 100)
6729 return 0;
6731 return 1;
6735 /* Scan a bitmap file. FP is the stream to read from. Value is
6736 either an enumerator from enum xbm_token, or a character for a
6737 single-character token, or 0 at end of file. If scanning an
6738 identifier, store the lexeme of the identifier in SVAL. If
6739 scanning a number, store its value in *IVAL. */
6741 static int
6742 xbm_scan (fp, sval, ival)
6743 FILE *fp;
6744 char *sval;
6745 int *ival;
6747 int c;
6749 /* Skip white space. */
6750 while ((c = fgetc (fp)) != EOF && isspace (c))
6753 if (c == EOF)
6754 c = 0;
6755 else if (isdigit (c))
6757 int value = 0, digit;
6759 if (c == '0')
6761 c = fgetc (fp);
6762 if (c == 'x' || c == 'X')
6764 while ((c = fgetc (fp)) != EOF)
6766 if (isdigit (c))
6767 digit = c - '0';
6768 else if (c >= 'a' && c <= 'f')
6769 digit = c - 'a' + 10;
6770 else if (c >= 'A' && c <= 'F')
6771 digit = c - 'A' + 10;
6772 else
6773 break;
6774 value = 16 * value + digit;
6777 else if (isdigit (c))
6779 value = c - '0';
6780 while ((c = fgetc (fp)) != EOF
6781 && isdigit (c))
6782 value = 8 * value + c - '0';
6785 else
6787 value = c - '0';
6788 while ((c = fgetc (fp)) != EOF
6789 && isdigit (c))
6790 value = 10 * value + c - '0';
6793 if (c != EOF)
6794 ungetc (c, fp);
6795 *ival = value;
6796 c = XBM_TK_NUMBER;
6798 else if (isalpha (c) || c == '_')
6800 *sval++ = c;
6801 while ((c = fgetc (fp)) != EOF
6802 && (isalnum (c) || c == '_'))
6803 *sval++ = c;
6804 *sval = 0;
6805 if (c != EOF)
6806 ungetc (c, fp);
6807 c = XBM_TK_IDENT;
6810 return c;
6814 /* Replacement for XReadBitmapFileData which isn't available under old
6815 X versions. FILE is the name of the bitmap file to read. Set
6816 *WIDTH and *HEIGHT to the width and height of the image. Return in
6817 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
6818 successful. */
6820 static int
6821 xbm_read_bitmap_file_data (file, width, height, data)
6822 char *file;
6823 int *width, *height;
6824 unsigned char **data;
6826 FILE *fp;
6827 char buffer[BUFSIZ];
6828 int padding_p = 0;
6829 int v10 = 0;
6830 int bytes_per_line, i, nbytes;
6831 unsigned char *p;
6832 int value;
6833 int LA1;
6835 #define match() \
6836 LA1 = xbm_scan (fp, buffer, &value)
6838 #define expect(TOKEN) \
6839 if (LA1 != (TOKEN)) \
6840 goto failure; \
6841 else \
6842 match ()
6844 #define expect_ident(IDENT) \
6845 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6846 match (); \
6847 else \
6848 goto failure
6850 fp = fopen (file, "r");
6851 if (fp == NULL)
6852 return 0;
6854 *width = *height = -1;
6855 *data = NULL;
6856 LA1 = xbm_scan (fp, buffer, &value);
6858 /* Parse defines for width, height and hot-spots. */
6859 while (LA1 == '#')
6861 match ();
6862 expect_ident ("define");
6863 expect (XBM_TK_IDENT);
6865 if (LA1 == XBM_TK_NUMBER);
6867 char *p = strrchr (buffer, '_');
6868 p = p ? p + 1 : buffer;
6869 if (strcmp (p, "width") == 0)
6870 *width = value;
6871 else if (strcmp (p, "height") == 0)
6872 *height = value;
6874 expect (XBM_TK_NUMBER);
6877 if (*width < 0 || *height < 0)
6878 goto failure;
6880 /* Parse bits. Must start with `static'. */
6881 expect_ident ("static");
6882 if (LA1 == XBM_TK_IDENT)
6884 if (strcmp (buffer, "unsigned") == 0)
6886 match ();
6887 expect_ident ("char");
6889 else if (strcmp (buffer, "short") == 0)
6891 match ();
6892 v10 = 1;
6893 if (*width % 16 && *width % 16 < 9)
6894 padding_p = 1;
6896 else if (strcmp (buffer, "char") == 0)
6897 match ();
6898 else
6899 goto failure;
6901 else
6902 goto failure;
6904 expect (XBM_TK_IDENT);
6905 expect ('[');
6906 expect (']');
6907 expect ('=');
6908 expect ('{');
6910 bytes_per_line = (*width + 7) / 8 + padding_p;
6911 nbytes = bytes_per_line * *height;
6912 p = *data = (char *) xmalloc (nbytes);
6914 if (v10)
6917 for (i = 0; i < nbytes; i += 2)
6919 int val = value;
6920 expect (XBM_TK_NUMBER);
6922 *p++ = val;
6923 if (!padding_p || ((i + 2) % bytes_per_line))
6924 *p++ = value >> 8;
6926 if (LA1 == ',' || LA1 == '}')
6927 match ();
6928 else
6929 goto failure;
6932 else
6934 for (i = 0; i < nbytes; ++i)
6936 int val = value;
6937 expect (XBM_TK_NUMBER);
6939 *p++ = val;
6941 if (LA1 == ',' || LA1 == '}')
6942 match ();
6943 else
6944 goto failure;
6948 fclose (fp);
6949 return 1;
6951 failure:
6953 fclose (fp);
6954 if (*data)
6956 xfree (*data);
6957 *data = NULL;
6959 return 0;
6961 #undef match
6962 #undef expect
6963 #undef expect_ident
6967 /* Load XBM image IMG which will be displayed on frame F from file
6968 SPECIFIED_FILE. Value is non-zero if successful. */
6970 static int
6971 xbm_load_image_from_file (f, img, specified_file)
6972 struct frame *f;
6973 struct image *img;
6974 Lisp_Object specified_file;
6976 int rc;
6977 unsigned char *data;
6978 int success_p = 0;
6979 Lisp_Object file;
6980 struct gcpro gcpro1;
6982 xassert (STRINGP (specified_file));
6983 file = Qnil;
6984 GCPRO1 (file);
6986 file = x_find_image_file (specified_file);
6987 if (!STRINGP (file))
6989 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6990 UNGCPRO;
6991 return 0;
6994 rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
6995 &img->height, &data);
6996 if (rc)
6998 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6999 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7000 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7001 Lisp_Object value;
7003 xassert (img->width > 0 && img->height > 0);
7005 /* Get foreground and background colors, maybe allocate colors. */
7006 value = image_spec_value (img->spec, QCforeground, NULL);
7007 if (!NILP (value))
7008 foreground = x_alloc_image_color (f, img, value, foreground);
7010 value = image_spec_value (img->spec, QCbackground, NULL);
7011 if (!NILP (value))
7012 background = x_alloc_image_color (f, img, value, background);
7014 BLOCK_INPUT;
7015 img->pixmap
7016 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7017 FRAME_X_WINDOW (f),
7018 data,
7019 img->width, img->height,
7020 foreground, background,
7021 depth);
7022 xfree (data);
7024 if (img->pixmap == 0)
7026 x_clear_image (f, img);
7027 image_error ("Unable to create X pixmap for `%s'", file, Qnil);
7029 else
7030 success_p = 1;
7032 UNBLOCK_INPUT;
7034 else
7035 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7037 UNGCPRO;
7038 return success_p;
7042 /* Fill image IMG which is used on frame F with pixmap data. Value is
7043 non-zero if successful. */
7045 static int
7046 xbm_load (f, img)
7047 struct frame *f;
7048 struct image *img;
7050 int success_p = 0;
7051 Lisp_Object file_name;
7053 xassert (xbm_image_p (img->spec));
7055 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7056 file_name = image_spec_value (img->spec, QCfile, NULL);
7057 if (STRINGP (file_name))
7058 success_p = xbm_load_image_from_file (f, img, file_name);
7059 else
7061 struct image_keyword fmt[XBM_LAST];
7062 Lisp_Object data;
7063 int depth;
7064 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7065 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7066 char *bits;
7067 int parsed_p;
7069 /* Parse the list specification. */
7070 bcopy (xbm_format, fmt, sizeof fmt);
7071 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
7072 xassert (parsed_p);
7074 /* Get specified width, and height. */
7075 img->width = XFASTINT (fmt[XBM_WIDTH].value);
7076 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
7077 xassert (img->width > 0 && img->height > 0);
7079 BLOCK_INPUT;
7081 if (fmt[XBM_ASCENT].count)
7082 img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
7084 /* Get foreground and background colors, maybe allocate colors. */
7085 if (fmt[XBM_FOREGROUND].count)
7086 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
7087 foreground);
7088 if (fmt[XBM_BACKGROUND].count)
7089 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
7090 background);
7092 /* Set bits to the bitmap image data. */
7093 data = fmt[XBM_DATA].value;
7094 if (VECTORP (data))
7096 int i;
7097 char *p;
7098 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
7100 p = bits = (char *) alloca (nbytes * img->height);
7101 for (i = 0; i < img->height; ++i, p += nbytes)
7103 Lisp_Object line = XVECTOR (data)->contents[i];
7104 if (STRINGP (line))
7105 bcopy (XSTRING (line)->data, p, nbytes);
7106 else
7107 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
7110 else if (STRINGP (data))
7111 bits = XSTRING (data)->data;
7112 else
7113 bits = XBOOL_VECTOR (data)->data;
7115 /* Create the pixmap. */
7116 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7117 img->pixmap
7118 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7119 FRAME_X_WINDOW (f),
7120 bits,
7121 img->width, img->height,
7122 foreground, background,
7123 depth);
7124 if (img->pixmap)
7125 success_p = 1;
7126 else
7128 image_error ("Unable to create pixmap for XBM image `%s'",
7129 img->spec, Qnil);
7130 x_clear_image (f, img);
7133 UNBLOCK_INPUT;
7136 return success_p;
7141 /***********************************************************************
7142 XPM images
7143 ***********************************************************************/
7145 #if HAVE_XPM
7147 static int xpm_image_p P_ ((Lisp_Object object));
7148 static int xpm_load P_ ((struct frame *f, struct image *img));
7149 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
7151 #include "X11/xpm.h"
7153 /* The symbol `xpm' identifying XPM-format images. */
7155 Lisp_Object Qxpm;
7157 /* Indices of image specification fields in xpm_format, below. */
7159 enum xpm_keyword_index
7161 XPM_TYPE,
7162 XPM_FILE,
7163 XPM_DATA,
7164 XPM_ASCENT,
7165 XPM_MARGIN,
7166 XPM_RELIEF,
7167 XPM_ALGORITHM,
7168 XPM_HEURISTIC_MASK,
7169 XPM_COLOR_SYMBOLS,
7170 XPM_LAST
7173 /* Vector of image_keyword structures describing the format
7174 of valid XPM image specifications. */
7176 static struct image_keyword xpm_format[XPM_LAST] =
7178 {":type", IMAGE_SYMBOL_VALUE, 1},
7179 {":file", IMAGE_STRING_VALUE, 0},
7180 {":data", IMAGE_STRING_VALUE, 0},
7181 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7182 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7183 {":relief", IMAGE_INTEGER_VALUE, 0},
7184 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7185 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7186 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7189 /* Structure describing the image type XBM. */
7191 static struct image_type xpm_type =
7193 &Qxpm,
7194 xpm_image_p,
7195 xpm_load,
7196 x_clear_image,
7197 NULL
7201 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7202 for XPM images. Such a list must consist of conses whose car and
7203 cdr are strings. */
7205 static int
7206 xpm_valid_color_symbols_p (color_symbols)
7207 Lisp_Object color_symbols;
7209 while (CONSP (color_symbols))
7211 Lisp_Object sym = XCAR (color_symbols);
7212 if (!CONSP (sym)
7213 || !STRINGP (XCAR (sym))
7214 || !STRINGP (XCDR (sym)))
7215 break;
7216 color_symbols = XCDR (color_symbols);
7219 return NILP (color_symbols);
7223 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7225 static int
7226 xpm_image_p (object)
7227 Lisp_Object object;
7229 struct image_keyword fmt[XPM_LAST];
7230 bcopy (xpm_format, fmt, sizeof fmt);
7231 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7232 /* Either `:file' or `:data' must be present. */
7233 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7234 /* Either no `:color-symbols' or it's a list of conses
7235 whose car and cdr are strings. */
7236 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7237 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
7238 && (fmt[XPM_ASCENT].count == 0
7239 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
7243 /* Load image IMG which will be displayed on frame F. Value is
7244 non-zero if successful. */
7246 static int
7247 xpm_load (f, img)
7248 struct frame *f;
7249 struct image *img;
7251 int rc, i;
7252 XpmAttributes attrs;
7253 Lisp_Object specified_file, color_symbols;
7255 /* Configure the XPM lib. Use the visual of frame F. Allocate
7256 close colors. Return colors allocated. */
7257 bzero (&attrs, sizeof attrs);
7258 attrs.visual = FRAME_X_DISPLAY_INFO (f)->visual;
7259 attrs.valuemask |= XpmVisual;
7260 attrs.valuemask |= XpmReturnAllocPixels;
7261 #ifdef XpmAllocCloseColors
7262 attrs.alloc_close_colors = 1;
7263 attrs.valuemask |= XpmAllocCloseColors;
7264 #else
7265 attrs.closeness = 600;
7266 attrs.valuemask |= XpmCloseness;
7267 #endif
7269 /* If image specification contains symbolic color definitions, add
7270 these to `attrs'. */
7271 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7272 if (CONSP (color_symbols))
7274 Lisp_Object tail;
7275 XpmColorSymbol *xpm_syms;
7276 int i, size;
7278 attrs.valuemask |= XpmColorSymbols;
7280 /* Count number of symbols. */
7281 attrs.numsymbols = 0;
7282 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7283 ++attrs.numsymbols;
7285 /* Allocate an XpmColorSymbol array. */
7286 size = attrs.numsymbols * sizeof *xpm_syms;
7287 xpm_syms = (XpmColorSymbol *) alloca (size);
7288 bzero (xpm_syms, size);
7289 attrs.colorsymbols = xpm_syms;
7291 /* Fill the color symbol array. */
7292 for (tail = color_symbols, i = 0;
7293 CONSP (tail);
7294 ++i, tail = XCDR (tail))
7296 Lisp_Object name = XCAR (XCAR (tail));
7297 Lisp_Object color = XCDR (XCAR (tail));
7298 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7299 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7300 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7301 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7305 /* Create a pixmap for the image, either from a file, or from a
7306 string buffer containing data in the same format as an XPM file. */
7307 BLOCK_INPUT;
7308 specified_file = image_spec_value (img->spec, QCfile, NULL);
7309 if (STRINGP (specified_file))
7311 Lisp_Object file = x_find_image_file (specified_file);
7312 if (!STRINGP (file))
7314 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7315 UNBLOCK_INPUT;
7316 return 0;
7319 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7320 XSTRING (file)->data, &img->pixmap, &img->mask,
7321 &attrs);
7323 else
7325 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7326 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7327 XSTRING (buffer)->data,
7328 &img->pixmap, &img->mask,
7329 &attrs);
7331 UNBLOCK_INPUT;
7333 if (rc == XpmSuccess)
7335 /* Remember allocated colors. */
7336 img->ncolors = attrs.nalloc_pixels;
7337 img->colors = (unsigned long *) xmalloc (img->ncolors
7338 * sizeof *img->colors);
7339 for (i = 0; i < attrs.nalloc_pixels; ++i)
7340 img->colors[i] = attrs.alloc_pixels[i];
7342 img->width = attrs.width;
7343 img->height = attrs.height;
7344 xassert (img->width > 0 && img->height > 0);
7346 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7347 BLOCK_INPUT;
7348 XpmFreeAttributes (&attrs);
7349 UNBLOCK_INPUT;
7351 else
7353 switch (rc)
7355 case XpmOpenFailed:
7356 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7357 break;
7359 case XpmFileInvalid:
7360 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7361 break;
7363 case XpmNoMemory:
7364 image_error ("Out of memory (%s)", img->spec, Qnil);
7365 break;
7367 case XpmColorFailed:
7368 image_error ("Color allocation error (%s)", img->spec, Qnil);
7369 break;
7371 default:
7372 image_error ("Unknown error (%s)", img->spec, Qnil);
7373 break;
7377 return rc == XpmSuccess;
7380 #endif /* HAVE_XPM != 0 */
7383 /***********************************************************************
7384 Color table
7385 ***********************************************************************/
7387 /* An entry in the color table mapping an RGB color to a pixel color. */
7389 struct ct_color
7391 int r, g, b;
7392 unsigned long pixel;
7394 /* Next in color table collision list. */
7395 struct ct_color *next;
7398 /* The bucket vector size to use. Must be prime. */
7400 #define CT_SIZE 101
7402 /* Value is a hash of the RGB color given by R, G, and B. */
7404 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7406 /* The color hash table. */
7408 struct ct_color **ct_table;
7410 /* Number of entries in the color table. */
7412 int ct_colors_allocated;
7414 /* Function prototypes. */
7416 static void init_color_table P_ ((void));
7417 static void free_color_table P_ ((void));
7418 static unsigned long *colors_in_color_table P_ ((int *n));
7419 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
7420 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
7423 /* Initialize the color table. */
7425 static void
7426 init_color_table ()
7428 int size = CT_SIZE * sizeof (*ct_table);
7429 ct_table = (struct ct_color **) xmalloc (size);
7430 bzero (ct_table, size);
7431 ct_colors_allocated = 0;
7435 /* Free memory associated with the color table. */
7437 static void
7438 free_color_table ()
7440 int i;
7441 struct ct_color *p, *next;
7443 for (i = 0; i < CT_SIZE; ++i)
7444 for (p = ct_table[i]; p; p = next)
7446 next = p->next;
7447 xfree (p);
7450 xfree (ct_table);
7451 ct_table = NULL;
7455 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7456 entry for that color already is in the color table, return the
7457 pixel color of that entry. Otherwise, allocate a new color for R,
7458 G, B, and make an entry in the color table. */
7460 static unsigned long
7461 lookup_rgb_color (f, r, g, b)
7462 struct frame *f;
7463 int r, g, b;
7465 unsigned hash = CT_HASH_RGB (r, g, b);
7466 int i = hash % CT_SIZE;
7467 struct ct_color *p;
7469 for (p = ct_table[i]; p; p = p->next)
7470 if (p->r == r && p->g == g && p->b == b)
7471 break;
7473 if (p == NULL)
7475 XColor color;
7476 Colormap cmap;
7477 int rc;
7479 color.red = r;
7480 color.green = g;
7481 color.blue = b;
7483 BLOCK_INPUT;
7484 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7485 rc = x_alloc_nearest_color (f, cmap, &color);
7486 UNBLOCK_INPUT;
7488 if (rc)
7490 ++ct_colors_allocated;
7492 p = (struct ct_color *) xmalloc (sizeof *p);
7493 p->r = r;
7494 p->g = g;
7495 p->b = b;
7496 p->pixel = color.pixel;
7497 p->next = ct_table[i];
7498 ct_table[i] = p;
7500 else
7501 return FRAME_FOREGROUND_PIXEL (f);
7504 return p->pixel;
7508 /* Look up pixel color PIXEL which is used on frame F in the color
7509 table. If not already present, allocate it. Value is PIXEL. */
7511 static unsigned long
7512 lookup_pixel_color (f, pixel)
7513 struct frame *f;
7514 unsigned long pixel;
7516 int i = pixel % CT_SIZE;
7517 struct ct_color *p;
7519 for (p = ct_table[i]; p; p = p->next)
7520 if (p->pixel == pixel)
7521 break;
7523 if (p == NULL)
7525 XColor color;
7526 Colormap cmap;
7527 int rc;
7529 BLOCK_INPUT;
7531 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7532 color.pixel = pixel;
7533 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
7534 rc = x_alloc_nearest_color (f, cmap, &color);
7535 UNBLOCK_INPUT;
7537 if (rc)
7539 ++ct_colors_allocated;
7541 p = (struct ct_color *) xmalloc (sizeof *p);
7542 p->r = color.red;
7543 p->g = color.green;
7544 p->b = color.blue;
7545 p->pixel = pixel;
7546 p->next = ct_table[i];
7547 ct_table[i] = p;
7549 else
7550 return FRAME_FOREGROUND_PIXEL (f);
7553 return p->pixel;
7557 /* Value is a vector of all pixel colors contained in the color table,
7558 allocated via xmalloc. Set *N to the number of colors. */
7560 static unsigned long *
7561 colors_in_color_table (n)
7562 int *n;
7564 int i, j;
7565 struct ct_color *p;
7566 unsigned long *colors;
7568 if (ct_colors_allocated == 0)
7570 *n = 0;
7571 colors = NULL;
7573 else
7575 colors = (unsigned long *) xmalloc (ct_colors_allocated
7576 * sizeof *colors);
7577 *n = ct_colors_allocated;
7579 for (i = j = 0; i < CT_SIZE; ++i)
7580 for (p = ct_table[i]; p; p = p->next)
7581 colors[j++] = p->pixel;
7584 return colors;
7589 /***********************************************************************
7590 Algorithms
7591 ***********************************************************************/
7593 static void x_laplace_write_row P_ ((struct frame *, long *,
7594 int, XImage *, int));
7595 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7596 XColor *, int, XImage *, int));
7599 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
7600 frame we operate on, CMAP is the color-map in effect, and WIDTH is
7601 the width of one row in the image. */
7603 static void
7604 x_laplace_read_row (f, cmap, colors, width, ximg, y)
7605 struct frame *f;
7606 Colormap cmap;
7607 XColor *colors;
7608 int width;
7609 XImage *ximg;
7610 int y;
7612 int x;
7614 for (x = 0; x < width; ++x)
7615 colors[x].pixel = XGetPixel (ximg, x, y);
7617 XQueryColors (FRAME_X_DISPLAY (f), cmap, colors, width);
7621 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
7622 containing the pixel colors to write. F is the frame we are
7623 working on. */
7625 static void
7626 x_laplace_write_row (f, pixels, width, ximg, y)
7627 struct frame *f;
7628 long *pixels;
7629 int width;
7630 XImage *ximg;
7631 int y;
7633 int x;
7635 for (x = 0; x < width; ++x)
7636 XPutPixel (ximg, x, y, pixels[x]);
7640 /* Transform image IMG which is used on frame F with a Laplace
7641 edge-detection algorithm. The result is an image that can be used
7642 to draw disabled buttons, for example. */
7644 static void
7645 x_laplace (f, img)
7646 struct frame *f;
7647 struct image *img;
7649 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7650 XImage *ximg, *oimg;
7651 XColor *in[3];
7652 long *out;
7653 Pixmap pixmap;
7654 int x, y, i;
7655 long pixel;
7656 int in_y, out_y, rc;
7657 int mv2 = 45000;
7659 BLOCK_INPUT;
7661 /* Get the X image IMG->pixmap. */
7662 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7663 0, 0, img->width, img->height, ~0, ZPixmap);
7665 /* Allocate 3 input rows, and one output row of colors. */
7666 for (i = 0; i < 3; ++i)
7667 in[i] = (XColor *) alloca (img->width * sizeof (XColor));
7668 out = (long *) alloca (img->width * sizeof (long));
7670 /* Create an X image for output. */
7671 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7672 &oimg, &pixmap);
7674 /* Fill first two rows. */
7675 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
7676 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
7677 in_y = 2;
7679 /* Write first row, all zeros. */
7680 init_color_table ();
7681 pixel = lookup_rgb_color (f, 0, 0, 0);
7682 for (x = 0; x < img->width; ++x)
7683 out[x] = pixel;
7684 x_laplace_write_row (f, out, img->width, oimg, 0);
7685 out_y = 1;
7687 for (y = 2; y < img->height; ++y)
7689 int rowa = y % 3;
7690 int rowb = (y + 2) % 3;
7692 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
7694 for (x = 0; x < img->width - 2; ++x)
7696 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
7697 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
7698 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
7700 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
7701 b & 0xffff);
7704 x_laplace_write_row (f, out, img->width, oimg, out_y++);
7707 /* Write last line, all zeros. */
7708 for (x = 0; x < img->width; ++x)
7709 out[x] = pixel;
7710 x_laplace_write_row (f, out, img->width, oimg, out_y);
7712 /* Free the input image, and free resources of IMG. */
7713 XDestroyImage (ximg);
7714 x_clear_image (f, img);
7716 /* Put the output image into pixmap, and destroy it. */
7717 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7718 x_destroy_x_image (oimg);
7720 /* Remember new pixmap and colors in IMG. */
7721 img->pixmap = pixmap;
7722 img->colors = colors_in_color_table (&img->ncolors);
7723 free_color_table ();
7725 UNBLOCK_INPUT;
7729 /* Build a mask for image IMG which is used on frame F. FILE is the
7730 name of an image file, for error messages. HOW determines how to
7731 determine the background color of IMG. If it is a list '(R G B)',
7732 with R, G, and B being integers >= 0, take that as the color of the
7733 background. Otherwise, determine the background color of IMG
7734 heuristically. Value is non-zero if successful. */
7736 static int
7737 x_build_heuristic_mask (f, img, how)
7738 struct frame *f;
7739 struct image *img;
7740 Lisp_Object how;
7742 Display *dpy = FRAME_X_DISPLAY (f);
7743 XImage *ximg, *mask_img;
7744 int x, y, rc, look_at_corners_p;
7745 unsigned long bg;
7747 BLOCK_INPUT;
7749 /* Create an image and pixmap serving as mask. */
7750 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7751 &mask_img, &img->mask);
7752 if (!rc)
7754 UNBLOCK_INPUT;
7755 return 0;
7758 /* Get the X image of IMG->pixmap. */
7759 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7760 ~0, ZPixmap);
7762 /* Determine the background color of ximg. If HOW is `(R G B)'
7763 take that as color. Otherwise, try to determine the color
7764 heuristically. */
7765 look_at_corners_p = 1;
7767 if (CONSP (how))
7769 int rgb[3], i = 0;
7771 while (i < 3
7772 && CONSP (how)
7773 && NATNUMP (XCAR (how)))
7775 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
7776 how = XCDR (how);
7779 if (i == 3 && NILP (how))
7781 char color_name[30];
7782 XColor exact, color;
7783 Colormap cmap;
7785 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
7787 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7788 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
7790 bg = color.pixel;
7791 look_at_corners_p = 0;
7796 if (look_at_corners_p)
7798 unsigned long corners[4];
7799 int i, best_count;
7801 /* Get the colors at the corners of ximg. */
7802 corners[0] = XGetPixel (ximg, 0, 0);
7803 corners[1] = XGetPixel (ximg, img->width - 1, 0);
7804 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
7805 corners[3] = XGetPixel (ximg, 0, img->height - 1);
7807 /* Choose the most frequently found color as background. */
7808 for (i = best_count = 0; i < 4; ++i)
7810 int j, n;
7812 for (j = n = 0; j < 4; ++j)
7813 if (corners[i] == corners[j])
7814 ++n;
7816 if (n > best_count)
7817 bg = corners[i], best_count = n;
7821 /* Set all bits in mask_img to 1 whose color in ximg is different
7822 from the background color bg. */
7823 for (y = 0; y < img->height; ++y)
7824 for (x = 0; x < img->width; ++x)
7825 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7827 /* Put mask_img into img->mask. */
7828 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7829 x_destroy_x_image (mask_img);
7830 XDestroyImage (ximg);
7832 UNBLOCK_INPUT;
7833 return 1;
7838 /***********************************************************************
7839 PBM (mono, gray, color)
7840 ***********************************************************************/
7842 static int pbm_image_p P_ ((Lisp_Object object));
7843 static int pbm_load P_ ((struct frame *f, struct image *img));
7844 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7846 /* The symbol `pbm' identifying images of this type. */
7848 Lisp_Object Qpbm;
7850 /* Indices of image specification fields in gs_format, below. */
7852 enum pbm_keyword_index
7854 PBM_TYPE,
7855 PBM_FILE,
7856 PBM_DATA,
7857 PBM_ASCENT,
7858 PBM_MARGIN,
7859 PBM_RELIEF,
7860 PBM_ALGORITHM,
7861 PBM_HEURISTIC_MASK,
7862 PBM_LAST
7865 /* Vector of image_keyword structures describing the format
7866 of valid user-defined image specifications. */
7868 static struct image_keyword pbm_format[PBM_LAST] =
7870 {":type", IMAGE_SYMBOL_VALUE, 1},
7871 {":file", IMAGE_STRING_VALUE, 0},
7872 {":data", IMAGE_STRING_VALUE, 0},
7873 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7874 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7875 {":relief", IMAGE_INTEGER_VALUE, 0},
7876 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7877 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7880 /* Structure describing the image type `pbm'. */
7882 static struct image_type pbm_type =
7884 &Qpbm,
7885 pbm_image_p,
7886 pbm_load,
7887 x_clear_image,
7888 NULL
7892 /* Return non-zero if OBJECT is a valid PBM image specification. */
7894 static int
7895 pbm_image_p (object)
7896 Lisp_Object object;
7898 struct image_keyword fmt[PBM_LAST];
7900 bcopy (pbm_format, fmt, sizeof fmt);
7902 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
7903 || (fmt[PBM_ASCENT].count
7904 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
7905 return 0;
7907 /* Must specify either :data or :file. */
7908 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7912 /* Scan a decimal number from *S and return it. Advance *S while
7913 reading the number. END is the end of the string. Value is -1 at
7914 end of input. */
7916 static int
7917 pbm_scan_number (s, end)
7918 unsigned char **s, *end;
7920 int c, val = -1;
7922 while (*s < end)
7924 /* Skip white-space. */
7925 while (*s < end && (c = *(*s)++, isspace (c)))
7928 if (c == '#')
7930 /* Skip comment to end of line. */
7931 while (*s < end && (c = *(*s)++, c != '\n'))
7934 else if (isdigit (c))
7936 /* Read decimal number. */
7937 val = c - '0';
7938 while (*s < end && (c = *(*s)++, isdigit (c)))
7939 val = 10 * val + c - '0';
7940 break;
7942 else
7943 break;
7946 return val;
7950 /* Read FILE into memory. Value is a pointer to a buffer allocated
7951 with xmalloc holding FILE's contents. Value is null if an error
7952 occured. *SIZE is set to the size of the file. */
7954 static char *
7955 pbm_read_file (file, size)
7956 Lisp_Object file;
7957 int *size;
7959 FILE *fp = NULL;
7960 char *buf = NULL;
7961 struct stat st;
7963 if (stat (XSTRING (file)->data, &st) == 0
7964 && (fp = fopen (XSTRING (file)->data, "r")) != NULL
7965 && (buf = (char *) xmalloc (st.st_size),
7966 fread (buf, 1, st.st_size, fp) == st.st_size))
7968 *size = st.st_size;
7969 fclose (fp);
7971 else
7973 if (fp)
7974 fclose (fp);
7975 if (buf)
7977 xfree (buf);
7978 buf = NULL;
7982 return buf;
7986 /* Load PBM image IMG for use on frame F. */
7988 static int
7989 pbm_load (f, img)
7990 struct frame *f;
7991 struct image *img;
7993 int raw_p, x, y;
7994 int width, height, max_color_idx = 0;
7995 XImage *ximg;
7996 Lisp_Object file, specified_file;
7997 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7998 struct gcpro gcpro1;
7999 unsigned char *contents = NULL;
8000 unsigned char *end, *p;
8001 int size;
8003 specified_file = image_spec_value (img->spec, QCfile, NULL);
8004 file = Qnil;
8005 GCPRO1 (file);
8007 if (STRINGP (specified_file))
8009 file = x_find_image_file (specified_file);
8010 if (!STRINGP (file))
8012 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8013 UNGCPRO;
8014 return 0;
8017 contents = pbm_read_file (file, &size);
8018 if (contents == NULL)
8020 image_error ("Error reading `%s'", file, Qnil);
8021 UNGCPRO;
8022 return 0;
8025 p = contents;
8026 end = contents + size;
8028 else
8030 Lisp_Object data;
8031 data = image_spec_value (img->spec, QCdata, NULL);
8032 p = XSTRING (data)->data;
8033 end = p + STRING_BYTES (XSTRING (data));
8036 /* Check magic number. */
8037 if (end - p < 2 || *p++ != 'P')
8039 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8040 error:
8041 xfree (contents);
8042 UNGCPRO;
8043 return 0;
8046 switch (*p++)
8048 case '1':
8049 raw_p = 0, type = PBM_MONO;
8050 break;
8052 case '2':
8053 raw_p = 0, type = PBM_GRAY;
8054 break;
8056 case '3':
8057 raw_p = 0, type = PBM_COLOR;
8058 break;
8060 case '4':
8061 raw_p = 1, type = PBM_MONO;
8062 break;
8064 case '5':
8065 raw_p = 1, type = PBM_GRAY;
8066 break;
8068 case '6':
8069 raw_p = 1, type = PBM_COLOR;
8070 break;
8072 default:
8073 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8074 goto error;
8077 /* Read width, height, maximum color-component. Characters
8078 starting with `#' up to the end of a line are ignored. */
8079 width = pbm_scan_number (&p, end);
8080 height = pbm_scan_number (&p, end);
8082 if (type != PBM_MONO)
8084 max_color_idx = pbm_scan_number (&p, end);
8085 if (raw_p && max_color_idx > 255)
8086 max_color_idx = 255;
8089 if (width < 0
8090 || height < 0
8091 || (type != PBM_MONO && max_color_idx < 0))
8092 goto error;
8094 BLOCK_INPUT;
8095 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8096 &ximg, &img->pixmap))
8098 UNBLOCK_INPUT;
8099 goto error;
8102 /* Initialize the color hash table. */
8103 init_color_table ();
8105 if (type == PBM_MONO)
8107 int c = 0, g;
8109 for (y = 0; y < height; ++y)
8110 for (x = 0; x < width; ++x)
8112 if (raw_p)
8114 if ((x & 7) == 0)
8115 c = *p++;
8116 g = c & 0x80;
8117 c <<= 1;
8119 else
8120 g = pbm_scan_number (&p, end);
8122 XPutPixel (ximg, x, y, (g
8123 ? FRAME_FOREGROUND_PIXEL (f)
8124 : FRAME_BACKGROUND_PIXEL (f)));
8127 else
8129 for (y = 0; y < height; ++y)
8130 for (x = 0; x < width; ++x)
8132 int r, g, b;
8134 if (type == PBM_GRAY)
8135 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8136 else if (raw_p)
8138 r = *p++;
8139 g = *p++;
8140 b = *p++;
8142 else
8144 r = pbm_scan_number (&p, end);
8145 g = pbm_scan_number (&p, end);
8146 b = pbm_scan_number (&p, end);
8149 if (r < 0 || g < 0 || b < 0)
8151 xfree (ximg->data);
8152 ximg->data = NULL;
8153 XDestroyImage (ximg);
8154 UNBLOCK_INPUT;
8155 image_error ("Invalid pixel value in image `%s'",
8156 img->spec, Qnil);
8157 goto error;
8160 /* RGB values are now in the range 0..max_color_idx.
8161 Scale this to the range 0..0xffff supported by X. */
8162 r = (double) r * 65535 / max_color_idx;
8163 g = (double) g * 65535 / max_color_idx;
8164 b = (double) b * 65535 / max_color_idx;
8165 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8169 /* Store in IMG->colors the colors allocated for the image, and
8170 free the color table. */
8171 img->colors = colors_in_color_table (&img->ncolors);
8172 free_color_table ();
8174 /* Put the image into a pixmap. */
8175 x_put_x_image (f, ximg, img->pixmap, width, height);
8176 x_destroy_x_image (ximg);
8177 UNBLOCK_INPUT;
8179 img->width = width;
8180 img->height = height;
8182 UNGCPRO;
8183 xfree (contents);
8184 return 1;
8189 /***********************************************************************
8191 ***********************************************************************/
8193 #if HAVE_PNG
8195 #include <png.h>
8197 /* Function prototypes. */
8199 static int png_image_p P_ ((Lisp_Object object));
8200 static int png_load P_ ((struct frame *f, struct image *img));
8202 /* The symbol `png' identifying images of this type. */
8204 Lisp_Object Qpng;
8206 /* Indices of image specification fields in png_format, below. */
8208 enum png_keyword_index
8210 PNG_TYPE,
8211 PNG_DATA,
8212 PNG_FILE,
8213 PNG_ASCENT,
8214 PNG_MARGIN,
8215 PNG_RELIEF,
8216 PNG_ALGORITHM,
8217 PNG_HEURISTIC_MASK,
8218 PNG_LAST
8221 /* Vector of image_keyword structures describing the format
8222 of valid user-defined image specifications. */
8224 static struct image_keyword png_format[PNG_LAST] =
8226 {":type", IMAGE_SYMBOL_VALUE, 1},
8227 {":data", IMAGE_STRING_VALUE, 0},
8228 {":file", IMAGE_STRING_VALUE, 0},
8229 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8230 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8231 {":relief", IMAGE_INTEGER_VALUE, 0},
8232 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8233 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8236 /* Structure describing the image type `png'. */
8238 static struct image_type png_type =
8240 &Qpng,
8241 png_image_p,
8242 png_load,
8243 x_clear_image,
8244 NULL
8248 /* Return non-zero if OBJECT is a valid PNG image specification. */
8250 static int
8251 png_image_p (object)
8252 Lisp_Object object;
8254 struct image_keyword fmt[PNG_LAST];
8255 bcopy (png_format, fmt, sizeof fmt);
8257 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
8258 || (fmt[PNG_ASCENT].count
8259 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
8260 return 0;
8262 /* Must specify either the :data or :file keyword. */
8263 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8267 /* Error and warning handlers installed when the PNG library
8268 is initialized. */
8270 static void
8271 my_png_error (png_ptr, msg)
8272 png_struct *png_ptr;
8273 char *msg;
8275 xassert (png_ptr != NULL);
8276 image_error ("PNG error: %s", build_string (msg), Qnil);
8277 longjmp (png_ptr->jmpbuf, 1);
8281 static void
8282 my_png_warning (png_ptr, msg)
8283 png_struct *png_ptr;
8284 char *msg;
8286 xassert (png_ptr != NULL);
8287 image_error ("PNG warning: %s", build_string (msg), Qnil);
8290 /* Memory source for PNG decoding. */
8292 struct png_memory_storage
8294 unsigned char *bytes; /* The data */
8295 size_t len; /* How big is it? */
8296 int index; /* Where are we? */
8300 /* Function set as reader function when reading PNG image from memory.
8301 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8302 bytes from the input to DATA. */
8304 static void
8305 png_read_from_memory (png_ptr, data, length)
8306 png_structp png_ptr;
8307 png_bytep data;
8308 png_size_t length;
8310 struct png_memory_storage *tbr
8311 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8313 if (length > tbr->len - tbr->index)
8314 png_error (png_ptr, "Read error");
8316 bcopy (tbr->bytes + tbr->index, data, length);
8317 tbr->index = tbr->index + length;
8320 /* Load PNG image IMG for use on frame F. Value is non-zero if
8321 successful. */
8323 static int
8324 png_load (f, img)
8325 struct frame *f;
8326 struct image *img;
8328 Lisp_Object file, specified_file;
8329 Lisp_Object specified_data;
8330 int x, y, i;
8331 XImage *ximg, *mask_img = NULL;
8332 struct gcpro gcpro1;
8333 png_struct *png_ptr = NULL;
8334 png_info *info_ptr = NULL, *end_info = NULL;
8335 FILE *fp = NULL;
8336 png_byte sig[8];
8337 png_byte *pixels = NULL;
8338 png_byte **rows = NULL;
8339 png_uint_32 width, height;
8340 int bit_depth, color_type, interlace_type;
8341 png_byte channels;
8342 png_uint_32 row_bytes;
8343 int transparent_p;
8344 char *gamma_str;
8345 double screen_gamma, image_gamma;
8346 int intent;
8347 struct png_memory_storage tbr; /* Data to be read */
8349 /* Find out what file to load. */
8350 specified_file = image_spec_value (img->spec, QCfile, NULL);
8351 specified_data = image_spec_value (img->spec, QCdata, NULL);
8352 file = Qnil;
8353 GCPRO1 (file);
8355 if (NILP (specified_data))
8357 file = x_find_image_file (specified_file);
8358 if (!STRINGP (file))
8360 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8361 UNGCPRO;
8362 return 0;
8365 /* Open the image file. */
8366 fp = fopen (XSTRING (file)->data, "rb");
8367 if (!fp)
8369 image_error ("Cannot open image file `%s'", file, Qnil);
8370 UNGCPRO;
8371 fclose (fp);
8372 return 0;
8375 /* Check PNG signature. */
8376 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8377 || !png_check_sig (sig, sizeof sig))
8379 image_error ("Not a PNG file: `%s'", file, Qnil);
8380 UNGCPRO;
8381 fclose (fp);
8382 return 0;
8385 else
8387 /* Read from memory. */
8388 tbr.bytes = XSTRING (specified_data)->data;
8389 tbr.len = STRING_BYTES (XSTRING (specified_data));
8390 tbr.index = 0;
8392 /* Check PNG signature. */
8393 if (tbr.len < sizeof sig
8394 || !png_check_sig (tbr.bytes, sizeof sig))
8396 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8397 UNGCPRO;
8398 return 0;
8401 /* Need to skip past the signature. */
8402 tbr.bytes += sizeof (sig);
8405 /* Initialize read and info structs for PNG lib. */
8406 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8407 my_png_error, my_png_warning);
8408 if (!png_ptr)
8410 if (fp) fclose (fp);
8411 UNGCPRO;
8412 return 0;
8415 info_ptr = png_create_info_struct (png_ptr);
8416 if (!info_ptr)
8418 png_destroy_read_struct (&png_ptr, NULL, NULL);
8419 if (fp) fclose (fp);
8420 UNGCPRO;
8421 return 0;
8424 end_info = png_create_info_struct (png_ptr);
8425 if (!end_info)
8427 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8428 if (fp) fclose (fp);
8429 UNGCPRO;
8430 return 0;
8433 /* Set error jump-back. We come back here when the PNG library
8434 detects an error. */
8435 if (setjmp (png_ptr->jmpbuf))
8437 error:
8438 if (png_ptr)
8439 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8440 xfree (pixels);
8441 xfree (rows);
8442 if (fp) fclose (fp);
8443 UNGCPRO;
8444 return 0;
8447 /* Read image info. */
8448 if (!NILP (specified_data))
8449 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8450 else
8451 png_init_io (png_ptr, fp);
8453 png_set_sig_bytes (png_ptr, sizeof sig);
8454 png_read_info (png_ptr, info_ptr);
8455 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8456 &interlace_type, NULL, NULL);
8458 /* If image contains simply transparency data, we prefer to
8459 construct a clipping mask. */
8460 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8461 transparent_p = 1;
8462 else
8463 transparent_p = 0;
8465 /* This function is easier to write if we only have to handle
8466 one data format: RGB or RGBA with 8 bits per channel. Let's
8467 transform other formats into that format. */
8469 /* Strip more than 8 bits per channel. */
8470 if (bit_depth == 16)
8471 png_set_strip_16 (png_ptr);
8473 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8474 if available. */
8475 png_set_expand (png_ptr);
8477 /* Convert grayscale images to RGB. */
8478 if (color_type == PNG_COLOR_TYPE_GRAY
8479 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8480 png_set_gray_to_rgb (png_ptr);
8482 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8483 gamma_str = getenv ("SCREEN_GAMMA");
8484 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8486 /* Tell the PNG lib to handle gamma correction for us. */
8488 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8489 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8490 /* There is a special chunk in the image specifying the gamma. */
8491 png_set_sRGB (png_ptr, info_ptr, intent);
8492 else
8493 #endif
8494 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8495 /* Image contains gamma information. */
8496 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8497 else
8498 /* Use a default of 0.5 for the image gamma. */
8499 png_set_gamma (png_ptr, screen_gamma, 0.5);
8501 /* Handle alpha channel by combining the image with a background
8502 color. Do this only if a real alpha channel is supplied. For
8503 simple transparency, we prefer a clipping mask. */
8504 if (!transparent_p)
8506 png_color_16 *image_background;
8508 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
8509 /* Image contains a background color with which to
8510 combine the image. */
8511 png_set_background (png_ptr, image_background,
8512 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8513 else
8515 /* Image does not contain a background color with which
8516 to combine the image data via an alpha channel. Use
8517 the frame's background instead. */
8518 XColor color;
8519 Colormap cmap;
8520 png_color_16 frame_background;
8522 BLOCK_INPUT;
8523 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
8524 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8525 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
8526 UNBLOCK_INPUT;
8528 bzero (&frame_background, sizeof frame_background);
8529 frame_background.red = color.red;
8530 frame_background.green = color.green;
8531 frame_background.blue = color.blue;
8533 png_set_background (png_ptr, &frame_background,
8534 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8538 /* Update info structure. */
8539 png_read_update_info (png_ptr, info_ptr);
8541 /* Get number of channels. Valid values are 1 for grayscale images
8542 and images with a palette, 2 for grayscale images with transparency
8543 information (alpha channel), 3 for RGB images, and 4 for RGB
8544 images with alpha channel, i.e. RGBA. If conversions above were
8545 sufficient we should only have 3 or 4 channels here. */
8546 channels = png_get_channels (png_ptr, info_ptr);
8547 xassert (channels == 3 || channels == 4);
8549 /* Number of bytes needed for one row of the image. */
8550 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8552 /* Allocate memory for the image. */
8553 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8554 rows = (png_byte **) xmalloc (height * sizeof *rows);
8555 for (i = 0; i < height; ++i)
8556 rows[i] = pixels + i * row_bytes;
8558 /* Read the entire image. */
8559 png_read_image (png_ptr, rows);
8560 png_read_end (png_ptr, info_ptr);
8561 if (fp)
8563 fclose (fp);
8564 fp = NULL;
8567 BLOCK_INPUT;
8569 /* Create the X image and pixmap. */
8570 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
8571 &img->pixmap))
8573 UNBLOCK_INPUT;
8574 goto error;
8577 /* Create an image and pixmap serving as mask if the PNG image
8578 contains an alpha channel. */
8579 if (channels == 4
8580 && !transparent_p
8581 && !x_create_x_image_and_pixmap (f, width, height, 1,
8582 &mask_img, &img->mask))
8584 x_destroy_x_image (ximg);
8585 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8586 img->pixmap = 0;
8587 UNBLOCK_INPUT;
8588 goto error;
8591 /* Fill the X image and mask from PNG data. */
8592 init_color_table ();
8594 for (y = 0; y < height; ++y)
8596 png_byte *p = rows[y];
8598 for (x = 0; x < width; ++x)
8600 unsigned r, g, b;
8602 r = *p++ << 8;
8603 g = *p++ << 8;
8604 b = *p++ << 8;
8605 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8607 /* An alpha channel, aka mask channel, associates variable
8608 transparency with an image. Where other image formats
8609 support binary transparency---fully transparent or fully
8610 opaque---PNG allows up to 254 levels of partial transparency.
8611 The PNG library implements partial transparency by combining
8612 the image with a specified background color.
8614 I'm not sure how to handle this here nicely: because the
8615 background on which the image is displayed may change, for
8616 real alpha channel support, it would be necessary to create
8617 a new image for each possible background.
8619 What I'm doing now is that a mask is created if we have
8620 boolean transparency information. Otherwise I'm using
8621 the frame's background color to combine the image with. */
8623 if (channels == 4)
8625 if (mask_img)
8626 XPutPixel (mask_img, x, y, *p > 0);
8627 ++p;
8632 /* Remember colors allocated for this image. */
8633 img->colors = colors_in_color_table (&img->ncolors);
8634 free_color_table ();
8636 /* Clean up. */
8637 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8638 xfree (rows);
8639 xfree (pixels);
8641 img->width = width;
8642 img->height = height;
8644 /* Put the image into the pixmap, then free the X image and its buffer. */
8645 x_put_x_image (f, ximg, img->pixmap, width, height);
8646 x_destroy_x_image (ximg);
8648 /* Same for the mask. */
8649 if (mask_img)
8651 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8652 x_destroy_x_image (mask_img);
8655 UNBLOCK_INPUT;
8656 UNGCPRO;
8657 return 1;
8660 #endif /* HAVE_PNG != 0 */
8664 /***********************************************************************
8665 JPEG
8666 ***********************************************************************/
8668 #if HAVE_JPEG
8670 /* Work around a warning about HAVE_STDLIB_H being redefined in
8671 jconfig.h. */
8672 #ifdef HAVE_STDLIB_H
8673 #define HAVE_STDLIB_H_1
8674 #undef HAVE_STDLIB_H
8675 #endif /* HAVE_STLIB_H */
8677 #include <jpeglib.h>
8678 #include <jerror.h>
8679 #include <setjmp.h>
8681 #ifdef HAVE_STLIB_H_1
8682 #define HAVE_STDLIB_H 1
8683 #endif
8685 static int jpeg_image_p P_ ((Lisp_Object object));
8686 static int jpeg_load P_ ((struct frame *f, struct image *img));
8688 /* The symbol `jpeg' identifying images of this type. */
8690 Lisp_Object Qjpeg;
8692 /* Indices of image specification fields in gs_format, below. */
8694 enum jpeg_keyword_index
8696 JPEG_TYPE,
8697 JPEG_DATA,
8698 JPEG_FILE,
8699 JPEG_ASCENT,
8700 JPEG_MARGIN,
8701 JPEG_RELIEF,
8702 JPEG_ALGORITHM,
8703 JPEG_HEURISTIC_MASK,
8704 JPEG_LAST
8707 /* Vector of image_keyword structures describing the format
8708 of valid user-defined image specifications. */
8710 static struct image_keyword jpeg_format[JPEG_LAST] =
8712 {":type", IMAGE_SYMBOL_VALUE, 1},
8713 {":data", IMAGE_STRING_VALUE, 0},
8714 {":file", IMAGE_STRING_VALUE, 0},
8715 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8716 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8717 {":relief", IMAGE_INTEGER_VALUE, 0},
8718 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8719 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8722 /* Structure describing the image type `jpeg'. */
8724 static struct image_type jpeg_type =
8726 &Qjpeg,
8727 jpeg_image_p,
8728 jpeg_load,
8729 x_clear_image,
8730 NULL
8734 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8736 static int
8737 jpeg_image_p (object)
8738 Lisp_Object object;
8740 struct image_keyword fmt[JPEG_LAST];
8742 bcopy (jpeg_format, fmt, sizeof fmt);
8744 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
8745 || (fmt[JPEG_ASCENT].count
8746 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
8747 return 0;
8749 /* Must specify either the :data or :file keyword. */
8750 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8754 struct my_jpeg_error_mgr
8756 struct jpeg_error_mgr pub;
8757 jmp_buf setjmp_buffer;
8760 static void
8761 my_error_exit (cinfo)
8762 j_common_ptr cinfo;
8764 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8765 longjmp (mgr->setjmp_buffer, 1);
8768 /* Init source method for JPEG data source manager. Called by
8769 jpeg_read_header() before any data is actually read. See
8770 libjpeg.doc from the JPEG lib distribution. */
8772 static void
8773 our_init_source (cinfo)
8774 j_decompress_ptr cinfo;
8779 /* Fill input buffer method for JPEG data source manager. Called
8780 whenever more data is needed. We read the whole image in one step,
8781 so this only adds a fake end of input marker at the end. */
8783 static boolean
8784 our_fill_input_buffer (cinfo)
8785 j_decompress_ptr cinfo;
8787 /* Insert a fake EOI marker. */
8788 struct jpeg_source_mgr *src = cinfo->src;
8789 static JOCTET buffer[2];
8791 buffer[0] = (JOCTET) 0xFF;
8792 buffer[1] = (JOCTET) JPEG_EOI;
8794 src->next_input_byte = buffer;
8795 src->bytes_in_buffer = 2;
8796 return TRUE;
8800 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8801 is the JPEG data source manager. */
8803 static void
8804 our_skip_input_data (cinfo, num_bytes)
8805 j_decompress_ptr cinfo;
8806 long num_bytes;
8808 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
8810 if (src)
8812 if (num_bytes > src->bytes_in_buffer)
8813 ERREXIT (cinfo, JERR_INPUT_EOF);
8815 src->bytes_in_buffer -= num_bytes;
8816 src->next_input_byte += num_bytes;
8821 /* Method to terminate data source. Called by
8822 jpeg_finish_decompress() after all data has been processed. */
8824 static void
8825 our_term_source (cinfo)
8826 j_decompress_ptr cinfo;
8831 /* Set up the JPEG lib for reading an image from DATA which contains
8832 LEN bytes. CINFO is the decompression info structure created for
8833 reading the image. */
8835 static void
8836 jpeg_memory_src (cinfo, data, len)
8837 j_decompress_ptr cinfo;
8838 JOCTET *data;
8839 unsigned int len;
8841 struct jpeg_source_mgr *src;
8843 if (cinfo->src == NULL)
8845 /* First time for this JPEG object? */
8846 cinfo->src = (struct jpeg_source_mgr *)
8847 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
8848 sizeof (struct jpeg_source_mgr));
8849 src = (struct jpeg_source_mgr *) cinfo->src;
8850 src->next_input_byte = data;
8853 src = (struct jpeg_source_mgr *) cinfo->src;
8854 src->init_source = our_init_source;
8855 src->fill_input_buffer = our_fill_input_buffer;
8856 src->skip_input_data = our_skip_input_data;
8857 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
8858 src->term_source = our_term_source;
8859 src->bytes_in_buffer = len;
8860 src->next_input_byte = data;
8864 /* Load image IMG for use on frame F. Patterned after example.c
8865 from the JPEG lib. */
8867 static int
8868 jpeg_load (f, img)
8869 struct frame *f;
8870 struct image *img;
8872 struct jpeg_decompress_struct cinfo;
8873 struct my_jpeg_error_mgr mgr;
8874 Lisp_Object file, specified_file;
8875 Lisp_Object specified_data;
8876 FILE *fp = NULL;
8877 JSAMPARRAY buffer;
8878 int row_stride, x, y;
8879 XImage *ximg = NULL;
8880 int rc;
8881 unsigned long *colors;
8882 int width, height;
8883 struct gcpro gcpro1;
8885 /* Open the JPEG file. */
8886 specified_file = image_spec_value (img->spec, QCfile, NULL);
8887 specified_data = image_spec_value (img->spec, QCdata, NULL);
8888 file = Qnil;
8889 GCPRO1 (file);
8891 if (NILP (specified_data))
8893 file = x_find_image_file (specified_file);
8894 if (!STRINGP (file))
8896 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8897 UNGCPRO;
8898 return 0;
8901 fp = fopen (XSTRING (file)->data, "r");
8902 if (fp == NULL)
8904 image_error ("Cannot open `%s'", file, Qnil);
8905 UNGCPRO;
8906 return 0;
8910 /* Customize libjpeg's error handling to call my_error_exit when an
8911 error is detected. This function will perform a longjmp. */
8912 mgr.pub.error_exit = my_error_exit;
8913 cinfo.err = jpeg_std_error (&mgr.pub);
8915 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8917 if (rc == 1)
8919 /* Called from my_error_exit. Display a JPEG error. */
8920 char buffer[JMSG_LENGTH_MAX];
8921 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8922 image_error ("Error reading JPEG image `%s': %s", img->spec,
8923 build_string (buffer));
8926 /* Close the input file and destroy the JPEG object. */
8927 if (fp)
8928 fclose (fp);
8929 jpeg_destroy_decompress (&cinfo);
8931 BLOCK_INPUT;
8933 /* If we already have an XImage, free that. */
8934 x_destroy_x_image (ximg);
8936 /* Free pixmap and colors. */
8937 x_clear_image (f, img);
8939 UNBLOCK_INPUT;
8940 UNGCPRO;
8941 return 0;
8944 /* Create the JPEG decompression object. Let it read from fp.
8945 Read the JPEG image header. */
8946 jpeg_create_decompress (&cinfo);
8948 if (NILP (specified_data))
8949 jpeg_stdio_src (&cinfo, fp);
8950 else
8951 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
8952 STRING_BYTES (XSTRING (specified_data)));
8954 jpeg_read_header (&cinfo, TRUE);
8956 /* Customize decompression so that color quantization will be used.
8957 Start decompression. */
8958 cinfo.quantize_colors = TRUE;
8959 jpeg_start_decompress (&cinfo);
8960 width = img->width = cinfo.output_width;
8961 height = img->height = cinfo.output_height;
8963 BLOCK_INPUT;
8965 /* Create X image and pixmap. */
8966 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8968 UNBLOCK_INPUT;
8969 longjmp (mgr.setjmp_buffer, 2);
8972 /* Allocate colors. When color quantization is used,
8973 cinfo.actual_number_of_colors has been set with the number of
8974 colors generated, and cinfo.colormap is a two-dimensional array
8975 of color indices in the range 0..cinfo.actual_number_of_colors.
8976 No more than 255 colors will be generated. */
8978 int i, ir, ig, ib;
8980 if (cinfo.out_color_components > 2)
8981 ir = 0, ig = 1, ib = 2;
8982 else if (cinfo.out_color_components > 1)
8983 ir = 0, ig = 1, ib = 0;
8984 else
8985 ir = 0, ig = 0, ib = 0;
8987 /* Use the color table mechanism because it handles colors that
8988 cannot be allocated nicely. Such colors will be replaced with
8989 a default color, and we don't have to care about which colors
8990 can be freed safely, and which can't. */
8991 init_color_table ();
8992 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8993 * sizeof *colors);
8995 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8997 /* Multiply RGB values with 255 because X expects RGB values
8998 in the range 0..0xffff. */
8999 int r = cinfo.colormap[ir][i] << 8;
9000 int g = cinfo.colormap[ig][i] << 8;
9001 int b = cinfo.colormap[ib][i] << 8;
9002 colors[i] = lookup_rgb_color (f, r, g, b);
9005 /* Remember those colors actually allocated. */
9006 img->colors = colors_in_color_table (&img->ncolors);
9007 free_color_table ();
9010 /* Read pixels. */
9011 row_stride = width * cinfo.output_components;
9012 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9013 row_stride, 1);
9014 for (y = 0; y < height; ++y)
9016 jpeg_read_scanlines (&cinfo, buffer, 1);
9017 for (x = 0; x < cinfo.output_width; ++x)
9018 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9021 /* Clean up. */
9022 jpeg_finish_decompress (&cinfo);
9023 jpeg_destroy_decompress (&cinfo);
9024 if (fp)
9025 fclose (fp);
9027 /* Put the image into the pixmap. */
9028 x_put_x_image (f, ximg, img->pixmap, width, height);
9029 x_destroy_x_image (ximg);
9030 UNBLOCK_INPUT;
9031 UNGCPRO;
9032 return 1;
9035 #endif /* HAVE_JPEG */
9039 /***********************************************************************
9040 TIFF
9041 ***********************************************************************/
9043 #if HAVE_TIFF
9045 #include <tiffio.h>
9047 static int tiff_image_p P_ ((Lisp_Object object));
9048 static int tiff_load P_ ((struct frame *f, struct image *img));
9050 /* The symbol `tiff' identifying images of this type. */
9052 Lisp_Object Qtiff;
9054 /* Indices of image specification fields in tiff_format, below. */
9056 enum tiff_keyword_index
9058 TIFF_TYPE,
9059 TIFF_DATA,
9060 TIFF_FILE,
9061 TIFF_ASCENT,
9062 TIFF_MARGIN,
9063 TIFF_RELIEF,
9064 TIFF_ALGORITHM,
9065 TIFF_HEURISTIC_MASK,
9066 TIFF_LAST
9069 /* Vector of image_keyword structures describing the format
9070 of valid user-defined image specifications. */
9072 static struct image_keyword tiff_format[TIFF_LAST] =
9074 {":type", IMAGE_SYMBOL_VALUE, 1},
9075 {":data", IMAGE_STRING_VALUE, 0},
9076 {":file", IMAGE_STRING_VALUE, 0},
9077 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9078 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9079 {":relief", IMAGE_INTEGER_VALUE, 0},
9080 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9081 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9084 /* Structure describing the image type `tiff'. */
9086 static struct image_type tiff_type =
9088 &Qtiff,
9089 tiff_image_p,
9090 tiff_load,
9091 x_clear_image,
9092 NULL
9096 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9098 static int
9099 tiff_image_p (object)
9100 Lisp_Object object;
9102 struct image_keyword fmt[TIFF_LAST];
9103 bcopy (tiff_format, fmt, sizeof fmt);
9105 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
9106 || (fmt[TIFF_ASCENT].count
9107 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
9108 return 0;
9110 /* Must specify either the :data or :file keyword. */
9111 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9115 /* Reading from a memory buffer for TIFF images Based on the PNG
9116 memory source, but we have to provide a lot of extra functions.
9117 Blah.
9119 We really only need to implement read and seek, but I am not
9120 convinced that the TIFF library is smart enough not to destroy
9121 itself if we only hand it the function pointers we need to
9122 override. */
9124 typedef struct
9126 unsigned char *bytes;
9127 size_t len;
9128 int index;
9130 tiff_memory_source;
9132 static size_t
9133 tiff_read_from_memory (data, buf, size)
9134 thandle_t data;
9135 tdata_t buf;
9136 tsize_t size;
9138 tiff_memory_source *src = (tiff_memory_source *) data;
9140 if (size > src->len - src->index)
9141 return (size_t) -1;
9142 bcopy (src->bytes + src->index, buf, size);
9143 src->index += size;
9144 return size;
9147 static size_t
9148 tiff_write_from_memory (data, buf, size)
9149 thandle_t data;
9150 tdata_t buf;
9151 tsize_t size;
9153 return (size_t) -1;
9156 static toff_t
9157 tiff_seek_in_memory (data, off, whence)
9158 thandle_t data;
9159 toff_t off;
9160 int whence;
9162 tiff_memory_source *src = (tiff_memory_source *) data;
9163 int idx;
9165 switch (whence)
9167 case SEEK_SET: /* Go from beginning of source. */
9168 idx = off;
9169 break;
9171 case SEEK_END: /* Go from end of source. */
9172 idx = src->len + off;
9173 break;
9175 case SEEK_CUR: /* Go from current position. */
9176 idx = src->index + off;
9177 break;
9179 default: /* Invalid `whence'. */
9180 return -1;
9183 if (idx > src->len || idx < 0)
9184 return -1;
9186 src->index = idx;
9187 return src->index;
9190 static int
9191 tiff_close_memory (data)
9192 thandle_t data;
9194 /* NOOP */
9195 return 0;
9198 static int
9199 tiff_mmap_memory (data, pbase, psize)
9200 thandle_t data;
9201 tdata_t *pbase;
9202 toff_t *psize;
9204 /* It is already _IN_ memory. */
9205 return 0;
9208 static void
9209 tiff_unmap_memory (data, base, size)
9210 thandle_t data;
9211 tdata_t base;
9212 toff_t size;
9214 /* We don't need to do this. */
9217 static toff_t
9218 tiff_size_of_memory (data)
9219 thandle_t data;
9221 return ((tiff_memory_source *) data)->len;
9224 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9225 successful. */
9227 static int
9228 tiff_load (f, img)
9229 struct frame *f;
9230 struct image *img;
9232 Lisp_Object file, specified_file;
9233 Lisp_Object specified_data;
9234 TIFF *tiff;
9235 int width, height, x, y;
9236 uint32 *buf;
9237 int rc;
9238 XImage *ximg;
9239 struct gcpro gcpro1;
9240 tiff_memory_source memsrc;
9242 specified_file = image_spec_value (img->spec, QCfile, NULL);
9243 specified_data = image_spec_value (img->spec, QCdata, NULL);
9244 file = Qnil;
9245 GCPRO1 (file);
9247 if (NILP (specified_data))
9249 /* Read from a file */
9250 file = x_find_image_file (specified_file);
9251 if (!STRINGP (file))
9253 image_error ("Cannot find image file `%s'", file, Qnil);
9254 UNGCPRO;
9255 return 0;
9258 /* Try to open the image file. */
9259 tiff = TIFFOpen (XSTRING (file)->data, "r");
9260 if (tiff == NULL)
9262 image_error ("Cannot open `%s'", file, Qnil);
9263 UNGCPRO;
9264 return 0;
9267 else
9269 /* Memory source! */
9270 memsrc.bytes = XSTRING (specified_data)->data;
9271 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9272 memsrc.index = 0;
9274 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9275 (TIFFReadWriteProc) tiff_read_from_memory,
9276 (TIFFReadWriteProc) tiff_write_from_memory,
9277 tiff_seek_in_memory,
9278 tiff_close_memory,
9279 tiff_size_of_memory,
9280 tiff_mmap_memory,
9281 tiff_unmap_memory);
9283 if (!tiff)
9285 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9286 UNGCPRO;
9287 return 0;
9291 /* Get width and height of the image, and allocate a raster buffer
9292 of width x height 32-bit values. */
9293 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9294 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9295 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9297 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9298 TIFFClose (tiff);
9299 if (!rc)
9301 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9302 xfree (buf);
9303 UNGCPRO;
9304 return 0;
9307 BLOCK_INPUT;
9309 /* Create the X image and pixmap. */
9310 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9312 UNBLOCK_INPUT;
9313 xfree (buf);
9314 UNGCPRO;
9315 return 0;
9318 /* Initialize the color table. */
9319 init_color_table ();
9321 /* Process the pixel raster. Origin is in the lower-left corner. */
9322 for (y = 0; y < height; ++y)
9324 uint32 *row = buf + y * width;
9326 for (x = 0; x < width; ++x)
9328 uint32 abgr = row[x];
9329 int r = TIFFGetR (abgr) << 8;
9330 int g = TIFFGetG (abgr) << 8;
9331 int b = TIFFGetB (abgr) << 8;
9332 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9336 /* Remember the colors allocated for the image. Free the color table. */
9337 img->colors = colors_in_color_table (&img->ncolors);
9338 free_color_table ();
9340 /* Put the image into the pixmap, then free the X image and its buffer. */
9341 x_put_x_image (f, ximg, img->pixmap, width, height);
9342 x_destroy_x_image (ximg);
9343 xfree (buf);
9344 UNBLOCK_INPUT;
9346 img->width = width;
9347 img->height = height;
9349 UNGCPRO;
9350 return 1;
9353 #endif /* HAVE_TIFF != 0 */
9357 /***********************************************************************
9359 ***********************************************************************/
9361 #if HAVE_GIF
9363 #include <gif_lib.h>
9365 static int gif_image_p P_ ((Lisp_Object object));
9366 static int gif_load P_ ((struct frame *f, struct image *img));
9368 /* The symbol `gif' identifying images of this type. */
9370 Lisp_Object Qgif;
9372 /* Indices of image specification fields in gif_format, below. */
9374 enum gif_keyword_index
9376 GIF_TYPE,
9377 GIF_DATA,
9378 GIF_FILE,
9379 GIF_ASCENT,
9380 GIF_MARGIN,
9381 GIF_RELIEF,
9382 GIF_ALGORITHM,
9383 GIF_HEURISTIC_MASK,
9384 GIF_IMAGE,
9385 GIF_LAST
9388 /* Vector of image_keyword structures describing the format
9389 of valid user-defined image specifications. */
9391 static struct image_keyword gif_format[GIF_LAST] =
9393 {":type", IMAGE_SYMBOL_VALUE, 1},
9394 {":data", IMAGE_STRING_VALUE, 0},
9395 {":file", IMAGE_STRING_VALUE, 0},
9396 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9397 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9398 {":relief", IMAGE_INTEGER_VALUE, 0},
9399 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9400 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9401 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
9404 /* Structure describing the image type `gif'. */
9406 static struct image_type gif_type =
9408 &Qgif,
9409 gif_image_p,
9410 gif_load,
9411 x_clear_image,
9412 NULL
9415 /* Return non-zero if OBJECT is a valid GIF image specification. */
9417 static int
9418 gif_image_p (object)
9419 Lisp_Object object;
9421 struct image_keyword fmt[GIF_LAST];
9422 bcopy (gif_format, fmt, sizeof fmt);
9424 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
9425 || (fmt[GIF_ASCENT].count
9426 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
9427 return 0;
9429 /* Must specify either the :data or :file keyword. */
9430 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9433 /* Reading a GIF image from memory
9434 Based on the PNG memory stuff to a certain extent. */
9436 typedef struct
9438 unsigned char *bytes;
9439 size_t len;
9440 int index;
9442 gif_memory_source;
9444 /* Make the current memory source available to gif_read_from_memory.
9445 It's done this way because not all versions of libungif support
9446 a UserData field in the GifFileType structure. */
9447 static gif_memory_source *current_gif_memory_src;
9449 static int
9450 gif_read_from_memory (file, buf, len)
9451 GifFileType *file;
9452 GifByteType *buf;
9453 int len;
9455 gif_memory_source *src = current_gif_memory_src;
9457 if (len > src->len - src->index)
9458 return -1;
9460 bcopy (src->bytes + src->index, buf, len);
9461 src->index += len;
9462 return len;
9466 /* Load GIF image IMG for use on frame F. Value is non-zero if
9467 successful. */
9469 static int
9470 gif_load (f, img)
9471 struct frame *f;
9472 struct image *img;
9474 Lisp_Object file, specified_file;
9475 Lisp_Object specified_data;
9476 int rc, width, height, x, y, i;
9477 XImage *ximg;
9478 ColorMapObject *gif_color_map;
9479 unsigned long pixel_colors[256];
9480 GifFileType *gif;
9481 struct gcpro gcpro1;
9482 Lisp_Object image;
9483 int ino, image_left, image_top, image_width, image_height;
9484 gif_memory_source memsrc;
9485 unsigned char *raster;
9487 specified_file = image_spec_value (img->spec, QCfile, NULL);
9488 specified_data = image_spec_value (img->spec, QCdata, NULL);
9489 file = Qnil;
9490 GCPRO1 (file);
9492 if (NILP (specified_data))
9494 file = x_find_image_file (specified_file);
9495 if (!STRINGP (file))
9497 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9498 UNGCPRO;
9499 return 0;
9502 /* Open the GIF file. */
9503 gif = DGifOpenFileName (XSTRING (file)->data);
9504 if (gif == NULL)
9506 image_error ("Cannot open `%s'", file, Qnil);
9507 UNGCPRO;
9508 return 0;
9511 else
9513 /* Read from memory! */
9514 current_gif_memory_src = &memsrc;
9515 memsrc.bytes = XSTRING (specified_data)->data;
9516 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9517 memsrc.index = 0;
9519 gif = DGifOpen(&memsrc, gif_read_from_memory);
9520 if (!gif)
9522 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
9523 UNGCPRO;
9524 return 0;
9528 /* Read entire contents. */
9529 rc = DGifSlurp (gif);
9530 if (rc == GIF_ERROR)
9532 image_error ("Error reading `%s'", img->spec, Qnil);
9533 DGifCloseFile (gif);
9534 UNGCPRO;
9535 return 0;
9538 image = image_spec_value (img->spec, QCindex, NULL);
9539 ino = INTEGERP (image) ? XFASTINT (image) : 0;
9540 if (ino >= gif->ImageCount)
9542 image_error ("Invalid image number `%s' in image `%s'",
9543 image, img->spec);
9544 DGifCloseFile (gif);
9545 UNGCPRO;
9546 return 0;
9549 width = img->width = gif->SWidth;
9550 height = img->height = gif->SHeight;
9552 BLOCK_INPUT;
9554 /* Create the X image and pixmap. */
9555 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9557 UNBLOCK_INPUT;
9558 DGifCloseFile (gif);
9559 UNGCPRO;
9560 return 0;
9563 /* Allocate colors. */
9564 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
9565 if (!gif_color_map)
9566 gif_color_map = gif->SColorMap;
9567 init_color_table ();
9568 bzero (pixel_colors, sizeof pixel_colors);
9570 for (i = 0; i < gif_color_map->ColorCount; ++i)
9572 int r = gif_color_map->Colors[i].Red << 8;
9573 int g = gif_color_map->Colors[i].Green << 8;
9574 int b = gif_color_map->Colors[i].Blue << 8;
9575 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9578 img->colors = colors_in_color_table (&img->ncolors);
9579 free_color_table ();
9581 /* Clear the part of the screen image that are not covered by
9582 the image from the GIF file. Full animated GIF support
9583 requires more than can be done here (see the gif89 spec,
9584 disposal methods). Let's simply assume that the part
9585 not covered by a sub-image is in the frame's background color. */
9586 image_top = gif->SavedImages[ino].ImageDesc.Top;
9587 image_left = gif->SavedImages[ino].ImageDesc.Left;
9588 image_width = gif->SavedImages[ino].ImageDesc.Width;
9589 image_height = gif->SavedImages[ino].ImageDesc.Height;
9591 for (y = 0; y < image_top; ++y)
9592 for (x = 0; x < width; ++x)
9593 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9595 for (y = image_top + image_height; y < height; ++y)
9596 for (x = 0; x < width; ++x)
9597 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9599 for (y = image_top; y < image_top + image_height; ++y)
9601 for (x = 0; x < image_left; ++x)
9602 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9603 for (x = image_left + image_width; x < width; ++x)
9604 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9607 /* Read the GIF image into the X image. We use a local variable
9608 `raster' here because RasterBits below is a char *, and invites
9609 problems with bytes >= 0x80. */
9610 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9612 if (gif->SavedImages[ino].ImageDesc.Interlace)
9614 static int interlace_start[] = {0, 4, 2, 1};
9615 static int interlace_increment[] = {8, 8, 4, 2};
9616 int pass, inc;
9617 int row = interlace_start[0];
9619 pass = 0;
9621 for (y = 0; y < image_height; y++)
9623 if (row >= image_height)
9625 row = interlace_start[++pass];
9626 while (row >= image_height)
9627 row = interlace_start[++pass];
9630 for (x = 0; x < image_width; x++)
9632 int i = raster[(y * image_width) + x];
9633 XPutPixel (ximg, x + image_left, row + image_top,
9634 pixel_colors[i]);
9637 row += interlace_increment[pass];
9640 else
9642 for (y = 0; y < image_height; ++y)
9643 for (x = 0; x < image_width; ++x)
9645 int i = raster[y * image_width + x];
9646 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9650 DGifCloseFile (gif);
9652 /* Put the image into the pixmap, then free the X image and its buffer. */
9653 x_put_x_image (f, ximg, img->pixmap, width, height);
9654 x_destroy_x_image (ximg);
9655 UNBLOCK_INPUT;
9657 UNGCPRO;
9658 return 1;
9661 #endif /* HAVE_GIF != 0 */
9665 /***********************************************************************
9666 Ghostscript
9667 ***********************************************************************/
9669 static int gs_image_p P_ ((Lisp_Object object));
9670 static int gs_load P_ ((struct frame *f, struct image *img));
9671 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9673 /* The symbol `postscript' identifying images of this type. */
9675 Lisp_Object Qpostscript;
9677 /* Keyword symbols. */
9679 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9681 /* Indices of image specification fields in gs_format, below. */
9683 enum gs_keyword_index
9685 GS_TYPE,
9686 GS_PT_WIDTH,
9687 GS_PT_HEIGHT,
9688 GS_FILE,
9689 GS_LOADER,
9690 GS_BOUNDING_BOX,
9691 GS_ASCENT,
9692 GS_MARGIN,
9693 GS_RELIEF,
9694 GS_ALGORITHM,
9695 GS_HEURISTIC_MASK,
9696 GS_LAST
9699 /* Vector of image_keyword structures describing the format
9700 of valid user-defined image specifications. */
9702 static struct image_keyword gs_format[GS_LAST] =
9704 {":type", IMAGE_SYMBOL_VALUE, 1},
9705 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9706 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9707 {":file", IMAGE_STRING_VALUE, 1},
9708 {":loader", IMAGE_FUNCTION_VALUE, 0},
9709 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9710 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9711 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9712 {":relief", IMAGE_INTEGER_VALUE, 0},
9713 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9714 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9717 /* Structure describing the image type `ghostscript'. */
9719 static struct image_type gs_type =
9721 &Qpostscript,
9722 gs_image_p,
9723 gs_load,
9724 gs_clear_image,
9725 NULL
9729 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9731 static void
9732 gs_clear_image (f, img)
9733 struct frame *f;
9734 struct image *img;
9736 /* IMG->data.ptr_val may contain a recorded colormap. */
9737 xfree (img->data.ptr_val);
9738 x_clear_image (f, img);
9742 /* Return non-zero if OBJECT is a valid Ghostscript image
9743 specification. */
9745 static int
9746 gs_image_p (object)
9747 Lisp_Object object;
9749 struct image_keyword fmt[GS_LAST];
9750 Lisp_Object tem;
9751 int i;
9753 bcopy (gs_format, fmt, sizeof fmt);
9755 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
9756 || (fmt[GS_ASCENT].count
9757 && XFASTINT (fmt[GS_ASCENT].value) > 100))
9758 return 0;
9760 /* Bounding box must be a list or vector containing 4 integers. */
9761 tem = fmt[GS_BOUNDING_BOX].value;
9762 if (CONSP (tem))
9764 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9765 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9766 return 0;
9767 if (!NILP (tem))
9768 return 0;
9770 else if (VECTORP (tem))
9772 if (XVECTOR (tem)->size != 4)
9773 return 0;
9774 for (i = 0; i < 4; ++i)
9775 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9776 return 0;
9778 else
9779 return 0;
9781 return 1;
9785 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9786 if successful. */
9788 static int
9789 gs_load (f, img)
9790 struct frame *f;
9791 struct image *img;
9793 char buffer[100];
9794 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9795 struct gcpro gcpro1, gcpro2;
9796 Lisp_Object frame;
9797 double in_width, in_height;
9798 Lisp_Object pixel_colors = Qnil;
9800 /* Compute pixel size of pixmap needed from the given size in the
9801 image specification. Sizes in the specification are in pt. 1 pt
9802 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9803 info. */
9804 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9805 in_width = XFASTINT (pt_width) / 72.0;
9806 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9807 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9808 in_height = XFASTINT (pt_height) / 72.0;
9809 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9811 /* Create the pixmap. */
9812 BLOCK_INPUT;
9813 xassert (img->pixmap == 0);
9814 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9815 img->width, img->height,
9816 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9817 UNBLOCK_INPUT;
9819 if (!img->pixmap)
9821 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9822 return 0;
9825 /* Call the loader to fill the pixmap. It returns a process object
9826 if successful. We do not record_unwind_protect here because
9827 other places in redisplay like calling window scroll functions
9828 don't either. Let the Lisp loader use `unwind-protect' instead. */
9829 GCPRO2 (window_and_pixmap_id, pixel_colors);
9831 sprintf (buffer, "%lu %lu",
9832 (unsigned long) FRAME_X_WINDOW (f),
9833 (unsigned long) img->pixmap);
9834 window_and_pixmap_id = build_string (buffer);
9836 sprintf (buffer, "%lu %lu",
9837 FRAME_FOREGROUND_PIXEL (f),
9838 FRAME_BACKGROUND_PIXEL (f));
9839 pixel_colors = build_string (buffer);
9841 XSETFRAME (frame, f);
9842 loader = image_spec_value (img->spec, QCloader, NULL);
9843 if (NILP (loader))
9844 loader = intern ("gs-load-image");
9846 img->data.lisp_val = call6 (loader, frame, img->spec,
9847 make_number (img->width),
9848 make_number (img->height),
9849 window_and_pixmap_id,
9850 pixel_colors);
9851 UNGCPRO;
9852 return PROCESSP (img->data.lisp_val);
9856 /* Kill the Ghostscript process that was started to fill PIXMAP on
9857 frame F. Called from XTread_socket when receiving an event
9858 telling Emacs that Ghostscript has finished drawing. */
9860 void
9861 x_kill_gs_process (pixmap, f)
9862 Pixmap pixmap;
9863 struct frame *f;
9865 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9866 int class, i;
9867 struct image *img;
9869 /* Find the image containing PIXMAP. */
9870 for (i = 0; i < c->used; ++i)
9871 if (c->images[i]->pixmap == pixmap)
9872 break;
9874 /* Kill the GS process. We should have found PIXMAP in the image
9875 cache and its image should contain a process object. */
9876 xassert (i < c->used);
9877 img = c->images[i];
9878 xassert (PROCESSP (img->data.lisp_val));
9879 Fkill_process (img->data.lisp_val, Qnil);
9880 img->data.lisp_val = Qnil;
9882 /* On displays with a mutable colormap, figure out the colors
9883 allocated for the image by looking at the pixels of an XImage for
9884 img->pixmap. */
9885 class = FRAME_X_DISPLAY_INFO (f)->visual->class;
9886 if (class != StaticColor && class != StaticGray && class != TrueColor)
9888 XImage *ximg;
9890 BLOCK_INPUT;
9892 /* Try to get an XImage for img->pixmep. */
9893 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9894 0, 0, img->width, img->height, ~0, ZPixmap);
9895 if (ximg)
9897 int x, y;
9899 /* Initialize the color table. */
9900 init_color_table ();
9902 /* For each pixel of the image, look its color up in the
9903 color table. After having done so, the color table will
9904 contain an entry for each color used by the image. */
9905 for (y = 0; y < img->height; ++y)
9906 for (x = 0; x < img->width; ++x)
9908 unsigned long pixel = XGetPixel (ximg, x, y);
9909 lookup_pixel_color (f, pixel);
9912 /* Record colors in the image. Free color table and XImage. */
9913 img->colors = colors_in_color_table (&img->ncolors);
9914 free_color_table ();
9915 XDestroyImage (ximg);
9917 #if 0 /* This doesn't seem to be the case. If we free the colors
9918 here, we get a BadAccess later in x_clear_image when
9919 freeing the colors. */
9920 /* We have allocated colors once, but Ghostscript has also
9921 allocated colors on behalf of us. So, to get the
9922 reference counts right, free them once. */
9923 if (img->ncolors)
9925 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
9926 XFreeColors (FRAME_X_DISPLAY (f), cmap,
9927 img->colors, img->ncolors, 0);
9929 #endif
9931 else
9932 image_error ("Cannot get X image of `%s'; colors will not be freed",
9933 img->spec, Qnil);
9935 UNBLOCK_INPUT;
9941 /***********************************************************************
9942 Window properties
9943 ***********************************************************************/
9945 DEFUN ("x-change-window-property", Fx_change_window_property,
9946 Sx_change_window_property, 2, 3, 0,
9947 "Change window property PROP to VALUE on the X window of FRAME.\n\
9948 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9949 selected frame. Value is VALUE.")
9950 (prop, value, frame)
9951 Lisp_Object frame, prop, value;
9953 struct frame *f = check_x_frame (frame);
9954 Atom prop_atom;
9956 CHECK_STRING (prop, 1);
9957 CHECK_STRING (value, 2);
9959 BLOCK_INPUT;
9960 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9961 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9962 prop_atom, XA_STRING, 8, PropModeReplace,
9963 XSTRING (value)->data, XSTRING (value)->size);
9965 /* Make sure the property is set when we return. */
9966 XFlush (FRAME_X_DISPLAY (f));
9967 UNBLOCK_INPUT;
9969 return value;
9973 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9974 Sx_delete_window_property, 1, 2, 0,
9975 "Remove window property PROP from X window of FRAME.\n\
9976 FRAME nil or omitted means use the selected frame. Value is PROP.")
9977 (prop, frame)
9978 Lisp_Object prop, frame;
9980 struct frame *f = check_x_frame (frame);
9981 Atom prop_atom;
9983 CHECK_STRING (prop, 1);
9984 BLOCK_INPUT;
9985 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9986 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9988 /* Make sure the property is removed when we return. */
9989 XFlush (FRAME_X_DISPLAY (f));
9990 UNBLOCK_INPUT;
9992 return prop;
9996 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9997 1, 2, 0,
9998 "Value is the value of window property PROP on FRAME.\n\
9999 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
10000 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10001 value.")
10002 (prop, frame)
10003 Lisp_Object prop, frame;
10005 struct frame *f = check_x_frame (frame);
10006 Atom prop_atom;
10007 int rc;
10008 Lisp_Object prop_value = Qnil;
10009 char *tmp_data = NULL;
10010 Atom actual_type;
10011 int actual_format;
10012 unsigned long actual_size, bytes_remaining;
10014 CHECK_STRING (prop, 1);
10015 BLOCK_INPUT;
10016 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10017 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10018 prop_atom, 0, 0, False, XA_STRING,
10019 &actual_type, &actual_format, &actual_size,
10020 &bytes_remaining, (unsigned char **) &tmp_data);
10021 if (rc == Success)
10023 int size = bytes_remaining;
10025 XFree (tmp_data);
10026 tmp_data = NULL;
10028 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10029 prop_atom, 0, bytes_remaining,
10030 False, XA_STRING,
10031 &actual_type, &actual_format,
10032 &actual_size, &bytes_remaining,
10033 (unsigned char **) &tmp_data);
10034 if (rc == Success)
10035 prop_value = make_string (tmp_data, size);
10037 XFree (tmp_data);
10040 UNBLOCK_INPUT;
10041 return prop_value;
10046 /***********************************************************************
10047 Busy cursor
10048 ***********************************************************************/
10050 /* The implementation partly follows a patch from
10051 F.Pierresteguy@frcl.bull.fr dated 1994. */
10053 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor display until
10054 the next X event is read and we enter XTread_socket again. Setting
10055 it to 1 inhibits busy-cursor display for direct commands. */
10057 int inhibit_busy_cursor;
10059 /* Incremented with each call to x-display-busy-cursor.
10060 Decremented in x-undisplay-busy-cursor. */
10062 static int busy_count;
10065 DEFUN ("x-show-busy-cursor", Fx_show_busy_cursor,
10066 Sx_show_busy_cursor, 0, 0, 0,
10067 "Show a busy cursor, if not already shown.\n\
10068 Each call to this function must be matched by a call to\n\
10069 `x-hide-busy-cursor' to make the busy pointer disappear again.")
10072 ++busy_count;
10073 if (busy_count == 1)
10075 Lisp_Object rest, frame;
10077 FOR_EACH_FRAME (rest, frame)
10078 if (FRAME_X_P (XFRAME (frame)))
10080 struct frame *f = XFRAME (frame);
10082 BLOCK_INPUT;
10083 f->output_data.x->busy_p = 1;
10085 if (!f->output_data.x->busy_window)
10087 unsigned long mask = CWCursor;
10088 XSetWindowAttributes attrs;
10090 attrs.cursor = f->output_data.x->busy_cursor;
10092 f->output_data.x->busy_window
10093 = XCreateWindow (FRAME_X_DISPLAY (f),
10094 FRAME_OUTER_WINDOW (f),
10095 0, 0, 32000, 32000, 0, 0,
10096 InputOnly,
10097 CopyFromParent,
10098 mask, &attrs);
10101 XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
10102 UNBLOCK_INPUT;
10106 return Qnil;
10110 DEFUN ("x-hide-busy-cursor", Fx_hide_busy_cursor,
10111 Sx_hide_busy_cursor, 0, 1, 0,
10112 "Hide a busy-cursor.\n\
10113 A busy-cursor will actually be undisplayed when a matching\n\
10114 `x-hide-busy-cursor' is called for each `x-show-busy-cursor'\n\
10115 issued. FORCE non-nil means hide the busy-cursor forcibly,\n\
10116 not counting calls.")
10117 (force)
10118 Lisp_Object force;
10120 Lisp_Object rest, frame;
10122 if (busy_count == 0)
10123 return Qnil;
10125 if (!NILP (force) && busy_count != 0)
10126 busy_count = 1;
10128 --busy_count;
10129 if (busy_count != 0)
10130 return Qnil;
10132 FOR_EACH_FRAME (rest, frame)
10134 struct frame *f = XFRAME (frame);
10136 if (FRAME_X_P (f)
10137 /* Watch out for newly created frames. */
10138 && f->output_data.x->busy_window)
10141 BLOCK_INPUT;
10142 XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
10143 /* Sync here because XTread_socket looks at the busy_p flag
10144 that is reset to zero below. */
10145 XSync (FRAME_X_DISPLAY (f), False);
10146 UNBLOCK_INPUT;
10147 f->output_data.x->busy_p = 0;
10151 return Qnil;
10156 /***********************************************************************
10157 Tool tips
10158 ***********************************************************************/
10160 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10161 Lisp_Object));
10163 /* The frame of a currently visible tooltip, or null. */
10165 struct frame *tip_frame;
10167 /* If non-nil, a timer started that hides the last tooltip when it
10168 fires. */
10170 Lisp_Object tip_timer;
10171 Window tip_window;
10173 /* Create a frame for a tooltip on the display described by DPYINFO.
10174 PARMS is a list of frame parameters. Value is the frame. */
10176 static Lisp_Object
10177 x_create_tip_frame (dpyinfo, parms)
10178 struct x_display_info *dpyinfo;
10179 Lisp_Object parms;
10181 struct frame *f;
10182 Lisp_Object frame, tem;
10183 Lisp_Object name;
10184 long window_prompting = 0;
10185 int width, height;
10186 int count = specpdl_ptr - specpdl;
10187 struct gcpro gcpro1, gcpro2, gcpro3;
10188 struct kboard *kb;
10190 check_x ();
10192 /* Use this general default value to start with until we know if
10193 this frame has a specified name. */
10194 Vx_resource_name = Vinvocation_name;
10196 #ifdef MULTI_KBOARD
10197 kb = dpyinfo->kboard;
10198 #else
10199 kb = &the_only_kboard;
10200 #endif
10202 /* Get the name of the frame to use for resource lookup. */
10203 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10204 if (!STRINGP (name)
10205 && !EQ (name, Qunbound)
10206 && !NILP (name))
10207 error ("Invalid frame name--not a string or nil");
10208 Vx_resource_name = name;
10210 frame = Qnil;
10211 GCPRO3 (parms, name, frame);
10212 tip_frame = f = make_frame (1);
10213 XSETFRAME (frame, f);
10214 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10216 f->output_method = output_x_window;
10217 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10218 bzero (f->output_data.x, sizeof (struct x_output));
10219 f->output_data.x->icon_bitmap = -1;
10220 f->output_data.x->fontset = -1;
10221 f->icon_name = Qnil;
10222 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10223 #ifdef MULTI_KBOARD
10224 FRAME_KBOARD (f) = kb;
10225 #endif
10226 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10227 f->output_data.x->explicit_parent = 0;
10229 /* Set the name; the functions to which we pass f expect the name to
10230 be set. */
10231 if (EQ (name, Qunbound) || NILP (name))
10233 f->name = build_string (dpyinfo->x_id_name);
10234 f->explicit_name = 0;
10236 else
10238 f->name = name;
10239 f->explicit_name = 1;
10240 /* use the frame's title when getting resources for this frame. */
10241 specbind (Qx_resource_name, name);
10244 /* Create fontsets from `global_fontset_alist' before handling fonts. */
10245 for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
10246 fs_register_fontset (f, XCAR (tem));
10248 /* Extract the window parameters from the supplied values
10249 that are needed to determine window geometry. */
10251 Lisp_Object font;
10253 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
10255 BLOCK_INPUT;
10256 /* First, try whatever font the caller has specified. */
10257 if (STRINGP (font))
10259 tem = Fquery_fontset (font, Qnil);
10260 if (STRINGP (tem))
10261 font = x_new_fontset (f, XSTRING (tem)->data);
10262 else
10263 font = x_new_font (f, XSTRING (font)->data);
10266 /* Try out a font which we hope has bold and italic variations. */
10267 if (!STRINGP (font))
10268 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10269 if (!STRINGP (font))
10270 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10271 if (! STRINGP (font))
10272 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10273 if (! STRINGP (font))
10274 /* This was formerly the first thing tried, but it finds too many fonts
10275 and takes too long. */
10276 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10277 /* If those didn't work, look for something which will at least work. */
10278 if (! STRINGP (font))
10279 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10280 UNBLOCK_INPUT;
10281 if (! STRINGP (font))
10282 font = build_string ("fixed");
10284 x_default_parameter (f, parms, Qfont, font,
10285 "font", "Font", RES_TYPE_STRING);
10288 x_default_parameter (f, parms, Qborder_width, make_number (2),
10289 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
10291 /* This defaults to 2 in order to match xterm. We recognize either
10292 internalBorderWidth or internalBorder (which is what xterm calls
10293 it). */
10294 if (NILP (Fassq (Qinternal_border_width, parms)))
10296 Lisp_Object value;
10298 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
10299 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
10300 if (! EQ (value, Qunbound))
10301 parms = Fcons (Fcons (Qinternal_border_width, value),
10302 parms);
10305 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
10306 "internalBorderWidth", "internalBorderWidth",
10307 RES_TYPE_NUMBER);
10309 /* Also do the stuff which must be set before the window exists. */
10310 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
10311 "foreground", "Foreground", RES_TYPE_STRING);
10312 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
10313 "background", "Background", RES_TYPE_STRING);
10314 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
10315 "pointerColor", "Foreground", RES_TYPE_STRING);
10316 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
10317 "cursorColor", "Foreground", RES_TYPE_STRING);
10318 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
10319 "borderColor", "BorderColor", RES_TYPE_STRING);
10321 /* Init faces before x_default_parameter is called for scroll-bar
10322 parameters because that function calls x_set_scroll_bar_width,
10323 which calls change_frame_size, which calls Fset_window_buffer,
10324 which runs hooks, which call Fvertical_motion. At the end, we
10325 end up in init_iterator with a null face cache, which should not
10326 happen. */
10327 init_frame_faces (f);
10329 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10330 window_prompting = x_figure_window_size (f, parms);
10332 if (window_prompting & XNegative)
10334 if (window_prompting & YNegative)
10335 f->output_data.x->win_gravity = SouthEastGravity;
10336 else
10337 f->output_data.x->win_gravity = NorthEastGravity;
10339 else
10341 if (window_prompting & YNegative)
10342 f->output_data.x->win_gravity = SouthWestGravity;
10343 else
10344 f->output_data.x->win_gravity = NorthWestGravity;
10347 f->output_data.x->size_hint_flags = window_prompting;
10349 XSetWindowAttributes attrs;
10350 unsigned long mask;
10352 BLOCK_INPUT;
10353 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
10354 /* Window managers looks at the override-redirect flag to
10355 determine whether or net to give windows a decoration (Xlib
10356 3.2.8). */
10357 attrs.override_redirect = True;
10358 attrs.save_under = True;
10359 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
10360 /* Arrange for getting MapNotify and UnmapNotify events. */
10361 attrs.event_mask = StructureNotifyMask;
10362 tip_window
10363 = FRAME_X_WINDOW (f)
10364 = XCreateWindow (FRAME_X_DISPLAY (f),
10365 FRAME_X_DISPLAY_INFO (f)->root_window,
10366 /* x, y, width, height */
10367 0, 0, 1, 1,
10368 /* Border. */
10370 CopyFromParent, InputOutput, CopyFromParent,
10371 mask, &attrs);
10372 UNBLOCK_INPUT;
10375 x_make_gc (f);
10377 x_default_parameter (f, parms, Qauto_raise, Qnil,
10378 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10379 x_default_parameter (f, parms, Qauto_lower, Qnil,
10380 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10381 x_default_parameter (f, parms, Qcursor_type, Qbox,
10382 "cursorType", "CursorType", RES_TYPE_SYMBOL);
10384 /* Dimensions, especially f->height, must be done via change_frame_size.
10385 Change will not be effected unless different from the current
10386 f->height. */
10387 width = f->width;
10388 height = f->height;
10389 f->height = 0;
10390 SET_FRAME_WIDTH (f, 0);
10391 change_frame_size (f, height, width, 1, 0, 0);
10393 f->no_split = 1;
10395 UNGCPRO;
10397 /* It is now ok to make the frame official even if we get an error
10398 below. And the frame needs to be on Vframe_list or making it
10399 visible won't work. */
10400 Vframe_list = Fcons (frame, Vframe_list);
10402 /* Now that the frame is official, it counts as a reference to
10403 its display. */
10404 FRAME_X_DISPLAY_INFO (f)->reference_count++;
10406 return unbind_to (count, frame);
10410 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 4, 0,
10411 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10412 A tooltip window is a small X window displaying STRING at\n\
10413 the current mouse position.\n\
10414 FRAME nil or omitted means use the selected frame.\n\
10415 PARMS is an optional list of frame parameters which can be\n\
10416 used to change the tooltip's appearance.\n\
10417 Automatically hide the tooltip after TIMEOUT seconds.\n\
10418 TIMEOUT nil means use the default timeout of 5 seconds.")
10419 (string, frame, parms, timeout)
10420 Lisp_Object string, frame, parms, timeout;
10422 struct frame *f;
10423 struct window *w;
10424 Window root, child;
10425 Lisp_Object buffer;
10426 struct buffer *old_buffer;
10427 struct text_pos pos;
10428 int i, width, height;
10429 int root_x, root_y, win_x, win_y;
10430 unsigned pmask;
10431 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10432 int old_windows_or_buffers_changed = windows_or_buffers_changed;
10433 int count = specpdl_ptr - specpdl;
10435 specbind (Qinhibit_redisplay, Qt);
10437 GCPRO4 (string, parms, frame, timeout);
10439 CHECK_STRING (string, 0);
10440 f = check_x_frame (frame);
10441 if (NILP (timeout))
10442 timeout = make_number (5);
10443 else
10444 CHECK_NATNUM (timeout, 2);
10446 /* Hide a previous tip, if any. */
10447 Fx_hide_tip ();
10449 /* Add default values to frame parameters. */
10450 if (NILP (Fassq (Qname, parms)))
10451 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10452 if (NILP (Fassq (Qinternal_border_width, parms)))
10453 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10454 if (NILP (Fassq (Qborder_width, parms)))
10455 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10456 if (NILP (Fassq (Qborder_color, parms)))
10457 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
10458 if (NILP (Fassq (Qbackground_color, parms)))
10459 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
10460 parms);
10462 /* Create a frame for the tooltip, and record it in the global
10463 variable tip_frame. */
10464 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
10465 tip_frame = f = XFRAME (frame);
10467 /* Set up the frame's root window. Currently we use a size of 80
10468 columns x 40 lines. If someone wants to show a larger tip, he
10469 will loose. I don't think this is a realistic case. */
10470 w = XWINDOW (FRAME_ROOT_WINDOW (f));
10471 w->left = w->top = make_number (0);
10472 w->width = 80;
10473 w->height = 40;
10474 adjust_glyphs (f);
10475 w->pseudo_window_p = 1;
10477 /* Display the tooltip text in a temporary buffer. */
10478 buffer = Fget_buffer_create (build_string (" *tip*"));
10479 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10480 old_buffer = current_buffer;
10481 set_buffer_internal_1 (XBUFFER (buffer));
10482 Ferase_buffer ();
10483 Finsert (make_number (1), &string);
10484 clear_glyph_matrix (w->desired_matrix);
10485 clear_glyph_matrix (w->current_matrix);
10486 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
10487 try_window (FRAME_ROOT_WINDOW (f), pos);
10489 /* Compute width and height of the tooltip. */
10490 width = height = 0;
10491 for (i = 0; i < w->desired_matrix->nrows; ++i)
10493 struct glyph_row *row = &w->desired_matrix->rows[i];
10494 struct glyph *last;
10495 int row_width;
10497 /* Stop at the first empty row at the end. */
10498 if (!row->enabled_p || !row->displays_text_p)
10499 break;
10501 /* Let the row go over the full width of the frame. */
10502 row->full_width_p = 1;
10504 /* There's a glyph at the end of rows that is use to place
10505 the cursor there. Don't include the width of this glyph. */
10506 if (row->used[TEXT_AREA])
10508 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
10509 row_width = row->pixel_width - last->pixel_width;
10511 else
10512 row_width = row->pixel_width;
10514 height += row->height;
10515 width = max (width, row_width);
10518 /* Add the frame's internal border to the width and height the X
10519 window should have. */
10520 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10521 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10523 /* Move the tooltip window where the mouse pointer is. Resize and
10524 show it. */
10525 BLOCK_INPUT;
10526 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10527 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
10528 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10529 root_x + 5, root_y - height - 5, width, height);
10530 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10531 UNBLOCK_INPUT;
10533 /* Draw into the window. */
10534 w->must_be_updated_p = 1;
10535 update_single_window (w, 1);
10537 /* Restore original current buffer. */
10538 set_buffer_internal_1 (old_buffer);
10539 windows_or_buffers_changed = old_windows_or_buffers_changed;
10541 /* Let the tip disappear after timeout seconds. */
10542 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
10543 intern ("x-hide-tip"));
10545 UNGCPRO;
10546 return unbind_to (count, Qnil);
10550 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
10551 "Hide the current tooltip window, if there is any.\n\
10552 Value is t is tooltip was open, nil otherwise.")
10555 int count = specpdl_ptr - specpdl;
10556 int deleted_p = 0;
10558 specbind (Qinhibit_redisplay, Qt);
10560 if (!NILP (tip_timer))
10562 call1 (intern ("cancel-timer"), tip_timer);
10563 tip_timer = Qnil;
10566 if (tip_frame)
10568 Lisp_Object frame;
10570 XSETFRAME (frame, tip_frame);
10571 Fdelete_frame (frame, Qt);
10572 tip_frame = NULL;
10573 deleted_p = 1;
10576 return unbind_to (count, deleted_p ? Qt : Qnil);
10581 /***********************************************************************
10582 File selection dialog
10583 ***********************************************************************/
10585 #ifdef USE_MOTIF
10587 /* Callback for "OK" and "Cancel" on file selection dialog. */
10589 static void
10590 file_dialog_cb (widget, client_data, call_data)
10591 Widget widget;
10592 XtPointer call_data, client_data;
10594 int *result = (int *) client_data;
10595 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
10596 *result = cb->reason;
10600 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10601 "Read file name, prompting with PROMPT in directory DIR.\n\
10602 Use a file selection dialog.\n\
10603 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10604 specified. Don't let the user enter a file name in the file\n\
10605 selection dialog's entry field, if MUSTMATCH is non-nil.")
10606 (prompt, dir, default_filename, mustmatch)
10607 Lisp_Object prompt, dir, default_filename, mustmatch;
10609 int result;
10610 struct frame *f = SELECTED_FRAME ();
10611 Lisp_Object file = Qnil;
10612 Widget dialog, text, list, help;
10613 Arg al[10];
10614 int ac = 0;
10615 extern XtAppContext Xt_app_con;
10616 char *title;
10617 XmString dir_xmstring, pattern_xmstring;
10618 int popup_activated_flag;
10619 int count = specpdl_ptr - specpdl;
10620 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10622 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10623 CHECK_STRING (prompt, 0);
10624 CHECK_STRING (dir, 1);
10626 /* Prevent redisplay. */
10627 specbind (Qinhibit_redisplay, Qt);
10629 BLOCK_INPUT;
10631 /* Create the dialog with PROMPT as title, using DIR as initial
10632 directory and using "*" as pattern. */
10633 dir = Fexpand_file_name (dir, Qnil);
10634 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
10635 pattern_xmstring = XmStringCreateLocalized ("*");
10637 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
10638 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
10639 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
10640 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
10641 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
10642 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
10643 "fsb", al, ac);
10644 XmStringFree (dir_xmstring);
10645 XmStringFree (pattern_xmstring);
10647 /* Add callbacks for OK and Cancel. */
10648 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
10649 (XtPointer) &result);
10650 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
10651 (XtPointer) &result);
10653 /* Disable the help button since we can't display help. */
10654 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
10655 XtSetSensitive (help, False);
10657 /* Mark OK button as default. */
10658 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
10659 XmNshowAsDefault, True, NULL);
10661 /* If MUSTMATCH is non-nil, disable the file entry field of the
10662 dialog, so that the user must select a file from the files list
10663 box. We can't remove it because we wouldn't have a way to get at
10664 the result file name, then. */
10665 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
10666 if (!NILP (mustmatch))
10668 Widget label;
10669 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
10670 XtSetSensitive (text, False);
10671 XtSetSensitive (label, False);
10674 /* Manage the dialog, so that list boxes get filled. */
10675 XtManageChild (dialog);
10677 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10678 must include the path for this to work. */
10679 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
10680 if (STRINGP (default_filename))
10682 XmString default_xmstring;
10683 int item_pos;
10685 default_xmstring
10686 = XmStringCreateLocalized (XSTRING (default_filename)->data);
10688 if (!XmListItemExists (list, default_xmstring))
10690 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10691 XmListAddItem (list, default_xmstring, 0);
10692 item_pos = 0;
10694 else
10695 item_pos = XmListItemPos (list, default_xmstring);
10696 XmStringFree (default_xmstring);
10698 /* Select the item and scroll it into view. */
10699 XmListSelectPos (list, item_pos, True);
10700 XmListSetPos (list, item_pos);
10703 /* Process all events until the user presses Cancel or OK. */
10704 for (result = 0; result == 0;)
10706 XEvent event;
10707 Widget widget, parent;
10709 XtAppNextEvent (Xt_app_con, &event);
10711 /* See if the receiver of the event is one of the widgets of
10712 the file selection dialog. If so, dispatch it. If not,
10713 discard it. */
10714 widget = XtWindowToWidget (event.xany.display, event.xany.window);
10715 parent = widget;
10716 while (parent && parent != dialog)
10717 parent = XtParent (parent);
10719 if (parent == dialog
10720 || (event.type == Expose
10721 && !process_expose_from_menu (event)))
10722 XtDispatchEvent (&event);
10725 /* Get the result. */
10726 if (result == XmCR_OK)
10728 XmString text;
10729 String data;
10731 XtVaGetValues (dialog, XmNtextString, &text, 0);
10732 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
10733 XmStringFree (text);
10734 file = build_string (data);
10735 XtFree (data);
10737 else
10738 file = Qnil;
10740 /* Clean up. */
10741 XtUnmanageChild (dialog);
10742 XtDestroyWidget (dialog);
10743 UNBLOCK_INPUT;
10744 UNGCPRO;
10746 /* Make "Cancel" equivalent to C-g. */
10747 if (NILP (file))
10748 Fsignal (Qquit, Qnil);
10750 return unbind_to (count, file);
10753 #endif /* USE_MOTIF */
10756 /***********************************************************************
10757 Tests
10758 ***********************************************************************/
10760 #if GLYPH_DEBUG
10762 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
10763 "Value is non-nil if SPEC is a valid image specification.")
10764 (spec)
10765 Lisp_Object spec;
10767 return valid_image_p (spec) ? Qt : Qnil;
10771 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
10772 (spec)
10773 Lisp_Object spec;
10775 int id = -1;
10777 if (valid_image_p (spec))
10778 id = lookup_image (SELECTED_FRAME (), spec);
10780 debug_print (spec);
10781 return make_number (id);
10784 #endif /* GLYPH_DEBUG != 0 */
10788 /***********************************************************************
10789 Initialization
10790 ***********************************************************************/
10792 void
10793 syms_of_xfns ()
10795 /* This is zero if not using X windows. */
10796 x_in_use = 0;
10798 /* The section below is built by the lisp expression at the top of the file,
10799 just above where these variables are declared. */
10800 /*&&& init symbols here &&&*/
10801 Qauto_raise = intern ("auto-raise");
10802 staticpro (&Qauto_raise);
10803 Qauto_lower = intern ("auto-lower");
10804 staticpro (&Qauto_lower);
10805 Qbar = intern ("bar");
10806 staticpro (&Qbar);
10807 Qborder_color = intern ("border-color");
10808 staticpro (&Qborder_color);
10809 Qborder_width = intern ("border-width");
10810 staticpro (&Qborder_width);
10811 Qbox = intern ("box");
10812 staticpro (&Qbox);
10813 Qcursor_color = intern ("cursor-color");
10814 staticpro (&Qcursor_color);
10815 Qcursor_type = intern ("cursor-type");
10816 staticpro (&Qcursor_type);
10817 Qgeometry = intern ("geometry");
10818 staticpro (&Qgeometry);
10819 Qicon_left = intern ("icon-left");
10820 staticpro (&Qicon_left);
10821 Qicon_top = intern ("icon-top");
10822 staticpro (&Qicon_top);
10823 Qicon_type = intern ("icon-type");
10824 staticpro (&Qicon_type);
10825 Qicon_name = intern ("icon-name");
10826 staticpro (&Qicon_name);
10827 Qinternal_border_width = intern ("internal-border-width");
10828 staticpro (&Qinternal_border_width);
10829 Qleft = intern ("left");
10830 staticpro (&Qleft);
10831 Qright = intern ("right");
10832 staticpro (&Qright);
10833 Qmouse_color = intern ("mouse-color");
10834 staticpro (&Qmouse_color);
10835 Qnone = intern ("none");
10836 staticpro (&Qnone);
10837 Qparent_id = intern ("parent-id");
10838 staticpro (&Qparent_id);
10839 Qscroll_bar_width = intern ("scroll-bar-width");
10840 staticpro (&Qscroll_bar_width);
10841 Qsuppress_icon = intern ("suppress-icon");
10842 staticpro (&Qsuppress_icon);
10843 Qundefined_color = intern ("undefined-color");
10844 staticpro (&Qundefined_color);
10845 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
10846 staticpro (&Qvertical_scroll_bars);
10847 Qvisibility = intern ("visibility");
10848 staticpro (&Qvisibility);
10849 Qwindow_id = intern ("window-id");
10850 staticpro (&Qwindow_id);
10851 Qouter_window_id = intern ("outer-window-id");
10852 staticpro (&Qouter_window_id);
10853 Qx_frame_parameter = intern ("x-frame-parameter");
10854 staticpro (&Qx_frame_parameter);
10855 Qx_resource_name = intern ("x-resource-name");
10856 staticpro (&Qx_resource_name);
10857 Quser_position = intern ("user-position");
10858 staticpro (&Quser_position);
10859 Quser_size = intern ("user-size");
10860 staticpro (&Quser_size);
10861 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
10862 staticpro (&Qscroll_bar_foreground);
10863 Qscroll_bar_background = intern ("scroll-bar-background");
10864 staticpro (&Qscroll_bar_background);
10865 Qscreen_gamma = intern ("screen-gamma");
10866 staticpro (&Qscreen_gamma);
10867 /* This is the end of symbol initialization. */
10869 /* Text property `display' should be nonsticky by default. */
10870 Vtext_property_default_nonsticky
10871 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10874 Qlaplace = intern ("laplace");
10875 staticpro (&Qlaplace);
10877 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10878 staticpro (&Qface_set_after_frame_default);
10880 Fput (Qundefined_color, Qerror_conditions,
10881 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10882 Fput (Qundefined_color, Qerror_message,
10883 build_string ("Undefined color"));
10885 init_x_parm_symbols ();
10887 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10888 "List of directories to search for bitmap files for X.");
10889 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
10891 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10892 "The shape of the pointer when over text.\n\
10893 Changing the value does not affect existing frames\n\
10894 unless you set the mouse color.");
10895 Vx_pointer_shape = Qnil;
10897 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
10898 "The name Emacs uses to look up X resources.\n\
10899 `x-get-resource' uses this as the first component of the instance name\n\
10900 when requesting resource values.\n\
10901 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10902 was invoked, or to the value specified with the `-name' or `-rn'\n\
10903 switches, if present.\n\
10905 It may be useful to bind this variable locally around a call\n\
10906 to `x-get-resource'. See also the variable `x-resource-class'.");
10907 Vx_resource_name = Qnil;
10909 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
10910 "The class Emacs uses to look up X resources.\n\
10911 `x-get-resource' uses this as the first component of the instance class\n\
10912 when requesting resource values.\n\
10913 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10915 Setting this variable permanently is not a reasonable thing to do,\n\
10916 but binding this variable locally around a call to `x-get-resource'\n\
10917 is a reasonable practice. See also the variable `x-resource-name'.");
10918 Vx_resource_class = build_string (EMACS_CLASS);
10920 #if 0 /* This doesn't really do anything. */
10921 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
10922 "The shape of the pointer when not over text.\n\
10923 This variable takes effect when you create a new frame\n\
10924 or when you set the mouse color.");
10925 #endif
10926 Vx_nontext_pointer_shape = Qnil;
10928 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
10929 "The shape of the pointer when Emacs is busy.\n\
10930 This variable takes effect when you create a new frame\n\
10931 or when you set the mouse color.");
10932 Vx_busy_pointer_shape = Qnil;
10934 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
10935 "Non-zero means Emacs displays a busy cursor on window systems.");
10936 display_busy_cursor_p = 1;
10938 #if 0 /* This doesn't really do anything. */
10939 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
10940 "The shape of the pointer when over the mode line.\n\
10941 This variable takes effect when you create a new frame\n\
10942 or when you set the mouse color.");
10943 #endif
10944 Vx_mode_pointer_shape = Qnil;
10946 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10947 &Vx_sensitive_text_pointer_shape,
10948 "The shape of the pointer when over mouse-sensitive text.\n\
10949 This variable takes effect when you create a new frame\n\
10950 or when you set the mouse color.");
10951 Vx_sensitive_text_pointer_shape = Qnil;
10953 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10954 "A string indicating the foreground color of the cursor box.");
10955 Vx_cursor_fore_pixel = Qnil;
10957 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10958 "Non-nil if no X window manager is in use.\n\
10959 Emacs doesn't try to figure this out; this is always nil\n\
10960 unless you set it to something else.");
10961 /* We don't have any way to find this out, so set it to nil
10962 and maybe the user would like to set it to t. */
10963 Vx_no_window_manager = Qnil;
10965 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10966 &Vx_pixel_size_width_font_regexp,
10967 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10969 Since Emacs gets width of a font matching with this regexp from\n\
10970 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10971 such a font. This is especially effective for such large fonts as\n\
10972 Chinese, Japanese, and Korean.");
10973 Vx_pixel_size_width_font_regexp = Qnil;
10975 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10976 "Time after which cached images are removed from the cache.\n\
10977 When an image has not been displayed this many seconds, remove it\n\
10978 from the image cache. Value must be an integer or nil with nil\n\
10979 meaning don't clear the cache.");
10980 Vimage_cache_eviction_delay = make_number (30 * 60);
10982 DEFVAR_LISP ("image-types", &Vimage_types,
10983 "List of supported image types.\n\
10984 Each element of the list is a symbol for a supported image type.");
10985 Vimage_types = Qnil;
10987 #ifdef USE_X_TOOLKIT
10988 Fprovide (intern ("x-toolkit"));
10989 #endif
10990 #ifdef USE_MOTIF
10991 Fprovide (intern ("motif"));
10992 #endif
10994 defsubr (&Sx_get_resource);
10996 /* X window properties. */
10997 defsubr (&Sx_change_window_property);
10998 defsubr (&Sx_delete_window_property);
10999 defsubr (&Sx_window_property);
11001 #if 0
11002 defsubr (&Sx_draw_rectangle);
11003 defsubr (&Sx_erase_rectangle);
11004 defsubr (&Sx_contour_region);
11005 defsubr (&Sx_uncontour_region);
11006 #endif
11007 defsubr (&Sxw_display_color_p);
11008 defsubr (&Sx_display_grayscale_p);
11009 defsubr (&Sxw_color_defined_p);
11010 defsubr (&Sxw_color_values);
11011 defsubr (&Sx_server_max_request_size);
11012 defsubr (&Sx_server_vendor);
11013 defsubr (&Sx_server_version);
11014 defsubr (&Sx_display_pixel_width);
11015 defsubr (&Sx_display_pixel_height);
11016 defsubr (&Sx_display_mm_width);
11017 defsubr (&Sx_display_mm_height);
11018 defsubr (&Sx_display_screens);
11019 defsubr (&Sx_display_planes);
11020 defsubr (&Sx_display_color_cells);
11021 defsubr (&Sx_display_visual_class);
11022 defsubr (&Sx_display_backing_store);
11023 defsubr (&Sx_display_save_under);
11024 #if 0
11025 defsubr (&Sx_rebind_key);
11026 defsubr (&Sx_rebind_keys);
11027 defsubr (&Sx_track_pointer);
11028 defsubr (&Sx_grab_pointer);
11029 defsubr (&Sx_ungrab_pointer);
11030 #endif
11031 defsubr (&Sx_parse_geometry);
11032 defsubr (&Sx_create_frame);
11033 #if 0
11034 defsubr (&Sx_horizontal_line);
11035 #endif
11036 defsubr (&Sx_open_connection);
11037 defsubr (&Sx_close_connection);
11038 defsubr (&Sx_display_list);
11039 defsubr (&Sx_synchronize);
11041 /* Setting callback functions for fontset handler. */
11042 get_font_info_func = x_get_font_info;
11044 #if 0 /* This function pointer doesn't seem to be used anywhere.
11045 And the pointer assigned has the wrong type, anyway. */
11046 list_fonts_func = x_list_fonts;
11047 #endif
11049 load_font_func = x_load_font;
11050 find_ccl_program_func = x_find_ccl_program;
11051 query_font_func = x_query_font;
11052 set_frame_fontset_func = x_set_font;
11053 check_window_system_func = check_x;
11055 /* Images. */
11056 Qxbm = intern ("xbm");
11057 staticpro (&Qxbm);
11058 QCtype = intern (":type");
11059 staticpro (&QCtype);
11060 QCalgorithm = intern (":algorithm");
11061 staticpro (&QCalgorithm);
11062 QCheuristic_mask = intern (":heuristic-mask");
11063 staticpro (&QCheuristic_mask);
11064 QCcolor_symbols = intern (":color-symbols");
11065 staticpro (&QCcolor_symbols);
11066 QCdata = intern (":data");
11067 staticpro (&QCdata);
11068 QCascent = intern (":ascent");
11069 staticpro (&QCascent);
11070 QCmargin = intern (":margin");
11071 staticpro (&QCmargin);
11072 QCrelief = intern (":relief");
11073 staticpro (&QCrelief);
11074 Qpostscript = intern ("postscript");
11075 staticpro (&Qpostscript);
11076 QCloader = intern (":loader");
11077 staticpro (&QCloader);
11078 QCbounding_box = intern (":bounding-box");
11079 staticpro (&QCbounding_box);
11080 QCpt_width = intern (":pt-width");
11081 staticpro (&QCpt_width);
11082 QCpt_height = intern (":pt-height");
11083 staticpro (&QCpt_height);
11084 QCindex = intern (":index");
11085 staticpro (&QCindex);
11086 Qpbm = intern ("pbm");
11087 staticpro (&Qpbm);
11089 #if HAVE_XPM
11090 Qxpm = intern ("xpm");
11091 staticpro (&Qxpm);
11092 #endif
11094 #if HAVE_JPEG
11095 Qjpeg = intern ("jpeg");
11096 staticpro (&Qjpeg);
11097 #endif
11099 #if HAVE_TIFF
11100 Qtiff = intern ("tiff");
11101 staticpro (&Qtiff);
11102 #endif
11104 #if HAVE_GIF
11105 Qgif = intern ("gif");
11106 staticpro (&Qgif);
11107 #endif
11109 #if HAVE_PNG
11110 Qpng = intern ("png");
11111 staticpro (&Qpng);
11112 #endif
11114 defsubr (&Sclear_image_cache);
11116 #if GLYPH_DEBUG
11117 defsubr (&Simagep);
11118 defsubr (&Slookup_image);
11119 #endif
11121 /* Busy-cursor. */
11122 defsubr (&Sx_show_busy_cursor);
11123 defsubr (&Sx_hide_busy_cursor);
11124 busy_count = 0;
11125 inhibit_busy_cursor = 0;
11127 defsubr (&Sx_show_tip);
11128 defsubr (&Sx_hide_tip);
11129 staticpro (&tip_timer);
11130 tip_timer = Qnil;
11132 #ifdef USE_MOTIF
11133 defsubr (&Sx_file_dialog);
11134 #endif
11138 void
11139 init_xfns ()
11141 image_types = NULL;
11142 Vimage_types = Qnil;
11144 define_image_type (&xbm_type);
11145 define_image_type (&gs_type);
11146 define_image_type (&pbm_type);
11148 #if HAVE_XPM
11149 define_image_type (&xpm_type);
11150 #endif
11152 #if HAVE_JPEG
11153 define_image_type (&jpeg_type);
11154 #endif
11156 #if HAVE_TIFF
11157 define_image_type (&tiff_type);
11158 #endif
11160 #if HAVE_GIF
11161 define_image_type (&gif_type);
11162 #endif
11164 #if HAVE_PNG
11165 define_image_type (&png_type);
11166 #endif
11169 #endif /* HAVE_X_WINDOWS */