Don't check HAVE_PNG_H: autoconf doesn't seem to find it.
[bpt/emacs.git] / src / xfns.c
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 01, 02, 03
3 Free Software Foundation.
4
5 This file is part of GNU Emacs.
6
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.
11
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.
16
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. */
21
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
26
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 /* This makes the fields of a Display accessible, in Xlib header files. */
32
33 #define XLIB_ILLEGAL_ACCESS
34
35 #include "lisp.h"
36 #include "xterm.h"
37 #include "frame.h"
38 #include "window.h"
39 #include "buffer.h"
40 #include "intervals.h"
41 #include "dispextern.h"
42 #include "keyboard.h"
43 #include "blockinput.h"
44 #include <epaths.h>
45 #include "charset.h"
46 #include "coding.h"
47 #include "fontset.h"
48 #include "systime.h"
49 #include "termhooks.h"
50 #include "atimer.h"
51
52 #ifdef HAVE_X_WINDOWS
53
54 #include <ctype.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57
58 #ifndef VMS
59 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
60 #include "bitmaps/gray.xbm"
61 #else
62 #include <X11/bitmaps/gray>
63 #endif
64 #else
65 #include "[.bitmaps]gray.xbm"
66 #endif
67
68 #ifdef USE_GTK
69 #include "gtkutil.h"
70 #endif
71
72 #ifdef USE_X_TOOLKIT
73 #include <X11/Shell.h>
74
75 #ifndef USE_MOTIF
76 #include <X11/Xaw/Paned.h>
77 #include <X11/Xaw/Label.h>
78 #endif /* USE_MOTIF */
79
80 #ifdef USG
81 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
82 #include <X11/Xos.h>
83 #define USG
84 #else
85 #include <X11/Xos.h>
86 #endif
87
88 #include "widget.h"
89
90 #include "../lwlib/lwlib.h"
91
92 #ifdef USE_MOTIF
93 #include <Xm/Xm.h>
94 #include <Xm/DialogS.h>
95 #include <Xm/FileSB.h>
96 #endif
97
98 /* Do the EDITRES protocol if running X11R5
99 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
100
101 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
102 #define HACK_EDITRES
103 extern void _XEditResCheckMessages ();
104 #endif /* R5 + Athena */
105
106 /* Unique id counter for widgets created by the Lucid Widget Library. */
107
108 extern LWLIB_ID widget_id_tick;
109
110 #ifdef USE_LUCID
111 /* This is part of a kludge--see lwlib/xlwmenu.c. */
112 extern XFontStruct *xlwmenu_default_font;
113 #endif
114
115 extern void free_frame_menubar ();
116 extern double atof ();
117
118 #ifdef USE_MOTIF
119
120 /* LessTif/Motif version info. */
121
122 static Lisp_Object Vmotif_version_string;
123
124 #endif /* USE_MOTIF */
125
126 #endif /* USE_X_TOOLKIT */
127
128 #ifdef HAVE_X11R4
129 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
130 #else
131 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
132 #endif
133
134 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
135 it, and including `bitmaps/gray' more than once is a problem when
136 config.h defines `static' as an empty replacement string. */
137
138 int gray_bitmap_width = gray_width;
139 int gray_bitmap_height = gray_height;
140 char *gray_bitmap_bits = gray_bits;
141
142 /* Non-zero means we're allowed to display an hourglass cursor. */
143
144 int display_hourglass_p;
145
146 /* The background and shape of the mouse pointer, and shape when not
147 over text or in the modeline. */
148
149 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
150 Lisp_Object Vx_hourglass_pointer_shape;
151
152 /* The shape when over mouse-sensitive text. */
153
154 Lisp_Object Vx_sensitive_text_pointer_shape;
155
156 /* If non-nil, the pointer shape to indicate that windows can be
157 dragged horizontally. */
158
159 Lisp_Object Vx_window_horizontal_drag_shape;
160
161 /* Color of chars displayed in cursor box. */
162
163 Lisp_Object Vx_cursor_fore_pixel;
164
165 /* Nonzero if using X. */
166
167 static int x_in_use;
168
169 /* Non nil if no window manager is in use. */
170
171 Lisp_Object Vx_no_window_manager;
172
173 /* Search path for bitmap files. */
174
175 Lisp_Object Vx_bitmap_file_path;
176
177 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
178
179 Lisp_Object Vx_pixel_size_width_font_regexp;
180
181 Lisp_Object Qnone;
182 Lisp_Object Qsuppress_icon;
183 Lisp_Object Qundefined_color;
184 Lisp_Object Qcenter;
185 Lisp_Object Qcompound_text, Qcancel_timer;
186
187 /* In dispnew.c */
188
189 extern Lisp_Object Vwindow_system_version;
190
191 /* The below are defined in frame.c. */
192
193 #if GLYPH_DEBUG
194 int image_cache_refcount, dpyinfo_refcount;
195 #endif
196
197
198 \f
199 /* Error if we are not connected to X. */
200
201 void
202 check_x ()
203 {
204 if (! x_in_use)
205 error ("X windows are not in use or not initialized");
206 }
207
208 /* Nonzero if we can use mouse menus.
209 You should not call this unless HAVE_MENUS is defined. */
210
211 int
212 have_menus_p ()
213 {
214 return x_in_use;
215 }
216
217 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
218 and checking validity for X. */
219
220 FRAME_PTR
221 check_x_frame (frame)
222 Lisp_Object frame;
223 {
224 FRAME_PTR f;
225
226 if (NILP (frame))
227 frame = selected_frame;
228 CHECK_LIVE_FRAME (frame);
229 f = XFRAME (frame);
230 if (! FRAME_X_P (f))
231 error ("Non-X frame used");
232 return f;
233 }
234
235 /* Let the user specify an X display with a frame.
236 nil stands for the selected frame--or, if that is not an X frame,
237 the first X display on the list. */
238
239 struct x_display_info *
240 check_x_display_info (frame)
241 Lisp_Object frame;
242 {
243 struct x_display_info *dpyinfo = NULL;
244
245 if (NILP (frame))
246 {
247 struct frame *sf = XFRAME (selected_frame);
248
249 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
250 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
251 else if (x_display_list != 0)
252 dpyinfo = x_display_list;
253 else
254 error ("X windows are not in use or not initialized");
255 }
256 else if (STRINGP (frame))
257 dpyinfo = x_display_info_for_name (frame);
258 else
259 {
260 FRAME_PTR f = check_x_frame (frame);
261 dpyinfo = FRAME_X_DISPLAY_INFO (f);
262 }
263
264 return dpyinfo;
265 }
266
267 \f
268 /* Return the Emacs frame-object corresponding to an X window.
269 It could be the frame's main window or an icon window. */
270
271 /* This function can be called during GC, so use GC_xxx type test macros. */
272
273 struct frame *
274 x_window_to_frame (dpyinfo, wdesc)
275 struct x_display_info *dpyinfo;
276 int wdesc;
277 {
278 Lisp_Object tail, frame;
279 struct frame *f;
280
281 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
282 {
283 frame = XCAR (tail);
284 if (!GC_FRAMEP (frame))
285 continue;
286 f = XFRAME (frame);
287 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
288 continue;
289 if (f->output_data.x->hourglass_window == wdesc)
290 return f;
291 #ifdef USE_X_TOOLKIT
292 if ((f->output_data.x->edit_widget
293 && XtWindow (f->output_data.x->edit_widget) == wdesc)
294 /* A tooltip frame? */
295 || (!f->output_data.x->edit_widget
296 && FRAME_X_WINDOW (f) == wdesc)
297 || f->output_data.x->icon_desc == wdesc)
298 return f;
299 #else /* not USE_X_TOOLKIT */
300 #ifdef USE_GTK
301 if (f->output_data.x->edit_widget)
302 {
303 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
304 struct x_output *x = f->output_data.x;
305 if (gwdesc != 0 && gwdesc == x->edit_widget)
306 return f;
307 }
308 #endif /* USE_GTK */
309 if (FRAME_X_WINDOW (f) == wdesc
310 || f->output_data.x->icon_desc == wdesc)
311 return f;
312 #endif /* not USE_X_TOOLKIT */
313 }
314 return 0;
315 }
316
317 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
318 /* Like x_window_to_frame but also compares the window with the widget's
319 windows. */
320
321 struct frame *
322 x_any_window_to_frame (dpyinfo, wdesc)
323 struct x_display_info *dpyinfo;
324 int wdesc;
325 {
326 Lisp_Object tail, frame;
327 struct frame *f, *found;
328 struct x_output *x;
329
330 found = NULL;
331 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
332 {
333 frame = XCAR (tail);
334 if (!GC_FRAMEP (frame))
335 continue;
336
337 f = XFRAME (frame);
338 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
339 {
340 /* This frame matches if the window is any of its widgets. */
341 x = f->output_data.x;
342 if (x->hourglass_window == wdesc)
343 found = f;
344 else if (x->widget)
345 {
346 #ifdef USE_GTK
347 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
348 if (gwdesc != 0
349 && (gwdesc == x->widget
350 || gwdesc == x->edit_widget
351 || gwdesc == x->vbox_widget
352 || gwdesc == x->menubar_widget))
353 found = f;
354 #else
355 if (wdesc == XtWindow (x->widget)
356 || wdesc == XtWindow (x->column_widget)
357 || wdesc == XtWindow (x->edit_widget))
358 found = f;
359 /* Match if the window is this frame's menubar. */
360 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
361 found = f;
362 #endif
363 }
364 else if (FRAME_X_WINDOW (f) == wdesc)
365 /* A tooltip frame. */
366 found = f;
367 }
368 }
369
370 return found;
371 }
372
373 /* Likewise, but exclude the menu bar widget. */
374
375 struct frame *
376 x_non_menubar_window_to_frame (dpyinfo, wdesc)
377 struct x_display_info *dpyinfo;
378 int wdesc;
379 {
380 Lisp_Object tail, frame;
381 struct frame *f;
382 struct x_output *x;
383
384 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
385 {
386 frame = XCAR (tail);
387 if (!GC_FRAMEP (frame))
388 continue;
389 f = XFRAME (frame);
390 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
391 continue;
392 x = f->output_data.x;
393 /* This frame matches if the window is any of its widgets. */
394 if (x->hourglass_window == wdesc)
395 return f;
396 else if (x->widget)
397 {
398 #ifdef USE_GTK
399 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
400 if (gwdesc != 0
401 && (gwdesc == x->widget
402 || gwdesc == x->edit_widget
403 || gwdesc == x->vbox_widget))
404 return f;
405 #else
406 if (wdesc == XtWindow (x->widget)
407 || wdesc == XtWindow (x->column_widget)
408 || wdesc == XtWindow (x->edit_widget))
409 return f;
410 #endif
411 }
412 else if (FRAME_X_WINDOW (f) == wdesc)
413 /* A tooltip frame. */
414 return f;
415 }
416 return 0;
417 }
418
419 /* Likewise, but consider only the menu bar widget. */
420
421 struct frame *
422 x_menubar_window_to_frame (dpyinfo, wdesc)
423 struct x_display_info *dpyinfo;
424 int wdesc;
425 {
426 Lisp_Object tail, frame;
427 struct frame *f;
428 struct x_output *x;
429
430 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
431 {
432 frame = XCAR (tail);
433 if (!GC_FRAMEP (frame))
434 continue;
435 f = XFRAME (frame);
436 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
437 continue;
438 x = f->output_data.x;
439 /* Match if the window is this frame's menubar. */
440 #ifdef USE_GTK
441 if (x->menubar_widget)
442 {
443 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
444 int found = 0;
445
446 BLOCK_INPUT;
447 if (gwdesc != 0
448 && (gwdesc == x->menubar_widget
449 || gtk_widget_get_parent (gwdesc) == x->menubar_widget))
450 found = 1;
451 UNBLOCK_INPUT;
452 if (found) return f;
453 }
454 #else
455 if (x->menubar_widget
456 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
457 return f;
458 #endif
459 }
460 return 0;
461 }
462
463 /* Return the frame whose principal (outermost) window is WDESC.
464 If WDESC is some other (smaller) window, we return 0. */
465
466 struct frame *
467 x_top_window_to_frame (dpyinfo, wdesc)
468 struct x_display_info *dpyinfo;
469 int wdesc;
470 {
471 Lisp_Object tail, frame;
472 struct frame *f;
473 struct x_output *x;
474
475 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
476 {
477 frame = XCAR (tail);
478 if (!GC_FRAMEP (frame))
479 continue;
480 f = XFRAME (frame);
481 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
482 continue;
483 x = f->output_data.x;
484
485 if (x->widget)
486 {
487 /* This frame matches if the window is its topmost widget. */
488 #ifdef USE_GTK
489 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
490 if (gwdesc == x->widget)
491 return f;
492 #else
493 if (wdesc == XtWindow (x->widget))
494 return f;
495 #if 0 /* I don't know why it did this,
496 but it seems logically wrong,
497 and it causes trouble for MapNotify events. */
498 /* Match if the window is this frame's menubar. */
499 if (x->menubar_widget
500 && wdesc == XtWindow (x->menubar_widget))
501 return f;
502 #endif
503 #endif
504 }
505 else if (FRAME_X_WINDOW (f) == wdesc)
506 /* Tooltip frame. */
507 return f;
508 }
509 return 0;
510 }
511 #endif /* USE_X_TOOLKIT || USE_GTK */
512
513 \f
514
515 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
516 id, which is just an int that this section returns. Bitmaps are
517 reference counted so they can be shared among frames.
518
519 Bitmap indices are guaranteed to be > 0, so a negative number can
520 be used to indicate no bitmap.
521
522 If you use x_create_bitmap_from_data, then you must keep track of
523 the bitmaps yourself. That is, creating a bitmap from the same
524 data more than once will not be caught. */
525
526
527 /* Functions to access the contents of a bitmap, given an id. */
528
529 int
530 x_bitmap_height (f, id)
531 FRAME_PTR f;
532 int id;
533 {
534 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
535 }
536
537 int
538 x_bitmap_width (f, id)
539 FRAME_PTR f;
540 int id;
541 {
542 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
543 }
544
545 int
546 x_bitmap_pixmap (f, id)
547 FRAME_PTR f;
548 int id;
549 {
550 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
551 }
552
553 int
554 x_bitmap_mask (f, id)
555 FRAME_PTR f;
556 int id;
557 {
558 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
559 }
560
561
562 /* Allocate a new bitmap record. Returns index of new record. */
563
564 static int
565 x_allocate_bitmap_record (f)
566 FRAME_PTR f;
567 {
568 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
569 int i;
570
571 if (dpyinfo->bitmaps == NULL)
572 {
573 dpyinfo->bitmaps_size = 10;
574 dpyinfo->bitmaps
575 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
576 dpyinfo->bitmaps_last = 1;
577 return 1;
578 }
579
580 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
581 return ++dpyinfo->bitmaps_last;
582
583 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
584 if (dpyinfo->bitmaps[i].refcount == 0)
585 return i + 1;
586
587 dpyinfo->bitmaps_size *= 2;
588 dpyinfo->bitmaps
589 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
590 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
591 return ++dpyinfo->bitmaps_last;
592 }
593
594 /* Add one reference to the reference count of the bitmap with id ID. */
595
596 void
597 x_reference_bitmap (f, id)
598 FRAME_PTR f;
599 int id;
600 {
601 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
602 }
603
604 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
605
606 int
607 x_create_bitmap_from_data (f, bits, width, height)
608 struct frame *f;
609 char *bits;
610 unsigned int width, height;
611 {
612 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
613 Pixmap bitmap;
614 int id;
615
616 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
617 bits, width, height);
618
619
620
621 if (! bitmap)
622 return -1;
623
624 id = x_allocate_bitmap_record (f);
625 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
626 dpyinfo->bitmaps[id - 1].file = NULL;
627 dpyinfo->bitmaps[id - 1].refcount = 1;
628 dpyinfo->bitmaps[id - 1].depth = 1;
629 dpyinfo->bitmaps[id - 1].height = height;
630 dpyinfo->bitmaps[id - 1].width = width;
631
632 return id;
633 }
634
635 /* Create bitmap from file FILE for frame F. */
636
637 int
638 x_create_bitmap_from_file (f, file)
639 struct frame *f;
640 Lisp_Object file;
641 {
642 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
643 unsigned int width, height;
644 Pixmap bitmap;
645 int xhot, yhot, result, id;
646 Lisp_Object found;
647 int fd;
648 char *filename;
649
650 /* Look for an existing bitmap with the same name. */
651 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
652 {
653 if (dpyinfo->bitmaps[id].refcount
654 && dpyinfo->bitmaps[id].file
655 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
656 {
657 ++dpyinfo->bitmaps[id].refcount;
658 return id + 1;
659 }
660 }
661
662 /* Search bitmap-file-path for the file, if appropriate. */
663 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
664 if (fd < 0)
665 return -1;
666 emacs_close (fd);
667
668 filename = (char *) SDATA (found);
669
670 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
671 filename, &width, &height, &bitmap, &xhot, &yhot);
672 if (result != BitmapSuccess)
673 return -1;
674
675 id = x_allocate_bitmap_record (f);
676 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
677 dpyinfo->bitmaps[id - 1].refcount = 1;
678 dpyinfo->bitmaps[id - 1].file
679 = (char *) xmalloc (SBYTES (file) + 1);
680 dpyinfo->bitmaps[id - 1].depth = 1;
681 dpyinfo->bitmaps[id - 1].height = height;
682 dpyinfo->bitmaps[id - 1].width = width;
683 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
684
685 return id;
686 }
687
688 /* Remove reference to bitmap with id number ID. */
689
690 void
691 x_destroy_bitmap (f, id)
692 FRAME_PTR f;
693 int id;
694 {
695 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
696
697 if (id > 0)
698 {
699 --dpyinfo->bitmaps[id - 1].refcount;
700 if (dpyinfo->bitmaps[id - 1].refcount == 0)
701 {
702 BLOCK_INPUT;
703 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
704 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].mask);
705 if (dpyinfo->bitmaps[id - 1].file)
706 {
707 xfree (dpyinfo->bitmaps[id - 1].file);
708 dpyinfo->bitmaps[id - 1].file = NULL;
709 }
710 UNBLOCK_INPUT;
711 }
712 }
713 }
714
715 /* Free all the bitmaps for the display specified by DPYINFO. */
716
717 static void
718 x_destroy_all_bitmaps (dpyinfo)
719 struct x_display_info *dpyinfo;
720 {
721 int i;
722 for (i = 0; i < dpyinfo->bitmaps_last; i++)
723 if (dpyinfo->bitmaps[i].refcount > 0)
724 {
725 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
726 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].mask);
727 if (dpyinfo->bitmaps[i].file)
728 xfree (dpyinfo->bitmaps[i].file);
729 }
730 dpyinfo->bitmaps_last = 0;
731 }
732 \f
733
734
735
736 /* Useful functions defined in the section
737 `Image type independent image structures' below. */
738
739 static unsigned long four_corners_best P_ ((XImage *ximg, unsigned long width,
740 unsigned long height));
741
742 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
743 int depth, XImage **ximg,
744 Pixmap *pixmap));
745
746 static void x_destroy_x_image P_ ((XImage *ximg));
747
748
749 /* Create a mask of a bitmap. Note is this not a perfect mask.
750 It's nicer with some borders in this context */
751
752 int
753 x_create_bitmap_mask(f, id)
754 struct frame *f;
755 int id;
756 {
757 Pixmap pixmap, mask;
758 XImage *ximg, *mask_img;
759 unsigned long width, height;
760 int result;
761 unsigned long bg;
762 unsigned long x, y, xp, xm, yp, ym;
763 GC gc;
764
765 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
766 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
767
768 if (!(id > 0))
769 return -1;
770
771 pixmap = x_bitmap_pixmap(f, id);
772 width = x_bitmap_width(f, id);
773 height = x_bitmap_height(f, id);
774
775 BLOCK_INPUT;
776 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
777 ~0, ZPixmap);
778
779 if (!ximg)
780 {
781 UNBLOCK_INPUT;
782 return -1;
783 }
784
785 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
786
787 UNBLOCK_INPUT;
788 if (!result)
789 {
790 XDestroyImage(ximg);
791 return -1;
792 }
793
794 bg = four_corners_best (ximg, width, height);
795
796 for (y = 0; y < ximg->height; ++y)
797 {
798 for (x = 0; x < ximg->width; ++x)
799 {
800 xp = x != ximg->width - 1 ? x + 1 : 0;
801 xm = x != 0 ? x - 1 : ximg->width - 1;
802 yp = y != ximg->height - 1 ? y + 1 : 0;
803 ym = y != 0 ? y - 1 : ximg->height - 1;
804 if (XGetPixel (ximg, x, y) == bg
805 && XGetPixel (ximg, x, yp) == bg
806 && XGetPixel (ximg, x, ym) == bg
807 && XGetPixel (ximg, xp, y) == bg
808 && XGetPixel (ximg, xp, yp) == bg
809 && XGetPixel (ximg, xp, ym) == bg
810 && XGetPixel (ximg, xm, y) == bg
811 && XGetPixel (ximg, xm, yp) == bg
812 && XGetPixel (ximg, xm, ym) == bg)
813 XPutPixel (mask_img, x, y, 0);
814 else
815 XPutPixel (mask_img, x, y, 1);
816 }
817 }
818
819 xassert (interrupt_input_blocked);
820 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
821 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
822 width, height);
823 XFreeGC (FRAME_X_DISPLAY (f), gc);
824
825 dpyinfo->bitmaps[id - 1].mask = mask;
826
827 XDestroyImage (ximg);
828 x_destroy_x_image(mask_img);
829
830 return 0;
831 }
832
833 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
834 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
835 static void x_disable_image P_ ((struct frame *, struct image *));
836
837 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
838 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
839 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
840 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
841 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
842 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
843 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
844 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
845 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
846 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
847 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
848 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
849 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
850 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
851 Lisp_Object));
852 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
853 Lisp_Object));
854 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
855 Lisp_Object,
856 Lisp_Object,
857 char *, char *,
858 int));
859 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
860 Lisp_Object));
861 static void init_color_table P_ ((void));
862 static void free_color_table P_ ((void));
863 static unsigned long *colors_in_color_table P_ ((int *n));
864 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
865 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
866
867
868
869 \f
870
871 /* Store the screen positions of frame F into XPTR and YPTR.
872 These are the positions of the containing window manager window,
873 not Emacs's own window. */
874
875 void
876 x_real_positions (f, xptr, yptr)
877 FRAME_PTR f;
878 int *xptr, *yptr;
879 {
880 int win_x, win_y, outer_x, outer_y;
881 int real_x = 0, real_y = 0;
882 int had_errors = 0;
883 Window win = f->output_data.x->parent_desc;
884
885 int count;
886
887 BLOCK_INPUT;
888
889 count = x_catch_errors (FRAME_X_DISPLAY (f));
890
891 if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
892 win = FRAME_OUTER_WINDOW (f);
893
894 /* This loop traverses up the containment tree until we hit the root
895 window. Window managers may intersect many windows between our window
896 and the root window. The window we find just before the root window
897 should be the outer WM window. */
898 for (;;)
899 {
900 Window wm_window, rootw;
901 Window *tmp_children;
902 unsigned int tmp_nchildren;
903 int success;
904
905 success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
906 &wm_window, &tmp_children, &tmp_nchildren);
907
908 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
909
910 /* Don't free tmp_children if XQueryTree failed. */
911 if (! success)
912 break;
913
914 XFree ((char *) tmp_children);
915
916 if (wm_window == rootw || had_errors)
917 break;
918
919 win = wm_window;
920 }
921
922 if (! had_errors)
923 {
924 int ign;
925 Window child, rootw;
926
927 /* Get the real coordinates for the WM window upper left corner */
928 XGetGeometry (FRAME_X_DISPLAY (f), win,
929 &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
930
931 /* Translate real coordinates to coordinates relative to our
932 window. For our window, the upper left corner is 0, 0.
933 Since the upper left corner of the WM window is outside
934 our window, win_x and win_y will be negative:
935
936 ------------------ ---> x
937 | title |
938 | ----------------- v y
939 | | our window
940 */
941 XTranslateCoordinates (FRAME_X_DISPLAY (f),
942
943 /* From-window, to-window. */
944 FRAME_X_DISPLAY_INFO (f)->root_window,
945 FRAME_X_WINDOW (f),
946
947 /* From-position, to-position. */
948 real_x, real_y, &win_x, &win_y,
949
950 /* Child of win. */
951 &child);
952
953 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
954 {
955 outer_x = win_x;
956 outer_y = win_y;
957 }
958 else
959 {
960 XTranslateCoordinates (FRAME_X_DISPLAY (f),
961
962 /* From-window, to-window. */
963 FRAME_X_DISPLAY_INFO (f)->root_window,
964 FRAME_OUTER_WINDOW (f),
965
966 /* From-position, to-position. */
967 real_x, real_y, &outer_x, &outer_y,
968
969 /* Child of win. */
970 &child);
971 }
972
973 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
974 }
975
976 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
977
978 UNBLOCK_INPUT;
979
980 if (had_errors) return;
981
982 f->x_pixels_diff = -win_x;
983 f->y_pixels_diff = -win_y;
984
985 FRAME_X_OUTPUT (f)->x_pixels_outer_diff = -outer_x;
986 FRAME_X_OUTPUT (f)->y_pixels_outer_diff = -outer_y;
987
988 *xptr = real_x;
989 *yptr = real_y;
990 }
991
992 \f
993
994
995 /* Gamma-correct COLOR on frame F. */
996
997 void
998 gamma_correct (f, color)
999 struct frame *f;
1000 XColor *color;
1001 {
1002 if (f->gamma)
1003 {
1004 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1005 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1006 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1007 }
1008 }
1009
1010
1011 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1012 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1013 allocate the color. Value is zero if COLOR_NAME is invalid, or
1014 no color could be allocated. */
1015
1016 int
1017 x_defined_color (f, color_name, color, alloc_p)
1018 struct frame *f;
1019 char *color_name;
1020 XColor *color;
1021 int alloc_p;
1022 {
1023 int success_p;
1024 Display *dpy = FRAME_X_DISPLAY (f);
1025 Colormap cmap = FRAME_X_COLORMAP (f);
1026
1027 BLOCK_INPUT;
1028 success_p = XParseColor (dpy, cmap, color_name, color);
1029 if (success_p && alloc_p)
1030 success_p = x_alloc_nearest_color (f, cmap, color);
1031 UNBLOCK_INPUT;
1032
1033 return success_p;
1034 }
1035
1036
1037 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1038 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1039 Signal an error if color can't be allocated. */
1040
1041 int
1042 x_decode_color (f, color_name, mono_color)
1043 FRAME_PTR f;
1044 Lisp_Object color_name;
1045 int mono_color;
1046 {
1047 XColor cdef;
1048
1049 CHECK_STRING (color_name);
1050
1051 #if 0 /* Don't do this. It's wrong when we're not using the default
1052 colormap, it makes freeing difficult, and it's probably not
1053 an important optimization. */
1054 if (strcmp (SDATA (color_name), "black") == 0)
1055 return BLACK_PIX_DEFAULT (f);
1056 else if (strcmp (SDATA (color_name), "white") == 0)
1057 return WHITE_PIX_DEFAULT (f);
1058 #endif
1059
1060 /* Return MONO_COLOR for monochrome frames. */
1061 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1062 return mono_color;
1063
1064 /* x_defined_color is responsible for coping with failures
1065 by looking for a near-miss. */
1066 if (x_defined_color (f, SDATA (color_name), &cdef, 1))
1067 return cdef.pixel;
1068
1069 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1070 Fcons (color_name, Qnil)));
1071 return 0;
1072 }
1073
1074
1075 \f
1076 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1077 the previous value of that parameter, NEW_VALUE is the new value.
1078 See also the comment of wait_for_wm in struct x_output. */
1079
1080 static void
1081 x_set_wait_for_wm (f, new_value, old_value)
1082 struct frame *f;
1083 Lisp_Object new_value, old_value;
1084 {
1085 f->output_data.x->wait_for_wm = !NILP (new_value);
1086 }
1087
1088 #ifdef USE_GTK
1089
1090 /* Wrapper for gtk_window_icon_from_file() */
1091
1092 int
1093 xg_set_icon(f, file)
1094 struct frame *f;
1095 Lisp_Object file;
1096 {
1097 struct gcpro gcpro1, gcpro2, gcpro3;
1098 int fd;
1099 int result = 1;
1100 Lisp_Object found, search_path;
1101 char *filename;
1102
1103 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
1104
1105 GCPRO3 (found, search_path, file);
1106 fd = openp (search_path, file, Qnil, &found, Qnil);
1107 if (fd > 0)
1108 {
1109 filename = (char *) SDATA (found);
1110 BLOCK_INPUT;
1111 result =
1112 gtk_window_set_icon_from_file (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1113 filename,
1114 NULL);
1115 UNBLOCK_INPUT;
1116 }
1117 emacs_close (fd);
1118 UNGCPRO;
1119 return result;
1120 }
1121 #endif /* USE_GTK */
1122
1123
1124 /* Functions called only from `x_set_frame_param'
1125 to set individual parameters.
1126
1127 If FRAME_X_WINDOW (f) is 0,
1128 the frame is being created and its X-window does not exist yet.
1129 In that case, just record the parameter's new value
1130 in the standard place; do not attempt to change the window. */
1131
1132 void
1133 x_set_foreground_color (f, arg, oldval)
1134 struct frame *f;
1135 Lisp_Object arg, oldval;
1136 {
1137 struct x_output *x = f->output_data.x;
1138 unsigned long fg, old_fg;
1139
1140 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1141 old_fg = x->foreground_pixel;
1142 x->foreground_pixel = fg;
1143
1144 if (FRAME_X_WINDOW (f) != 0)
1145 {
1146 Display *dpy = FRAME_X_DISPLAY (f);
1147
1148 BLOCK_INPUT;
1149 XSetForeground (dpy, x->normal_gc, fg);
1150 XSetBackground (dpy, x->reverse_gc, fg);
1151
1152 if (x->cursor_pixel == old_fg)
1153 {
1154 unload_color (f, x->cursor_pixel);
1155 x->cursor_pixel = x_copy_color (f, fg);
1156 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1157 }
1158
1159 UNBLOCK_INPUT;
1160
1161 update_face_from_frame_parameter (f, Qforeground_color, arg);
1162
1163 if (FRAME_VISIBLE_P (f))
1164 redraw_frame (f);
1165 }
1166
1167 unload_color (f, old_fg);
1168 }
1169
1170 void
1171 x_set_background_color (f, arg, oldval)
1172 struct frame *f;
1173 Lisp_Object arg, oldval;
1174 {
1175 struct x_output *x = f->output_data.x;
1176 unsigned long bg;
1177
1178 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1179 unload_color (f, x->background_pixel);
1180 x->background_pixel = bg;
1181
1182 if (FRAME_X_WINDOW (f) != 0)
1183 {
1184 Display *dpy = FRAME_X_DISPLAY (f);
1185
1186 BLOCK_INPUT;
1187 XSetBackground (dpy, x->normal_gc, bg);
1188 XSetForeground (dpy, x->reverse_gc, bg);
1189 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1190 XSetForeground (dpy, x->cursor_gc, bg);
1191
1192 #ifdef USE_GTK
1193 xg_set_background_color (f, bg);
1194 #endif
1195
1196 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1197 toolkit scroll bars. */
1198 {
1199 Lisp_Object bar;
1200 for (bar = FRAME_SCROLL_BARS (f);
1201 !NILP (bar);
1202 bar = XSCROLL_BAR (bar)->next)
1203 {
1204 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1205 XSetWindowBackground (dpy, window, bg);
1206 }
1207 }
1208 #endif /* USE_TOOLKIT_SCROLL_BARS */
1209
1210 UNBLOCK_INPUT;
1211 update_face_from_frame_parameter (f, Qbackground_color, arg);
1212
1213 if (FRAME_VISIBLE_P (f))
1214 redraw_frame (f);
1215 }
1216 }
1217
1218 void
1219 x_set_mouse_color (f, arg, oldval)
1220 struct frame *f;
1221 Lisp_Object arg, oldval;
1222 {
1223 struct x_output *x = f->output_data.x;
1224 Display *dpy = FRAME_X_DISPLAY (f);
1225 Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
1226 Cursor hourglass_cursor, horizontal_drag_cursor;
1227 int count;
1228 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1229 unsigned long mask_color = x->background_pixel;
1230
1231 /* Don't let pointers be invisible. */
1232 if (mask_color == pixel)
1233 {
1234 x_free_colors (f, &pixel, 1);
1235 pixel = x_copy_color (f, x->foreground_pixel);
1236 }
1237
1238 unload_color (f, x->mouse_pixel);
1239 x->mouse_pixel = pixel;
1240
1241 BLOCK_INPUT;
1242
1243 /* It's not okay to crash if the user selects a screwy cursor. */
1244 count = x_catch_errors (dpy);
1245
1246 if (!NILP (Vx_pointer_shape))
1247 {
1248 CHECK_NUMBER (Vx_pointer_shape);
1249 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1250 }
1251 else
1252 cursor = XCreateFontCursor (dpy, XC_xterm);
1253 x_check_errors (dpy, "bad text pointer cursor: %s");
1254
1255 if (!NILP (Vx_nontext_pointer_shape))
1256 {
1257 CHECK_NUMBER (Vx_nontext_pointer_shape);
1258 nontext_cursor
1259 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1260 }
1261 else
1262 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1263 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1264
1265 if (!NILP (Vx_hourglass_pointer_shape))
1266 {
1267 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1268 hourglass_cursor
1269 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1270 }
1271 else
1272 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1273 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1274
1275 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1276 if (!NILP (Vx_mode_pointer_shape))
1277 {
1278 CHECK_NUMBER (Vx_mode_pointer_shape);
1279 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1280 }
1281 else
1282 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1283 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1284
1285 if (!NILP (Vx_sensitive_text_pointer_shape))
1286 {
1287 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1288 hand_cursor
1289 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1290 }
1291 else
1292 hand_cursor = XCreateFontCursor (dpy, XC_hand2);
1293
1294 if (!NILP (Vx_window_horizontal_drag_shape))
1295 {
1296 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1297 horizontal_drag_cursor
1298 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1299 }
1300 else
1301 horizontal_drag_cursor
1302 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1303
1304 /* Check and report errors with the above calls. */
1305 x_check_errors (dpy, "can't set cursor shape: %s");
1306 x_uncatch_errors (dpy, count);
1307
1308 {
1309 XColor fore_color, back_color;
1310
1311 fore_color.pixel = x->mouse_pixel;
1312 x_query_color (f, &fore_color);
1313 back_color.pixel = mask_color;
1314 x_query_color (f, &back_color);
1315
1316 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1317 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1318 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1319 XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
1320 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1321 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1322 }
1323
1324 if (FRAME_X_WINDOW (f) != 0)
1325 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1326
1327 if (cursor != x->text_cursor
1328 && x->text_cursor != 0)
1329 XFreeCursor (dpy, x->text_cursor);
1330 x->text_cursor = cursor;
1331
1332 if (nontext_cursor != x->nontext_cursor
1333 && x->nontext_cursor != 0)
1334 XFreeCursor (dpy, x->nontext_cursor);
1335 x->nontext_cursor = nontext_cursor;
1336
1337 if (hourglass_cursor != x->hourglass_cursor
1338 && x->hourglass_cursor != 0)
1339 XFreeCursor (dpy, x->hourglass_cursor);
1340 x->hourglass_cursor = hourglass_cursor;
1341
1342 if (mode_cursor != x->modeline_cursor
1343 && x->modeline_cursor != 0)
1344 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1345 x->modeline_cursor = mode_cursor;
1346
1347 if (hand_cursor != x->hand_cursor
1348 && x->hand_cursor != 0)
1349 XFreeCursor (dpy, x->hand_cursor);
1350 x->hand_cursor = hand_cursor;
1351
1352 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1353 && x->horizontal_drag_cursor != 0)
1354 XFreeCursor (dpy, x->horizontal_drag_cursor);
1355 x->horizontal_drag_cursor = horizontal_drag_cursor;
1356
1357 XFlush (dpy);
1358 UNBLOCK_INPUT;
1359
1360 update_face_from_frame_parameter (f, Qmouse_color, arg);
1361 }
1362
1363 void
1364 x_set_cursor_color (f, arg, oldval)
1365 struct frame *f;
1366 Lisp_Object arg, oldval;
1367 {
1368 unsigned long fore_pixel, pixel;
1369 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1370 struct x_output *x = f->output_data.x;
1371
1372 if (!NILP (Vx_cursor_fore_pixel))
1373 {
1374 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1375 WHITE_PIX_DEFAULT (f));
1376 fore_pixel_allocated_p = 1;
1377 }
1378 else
1379 fore_pixel = x->background_pixel;
1380
1381 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1382 pixel_allocated_p = 1;
1383
1384 /* Make sure that the cursor color differs from the background color. */
1385 if (pixel == x->background_pixel)
1386 {
1387 if (pixel_allocated_p)
1388 {
1389 x_free_colors (f, &pixel, 1);
1390 pixel_allocated_p = 0;
1391 }
1392
1393 pixel = x->mouse_pixel;
1394 if (pixel == fore_pixel)
1395 {
1396 if (fore_pixel_allocated_p)
1397 {
1398 x_free_colors (f, &fore_pixel, 1);
1399 fore_pixel_allocated_p = 0;
1400 }
1401 fore_pixel = x->background_pixel;
1402 }
1403 }
1404
1405 unload_color (f, x->cursor_foreground_pixel);
1406 if (!fore_pixel_allocated_p)
1407 fore_pixel = x_copy_color (f, fore_pixel);
1408 x->cursor_foreground_pixel = fore_pixel;
1409
1410 unload_color (f, x->cursor_pixel);
1411 if (!pixel_allocated_p)
1412 pixel = x_copy_color (f, pixel);
1413 x->cursor_pixel = pixel;
1414
1415 if (FRAME_X_WINDOW (f) != 0)
1416 {
1417 BLOCK_INPUT;
1418 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1419 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1420 UNBLOCK_INPUT;
1421
1422 if (FRAME_VISIBLE_P (f))
1423 {
1424 x_update_cursor (f, 0);
1425 x_update_cursor (f, 1);
1426 }
1427 }
1428
1429 update_face_from_frame_parameter (f, Qcursor_color, arg);
1430 }
1431 \f
1432 /* Set the border-color of frame F to pixel value PIX.
1433 Note that this does not fully take effect if done before
1434 F has an x-window. */
1435
1436 void
1437 x_set_border_pixel (f, pix)
1438 struct frame *f;
1439 int pix;
1440 {
1441 unload_color (f, f->output_data.x->border_pixel);
1442 f->output_data.x->border_pixel = pix;
1443
1444 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1445 {
1446 BLOCK_INPUT;
1447 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1448 (unsigned long)pix);
1449 UNBLOCK_INPUT;
1450
1451 if (FRAME_VISIBLE_P (f))
1452 redraw_frame (f);
1453 }
1454 }
1455
1456 /* Set the border-color of frame F to value described by ARG.
1457 ARG can be a string naming a color.
1458 The border-color is used for the border that is drawn by the X server.
1459 Note that this does not fully take effect if done before
1460 F has an x-window; it must be redone when the window is created.
1461
1462 Note: this is done in two routines because of the way X10 works.
1463
1464 Note: under X11, this is normally the province of the window manager,
1465 and so emacs' border colors may be overridden. */
1466
1467 void
1468 x_set_border_color (f, arg, oldval)
1469 struct frame *f;
1470 Lisp_Object arg, oldval;
1471 {
1472 int pix;
1473
1474 CHECK_STRING (arg);
1475 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1476 x_set_border_pixel (f, pix);
1477 update_face_from_frame_parameter (f, Qborder_color, arg);
1478 }
1479
1480
1481 void
1482 x_set_cursor_type (f, arg, oldval)
1483 FRAME_PTR f;
1484 Lisp_Object arg, oldval;
1485 {
1486 set_frame_cursor_types (f, arg);
1487
1488 /* Make sure the cursor gets redrawn. */
1489 cursor_type_changed = 1;
1490 }
1491 \f
1492 void
1493 x_set_icon_type (f, arg, oldval)
1494 struct frame *f;
1495 Lisp_Object arg, oldval;
1496 {
1497 int result;
1498
1499 if (STRINGP (arg))
1500 {
1501 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1502 return;
1503 }
1504 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1505 return;
1506
1507 BLOCK_INPUT;
1508 if (NILP (arg))
1509 result = x_text_icon (f,
1510 (char *) SDATA ((!NILP (f->icon_name)
1511 ? f->icon_name
1512 : f->name)));
1513 else
1514 result = x_bitmap_icon (f, arg);
1515
1516 if (result)
1517 {
1518 UNBLOCK_INPUT;
1519 error ("No icon window available");
1520 }
1521
1522 XFlush (FRAME_X_DISPLAY (f));
1523 UNBLOCK_INPUT;
1524 }
1525
1526 void
1527 x_set_icon_name (f, arg, oldval)
1528 struct frame *f;
1529 Lisp_Object arg, oldval;
1530 {
1531 int result;
1532
1533 if (STRINGP (arg))
1534 {
1535 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1536 return;
1537 }
1538 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1539 return;
1540
1541 f->icon_name = arg;
1542
1543 if (f->output_data.x->icon_bitmap != 0)
1544 return;
1545
1546 BLOCK_INPUT;
1547
1548 result = x_text_icon (f,
1549 (char *) SDATA ((!NILP (f->icon_name)
1550 ? f->icon_name
1551 : !NILP (f->title)
1552 ? f->title
1553 : f->name)));
1554
1555 if (result)
1556 {
1557 UNBLOCK_INPUT;
1558 error ("No icon window available");
1559 }
1560
1561 XFlush (FRAME_X_DISPLAY (f));
1562 UNBLOCK_INPUT;
1563 }
1564
1565 \f
1566 void
1567 x_set_menu_bar_lines (f, value, oldval)
1568 struct frame *f;
1569 Lisp_Object value, oldval;
1570 {
1571 int nlines;
1572 #ifndef USE_X_TOOLKIT
1573 int olines = FRAME_MENU_BAR_LINES (f);
1574 #endif
1575
1576 /* Right now, menu bars don't work properly in minibuf-only frames;
1577 most of the commands try to apply themselves to the minibuffer
1578 frame itself, and get an error because you can't switch buffers
1579 in or split the minibuffer window. */
1580 if (FRAME_MINIBUF_ONLY_P (f))
1581 return;
1582
1583 if (INTEGERP (value))
1584 nlines = XINT (value);
1585 else
1586 nlines = 0;
1587
1588 /* Make sure we redisplay all windows in this frame. */
1589 windows_or_buffers_changed++;
1590
1591 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1592 FRAME_MENU_BAR_LINES (f) = 0;
1593 if (nlines)
1594 {
1595 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1596 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1597 /* Make sure next redisplay shows the menu bar. */
1598 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1599 }
1600 else
1601 {
1602 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1603 free_frame_menubar (f);
1604 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1605 if (FRAME_X_P (f))
1606 f->output_data.x->menubar_widget = 0;
1607 }
1608 #else /* not USE_X_TOOLKIT && not USE_GTK */
1609 FRAME_MENU_BAR_LINES (f) = nlines;
1610 change_window_heights (f->root_window, nlines - olines);
1611 #endif /* not USE_X_TOOLKIT */
1612 adjust_glyphs (f);
1613 }
1614
1615
1616 /* Set the number of lines used for the tool bar of frame F to VALUE.
1617 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1618 is the old number of tool bar lines. This function changes the
1619 height of all windows on frame F to match the new tool bar height.
1620 The frame's height doesn't change. */
1621
1622 void
1623 x_set_tool_bar_lines (f, value, oldval)
1624 struct frame *f;
1625 Lisp_Object value, oldval;
1626 {
1627 int delta, nlines, root_height;
1628 Lisp_Object root_window;
1629
1630 /* Treat tool bars like menu bars. */
1631 if (FRAME_MINIBUF_ONLY_P (f))
1632 return;
1633
1634 /* Use VALUE only if an integer >= 0. */
1635 if (INTEGERP (value) && XINT (value) >= 0)
1636 nlines = XFASTINT (value);
1637 else
1638 nlines = 0;
1639
1640 #ifdef USE_GTK
1641 FRAME_TOOL_BAR_LINES (f) = 0;
1642 if (nlines)
1643 {
1644 FRAME_EXTERNAL_TOOL_BAR (f) = 1;
1645 if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1646 /* Make sure next redisplay shows the tool bar. */
1647 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1648 update_frame_tool_bar (f);
1649 }
1650 else
1651 {
1652 if (FRAME_EXTERNAL_TOOL_BAR (f))
1653 free_frame_tool_bar (f);
1654 FRAME_EXTERNAL_TOOL_BAR (f) = 0;
1655 }
1656
1657 return;
1658 #endif
1659
1660 /* Make sure we redisplay all windows in this frame. */
1661 ++windows_or_buffers_changed;
1662
1663 delta = nlines - FRAME_TOOL_BAR_LINES (f);
1664
1665 /* Don't resize the tool-bar to more than we have room for. */
1666 root_window = FRAME_ROOT_WINDOW (f);
1667 root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
1668 if (root_height - delta < 1)
1669 {
1670 delta = root_height - 1;
1671 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
1672 }
1673
1674 FRAME_TOOL_BAR_LINES (f) = nlines;
1675 change_window_heights (root_window, delta);
1676 adjust_glyphs (f);
1677
1678 /* We also have to make sure that the internal border at the top of
1679 the frame, below the menu bar or tool bar, is redrawn when the
1680 tool bar disappears. This is so because the internal border is
1681 below the tool bar if one is displayed, but is below the menu bar
1682 if there isn't a tool bar. The tool bar draws into the area
1683 below the menu bar. */
1684 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
1685 {
1686 updating_frame = f;
1687 clear_frame ();
1688 clear_current_matrices (f);
1689 updating_frame = NULL;
1690 }
1691
1692 /* If the tool bar gets smaller, the internal border below it
1693 has to be cleared. It was formerly part of the display
1694 of the larger tool bar, and updating windows won't clear it. */
1695 if (delta < 0)
1696 {
1697 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1698 int width = FRAME_PIXEL_WIDTH (f);
1699 int y = nlines * FRAME_LINE_HEIGHT (f);
1700
1701 BLOCK_INPUT;
1702 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1703 0, y, width, height, False);
1704 UNBLOCK_INPUT;
1705
1706 if (WINDOWP (f->tool_bar_window))
1707 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1708 }
1709 }
1710
1711
1712 /* Set the foreground color for scroll bars on frame F to VALUE.
1713 VALUE should be a string, a color name. If it isn't a string or
1714 isn't a valid color name, do nothing. OLDVAL is the old value of
1715 the frame parameter. */
1716
1717 void
1718 x_set_scroll_bar_foreground (f, value, oldval)
1719 struct frame *f;
1720 Lisp_Object value, oldval;
1721 {
1722 unsigned long pixel;
1723
1724 if (STRINGP (value))
1725 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1726 else
1727 pixel = -1;
1728
1729 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1730 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1731
1732 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1733 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1734 {
1735 /* Remove all scroll bars because they have wrong colors. */
1736 if (condemn_scroll_bars_hook)
1737 (*condemn_scroll_bars_hook) (f);
1738 if (judge_scroll_bars_hook)
1739 (*judge_scroll_bars_hook) (f);
1740
1741 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
1742 redraw_frame (f);
1743 }
1744 }
1745
1746
1747 /* Set the background color for scroll bars on frame F to VALUE VALUE
1748 should be a string, a color name. If it isn't a string or isn't a
1749 valid color name, do nothing. OLDVAL is the old value of the frame
1750 parameter. */
1751
1752 void
1753 x_set_scroll_bar_background (f, value, oldval)
1754 struct frame *f;
1755 Lisp_Object value, oldval;
1756 {
1757 unsigned long pixel;
1758
1759 if (STRINGP (value))
1760 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1761 else
1762 pixel = -1;
1763
1764 if (f->output_data.x->scroll_bar_background_pixel != -1)
1765 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1766
1767 #ifdef USE_TOOLKIT_SCROLL_BARS
1768 /* Scrollbar shadow colors. */
1769 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1770 {
1771 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1772 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1773 }
1774 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1775 {
1776 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1777 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1778 }
1779 #endif /* USE_TOOLKIT_SCROLL_BARS */
1780
1781 f->output_data.x->scroll_bar_background_pixel = pixel;
1782 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1783 {
1784 /* Remove all scroll bars because they have wrong colors. */
1785 if (condemn_scroll_bars_hook)
1786 (*condemn_scroll_bars_hook) (f);
1787 if (judge_scroll_bars_hook)
1788 (*judge_scroll_bars_hook) (f);
1789
1790 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
1791 redraw_frame (f);
1792 }
1793 }
1794
1795 \f
1796 /* Encode Lisp string STRING as a text in a format appropriate for
1797 XICCC (X Inter Client Communication Conventions).
1798
1799 If STRING contains only ASCII characters, do no conversion and
1800 return the string data of STRING. Otherwise, encode the text by
1801 CODING_SYSTEM, and return a newly allocated memory area which
1802 should be freed by `xfree' by a caller.
1803
1804 SELECTIONP non-zero means the string is being encoded for an X
1805 selection, so it is safe to run pre-write conversions (which
1806 may run Lisp code).
1807
1808 Store the byte length of resulting text in *TEXT_BYTES.
1809
1810 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
1811 which means that the `encoding' of the result can be `STRING'.
1812 Otherwise store 0 in *STRINGP, which means that the `encoding' of
1813 the result should be `COMPOUND_TEXT'. */
1814
1815 unsigned char *
1816 x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
1817 Lisp_Object string, coding_system;
1818 int *text_bytes, *stringp;
1819 int selectionp;
1820 {
1821 unsigned char *str = SDATA (string);
1822 int chars = SCHARS (string);
1823 int bytes = SBYTES (string);
1824 int charset_info;
1825 int bufsize;
1826 unsigned char *buf;
1827 struct coding_system coding;
1828 extern Lisp_Object Qcompound_text_with_extensions;
1829
1830 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
1831 if (charset_info == 0)
1832 {
1833 /* No multibyte character in OBJ. We need not encode it. */
1834 *text_bytes = bytes;
1835 *stringp = 1;
1836 return str;
1837 }
1838
1839 setup_coding_system (coding_system, &coding);
1840 if (selectionp
1841 && SYMBOLP (coding.pre_write_conversion)
1842 && !NILP (Ffboundp (coding.pre_write_conversion)))
1843 {
1844 string = run_pre_post_conversion_on_str (string, &coding, 1);
1845 str = SDATA (string);
1846 chars = SCHARS (string);
1847 bytes = SBYTES (string);
1848 }
1849 coding.src_multibyte = 1;
1850 coding.dst_multibyte = 0;
1851 coding.mode |= CODING_MODE_LAST_BLOCK;
1852 if (coding.type == coding_type_iso2022)
1853 coding.flags |= CODING_FLAG_ISO_SAFE;
1854 /* We suppress producing escape sequences for composition. */
1855 coding.composing = COMPOSITION_DISABLED;
1856 bufsize = encoding_buffer_size (&coding, bytes);
1857 buf = (unsigned char *) xmalloc (bufsize);
1858 encode_coding (&coding, str, buf, bytes, bufsize);
1859 *text_bytes = coding.produced;
1860 *stringp = (charset_info == 1
1861 || (!EQ (coding_system, Qcompound_text)
1862 && !EQ (coding_system, Qcompound_text_with_extensions)));
1863 return buf;
1864 }
1865
1866 \f
1867 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1868 x_id_name.
1869
1870 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1871 name; if NAME is a string, set F's name to NAME and set
1872 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1873
1874 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1875 suggesting a new name, which lisp code should override; if
1876 F->explicit_name is set, ignore the new name; otherwise, set it. */
1877
1878 void
1879 x_set_name (f, name, explicit)
1880 struct frame *f;
1881 Lisp_Object name;
1882 int explicit;
1883 {
1884 /* Make sure that requests from lisp code override requests from
1885 Emacs redisplay code. */
1886 if (explicit)
1887 {
1888 /* If we're switching from explicit to implicit, we had better
1889 update the mode lines and thereby update the title. */
1890 if (f->explicit_name && NILP (name))
1891 update_mode_lines = 1;
1892
1893 f->explicit_name = ! NILP (name);
1894 }
1895 else if (f->explicit_name)
1896 return;
1897
1898 /* If NAME is nil, set the name to the x_id_name. */
1899 if (NILP (name))
1900 {
1901 /* Check for no change needed in this very common case
1902 before we do any consing. */
1903 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1904 SDATA (f->name)))
1905 return;
1906 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
1907 }
1908 else
1909 CHECK_STRING (name);
1910
1911 /* Don't change the name if it's already NAME. */
1912 if (! NILP (Fstring_equal (name, f->name)))
1913 return;
1914
1915 f->name = name;
1916
1917 /* For setting the frame title, the title parameter should override
1918 the name parameter. */
1919 if (! NILP (f->title))
1920 name = f->title;
1921
1922 if (FRAME_X_WINDOW (f))
1923 {
1924 BLOCK_INPUT;
1925 #ifdef HAVE_X11R4
1926 {
1927 XTextProperty text, icon;
1928 int bytes, stringp;
1929 Lisp_Object coding_system;
1930
1931 /* Note: Encoding strategy
1932
1933 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1934 text.encoding. But, there are non-internationalized window
1935 managers which don't support that encoding. So, if NAME
1936 contains only ASCII and 8859-1 characters, encode it by
1937 iso-latin-1, and use "STRING" in text.encoding hoping that
1938 such window managers at least analyze this format correctly,
1939 i.e. treat 8-bit bytes as 8859-1 characters.
1940
1941 We may also be able to use "UTF8_STRING" in text.encoding
1942 in the future which can encode all Unicode characters.
1943 But, for the moment, there's no way to know that the
1944 current window manager supports it or not. */
1945 coding_system = Qcompound_text;
1946 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
1947 text.encoding = (stringp ? XA_STRING
1948 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1949 text.format = 8;
1950 text.nitems = bytes;
1951
1952 if (NILP (f->icon_name))
1953 {
1954 icon = text;
1955 }
1956 else
1957 {
1958 /* See the above comment "Note: Encoding strategy". */
1959 icon.value = x_encode_text (f->icon_name, coding_system, 0,
1960 &bytes, &stringp);
1961 icon.encoding = (stringp ? XA_STRING
1962 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1963 icon.format = 8;
1964 icon.nitems = bytes;
1965 }
1966 #ifdef USE_GTK
1967 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1968 SDATA (name));
1969 #else /* not USE_GTK */
1970 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1971 #endif /* not USE_GTK */
1972
1973 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
1974
1975 if (!NILP (f->icon_name)
1976 && icon.value != (unsigned char *) SDATA (f->icon_name))
1977 xfree (icon.value);
1978 if (text.value != (unsigned char *) SDATA (name))
1979 xfree (text.value);
1980 }
1981 #else /* not HAVE_X11R4 */
1982 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1983 SDATA (name));
1984 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1985 SDATA (name));
1986 #endif /* not HAVE_X11R4 */
1987 UNBLOCK_INPUT;
1988 }
1989 }
1990
1991 /* This function should be called when the user's lisp code has
1992 specified a name for the frame; the name will override any set by the
1993 redisplay code. */
1994 void
1995 x_explicitly_set_name (f, arg, oldval)
1996 FRAME_PTR f;
1997 Lisp_Object arg, oldval;
1998 {
1999 x_set_name (f, arg, 1);
2000 }
2001
2002 /* This function should be called by Emacs redisplay code to set the
2003 name; names set this way will never override names set by the user's
2004 lisp code. */
2005 void
2006 x_implicitly_set_name (f, arg, oldval)
2007 FRAME_PTR f;
2008 Lisp_Object arg, oldval;
2009 {
2010 x_set_name (f, arg, 0);
2011 }
2012 \f
2013 /* Change the title of frame F to NAME.
2014 If NAME is nil, use the frame name as the title.
2015
2016 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2017 name; if NAME is a string, set F's name to NAME and set
2018 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2019
2020 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2021 suggesting a new name, which lisp code should override; if
2022 F->explicit_name is set, ignore the new name; otherwise, set it. */
2023
2024 void
2025 x_set_title (f, name, old_name)
2026 struct frame *f;
2027 Lisp_Object name, old_name;
2028 {
2029 /* Don't change the title if it's already NAME. */
2030 if (EQ (name, f->title))
2031 return;
2032
2033 update_mode_lines = 1;
2034
2035 f->title = name;
2036
2037 if (NILP (name))
2038 name = f->name;
2039 else
2040 CHECK_STRING (name);
2041
2042 if (FRAME_X_WINDOW (f))
2043 {
2044 BLOCK_INPUT;
2045 #ifdef HAVE_X11R4
2046 {
2047 XTextProperty text, icon;
2048 int bytes, stringp;
2049 Lisp_Object coding_system;
2050
2051 coding_system = Qcompound_text;
2052 /* See the comment "Note: Encoding strategy" in x_set_name. */
2053 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
2054 text.encoding = (stringp ? XA_STRING
2055 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2056 text.format = 8;
2057 text.nitems = bytes;
2058
2059 if (NILP (f->icon_name))
2060 {
2061 icon = text;
2062 }
2063 else
2064 {
2065 /* See the comment "Note: Encoding strategy" in x_set_name. */
2066 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2067 &bytes, &stringp);
2068 icon.encoding = (stringp ? XA_STRING
2069 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2070 icon.format = 8;
2071 icon.nitems = bytes;
2072 }
2073
2074 #ifdef USE_GTK
2075 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
2076 SDATA (name));
2077 #else /* not USE_GTK */
2078 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
2079 #endif /* not USE_GTK */
2080
2081 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
2082 &icon);
2083
2084 if (!NILP (f->icon_name)
2085 && icon.value != (unsigned char *) SDATA (f->icon_name))
2086 xfree (icon.value);
2087 if (text.value != (unsigned char *) SDATA (name))
2088 xfree (text.value);
2089 }
2090 #else /* not HAVE_X11R4 */
2091 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2092 SDATA (name));
2093 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2094 SDATA (name));
2095 #endif /* not HAVE_X11R4 */
2096 UNBLOCK_INPUT;
2097 }
2098 }
2099
2100 void
2101 x_set_scroll_bar_default_width (f)
2102 struct frame *f;
2103 {
2104 int wid = FRAME_COLUMN_WIDTH (f);
2105
2106 #ifdef USE_TOOLKIT_SCROLL_BARS
2107 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2108 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2109 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2110 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = width;
2111 #else
2112 /* Make the actual width at least 14 pixels and a multiple of a
2113 character width. */
2114 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2115
2116 /* Use all of that space (aside from required margins) for the
2117 scroll bar. */
2118 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
2119 #endif
2120 }
2121
2122 \f
2123 /* Record in frame F the specified or default value according to ALIST
2124 of the parameter named PROP (a Lisp symbol). If no value is
2125 specified for PROP, look for an X default for XPROP on the frame
2126 named NAME. If that is not found either, use the value DEFLT. */
2127
2128 static Lisp_Object
2129 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2130 foreground_p)
2131 struct frame *f;
2132 Lisp_Object alist;
2133 Lisp_Object prop;
2134 char *xprop;
2135 char *xclass;
2136 int foreground_p;
2137 {
2138 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2139 Lisp_Object tem;
2140
2141 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2142 if (EQ (tem, Qunbound))
2143 {
2144 #ifdef USE_TOOLKIT_SCROLL_BARS
2145
2146 /* See if an X resource for the scroll bar color has been
2147 specified. */
2148 tem = display_x_get_resource (dpyinfo,
2149 build_string (foreground_p
2150 ? "foreground"
2151 : "background"),
2152 empty_string,
2153 build_string ("verticalScrollBar"),
2154 empty_string);
2155 if (!STRINGP (tem))
2156 {
2157 /* If nothing has been specified, scroll bars will use a
2158 toolkit-dependent default. Because these defaults are
2159 difficult to get at without actually creating a scroll
2160 bar, use nil to indicate that no color has been
2161 specified. */
2162 tem = Qnil;
2163 }
2164
2165 #else /* not USE_TOOLKIT_SCROLL_BARS */
2166
2167 tem = Qnil;
2168
2169 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2170 }
2171
2172 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2173 return tem;
2174 }
2175
2176
2177
2178 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2179
2180 Status
2181 XSetWMProtocols (dpy, w, protocols, count)
2182 Display *dpy;
2183 Window w;
2184 Atom *protocols;
2185 int count;
2186 {
2187 Atom prop;
2188 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2189 if (prop == None) return False;
2190 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2191 (unsigned char *) protocols, count);
2192 return True;
2193 }
2194 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2195 \f
2196 #ifdef USE_X_TOOLKIT
2197
2198 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2199 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2200 already be present because of the toolkit (Motif adds some of them,
2201 for example, but Xt doesn't). */
2202
2203 static void
2204 hack_wm_protocols (f, widget)
2205 FRAME_PTR f;
2206 Widget widget;
2207 {
2208 Display *dpy = XtDisplay (widget);
2209 Window w = XtWindow (widget);
2210 int need_delete = 1;
2211 int need_focus = 1;
2212 int need_save = 1;
2213
2214 BLOCK_INPUT;
2215 {
2216 Atom type, *atoms = 0;
2217 int format = 0;
2218 unsigned long nitems = 0;
2219 unsigned long bytes_after;
2220
2221 if ((XGetWindowProperty (dpy, w,
2222 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2223 (long)0, (long)100, False, XA_ATOM,
2224 &type, &format, &nitems, &bytes_after,
2225 (unsigned char **) &atoms)
2226 == Success)
2227 && format == 32 && type == XA_ATOM)
2228 while (nitems > 0)
2229 {
2230 nitems--;
2231 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2232 need_delete = 0;
2233 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2234 need_focus = 0;
2235 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2236 need_save = 0;
2237 }
2238 if (atoms) XFree ((char *) atoms);
2239 }
2240 {
2241 Atom props [10];
2242 int count = 0;
2243 if (need_delete)
2244 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2245 if (need_focus)
2246 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2247 if (need_save)
2248 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2249 if (count)
2250 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2251 XA_ATOM, 32, PropModeAppend,
2252 (unsigned char *) props, count);
2253 }
2254 UNBLOCK_INPUT;
2255 }
2256 #endif
2257
2258
2259 \f
2260 /* Support routines for XIC (X Input Context). */
2261
2262 #ifdef HAVE_X_I18N
2263
2264 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
2265 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
2266
2267
2268 /* Supported XIM styles, ordered by preference. */
2269
2270 static XIMStyle supported_xim_styles[] =
2271 {
2272 XIMPreeditPosition | XIMStatusArea,
2273 XIMPreeditPosition | XIMStatusNothing,
2274 XIMPreeditPosition | XIMStatusNone,
2275 XIMPreeditNothing | XIMStatusArea,
2276 XIMPreeditNothing | XIMStatusNothing,
2277 XIMPreeditNothing | XIMStatusNone,
2278 XIMPreeditNone | XIMStatusArea,
2279 XIMPreeditNone | XIMStatusNothing,
2280 XIMPreeditNone | XIMStatusNone,
2281 0,
2282 };
2283
2284
2285 /* Create an X fontset on frame F with base font name
2286 BASE_FONTNAME.. */
2287
2288 static XFontSet
2289 xic_create_xfontset (f, base_fontname)
2290 struct frame *f;
2291 char *base_fontname;
2292 {
2293 XFontSet xfs;
2294 char **missing_list;
2295 int missing_count;
2296 char *def_string;
2297
2298 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
2299 base_fontname, &missing_list,
2300 &missing_count, &def_string);
2301 if (missing_list)
2302 XFreeStringList (missing_list);
2303
2304 /* No need to free def_string. */
2305 return xfs;
2306 }
2307
2308
2309 /* Value is the best input style, given user preferences USER (already
2310 checked to be supported by Emacs), and styles supported by the
2311 input method XIM. */
2312
2313 static XIMStyle
2314 best_xim_style (user, xim)
2315 XIMStyles *user;
2316 XIMStyles *xim;
2317 {
2318 int i, j;
2319
2320 for (i = 0; i < user->count_styles; ++i)
2321 for (j = 0; j < xim->count_styles; ++j)
2322 if (user->supported_styles[i] == xim->supported_styles[j])
2323 return user->supported_styles[i];
2324
2325 /* Return the default style. */
2326 return XIMPreeditNothing | XIMStatusNothing;
2327 }
2328
2329 /* Create XIC for frame F. */
2330
2331 static XIMStyle xic_style;
2332
2333 void
2334 create_frame_xic (f)
2335 struct frame *f;
2336 {
2337 XIM xim;
2338 XIC xic = NULL;
2339 XFontSet xfs = NULL;
2340
2341 if (FRAME_XIC (f))
2342 return;
2343
2344 xim = FRAME_X_XIM (f);
2345 if (xim)
2346 {
2347 XRectangle s_area;
2348 XPoint spot;
2349 XVaNestedList preedit_attr;
2350 XVaNestedList status_attr;
2351 char *base_fontname;
2352 int fontset;
2353
2354 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2355 spot.x = 0; spot.y = 1;
2356 /* Create X fontset. */
2357 fontset = FRAME_FONTSET (f);
2358 if (fontset < 0)
2359 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2360 else
2361 {
2362 /* Determine the base fontname from the ASCII font name of
2363 FONTSET. */
2364 char *ascii_font = (char *) SDATA (fontset_ascii (fontset));
2365 char *p = ascii_font;
2366 int i;
2367
2368 for (i = 0; *p; p++)
2369 if (*p == '-') i++;
2370 if (i != 14)
2371 /* As the font name doesn't conform to XLFD, we can't
2372 modify it to get a suitable base fontname for the
2373 frame. */
2374 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2375 else
2376 {
2377 int len = strlen (ascii_font) + 1;
2378 char *p1 = NULL;
2379
2380 for (i = 0, p = ascii_font; i < 8; p++)
2381 {
2382 if (*p == '-')
2383 {
2384 i++;
2385 if (i == 3)
2386 p1 = p + 1;
2387 }
2388 }
2389 base_fontname = (char *) alloca (len);
2390 bzero (base_fontname, len);
2391 strcpy (base_fontname, "-*-*-");
2392 bcopy (p1, base_fontname + 5, p - p1);
2393 strcat (base_fontname, "*-*-*-*-*-*-*");
2394 }
2395 }
2396 xfs = xic_create_xfontset (f, base_fontname);
2397
2398 /* Determine XIC style. */
2399 if (xic_style == 0)
2400 {
2401 XIMStyles supported_list;
2402 supported_list.count_styles = (sizeof supported_xim_styles
2403 / sizeof supported_xim_styles[0]);
2404 supported_list.supported_styles = supported_xim_styles;
2405 xic_style = best_xim_style (&supported_list,
2406 FRAME_X_XIM_STYLES (f));
2407 }
2408
2409 preedit_attr = XVaCreateNestedList (0,
2410 XNFontSet, xfs,
2411 XNForeground,
2412 FRAME_FOREGROUND_PIXEL (f),
2413 XNBackground,
2414 FRAME_BACKGROUND_PIXEL (f),
2415 (xic_style & XIMPreeditPosition
2416 ? XNSpotLocation
2417 : NULL),
2418 &spot,
2419 NULL);
2420 status_attr = XVaCreateNestedList (0,
2421 XNArea,
2422 &s_area,
2423 XNFontSet,
2424 xfs,
2425 XNForeground,
2426 FRAME_FOREGROUND_PIXEL (f),
2427 XNBackground,
2428 FRAME_BACKGROUND_PIXEL (f),
2429 NULL);
2430
2431 xic = XCreateIC (xim,
2432 XNInputStyle, xic_style,
2433 XNClientWindow, FRAME_X_WINDOW(f),
2434 XNFocusWindow, FRAME_X_WINDOW(f),
2435 XNStatusAttributes, status_attr,
2436 XNPreeditAttributes, preedit_attr,
2437 NULL);
2438 XFree (preedit_attr);
2439 XFree (status_attr);
2440 }
2441
2442 FRAME_XIC (f) = xic;
2443 FRAME_XIC_STYLE (f) = xic_style;
2444 FRAME_XIC_FONTSET (f) = xfs;
2445 }
2446
2447
2448 /* Destroy XIC and free XIC fontset of frame F, if any. */
2449
2450 void
2451 free_frame_xic (f)
2452 struct frame *f;
2453 {
2454 if (FRAME_XIC (f) == NULL)
2455 return;
2456
2457 XDestroyIC (FRAME_XIC (f));
2458 if (FRAME_XIC_FONTSET (f))
2459 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2460
2461 FRAME_XIC (f) = NULL;
2462 FRAME_XIC_FONTSET (f) = NULL;
2463 }
2464
2465
2466 /* Place preedit area for XIC of window W's frame to specified
2467 pixel position X/Y. X and Y are relative to window W. */
2468
2469 void
2470 xic_set_preeditarea (w, x, y)
2471 struct window *w;
2472 int x, y;
2473 {
2474 struct frame *f = XFRAME (w->frame);
2475 XVaNestedList attr;
2476 XPoint spot;
2477
2478 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
2479 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2480 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2481 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2482 XFree (attr);
2483 }
2484
2485
2486 /* Place status area for XIC in bottom right corner of frame F.. */
2487
2488 void
2489 xic_set_statusarea (f)
2490 struct frame *f;
2491 {
2492 XIC xic = FRAME_XIC (f);
2493 XVaNestedList attr;
2494 XRectangle area;
2495 XRectangle *needed;
2496
2497 /* Negotiate geometry of status area. If input method has existing
2498 status area, use its current size. */
2499 area.x = area.y = area.width = area.height = 0;
2500 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2501 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2502 XFree (attr);
2503
2504 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2505 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2506 XFree (attr);
2507
2508 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2509 {
2510 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2511 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2512 XFree (attr);
2513 }
2514
2515 area.width = needed->width;
2516 area.height = needed->height;
2517 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2518 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2519 - FRAME_MENUBAR_HEIGHT (f)
2520 - FRAME_TOOLBAR_HEIGHT (f)
2521 - FRAME_INTERNAL_BORDER_WIDTH (f));
2522 XFree (needed);
2523
2524 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2525 XSetICValues(xic, XNStatusAttributes, attr, NULL);
2526 XFree (attr);
2527 }
2528
2529
2530 /* Set X fontset for XIC of frame F, using base font name
2531 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2532
2533 void
2534 xic_set_xfontset (f, base_fontname)
2535 struct frame *f;
2536 char *base_fontname;
2537 {
2538 XVaNestedList attr;
2539 XFontSet xfs;
2540
2541 xfs = xic_create_xfontset (f, base_fontname);
2542
2543 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2544 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2545 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2546 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2547 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2548 XFree (attr);
2549
2550 if (FRAME_XIC_FONTSET (f))
2551 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2552 FRAME_XIC_FONTSET (f) = xfs;
2553 }
2554
2555 #endif /* HAVE_X_I18N */
2556
2557
2558 \f
2559 #ifdef USE_X_TOOLKIT
2560
2561 /* Create and set up the X widget for frame F. */
2562
2563 static void
2564 x_window (f, window_prompting, minibuffer_only)
2565 struct frame *f;
2566 long window_prompting;
2567 int minibuffer_only;
2568 {
2569 XClassHint class_hints;
2570 XSetWindowAttributes attributes;
2571 unsigned long attribute_mask;
2572 Widget shell_widget;
2573 Widget pane_widget;
2574 Widget frame_widget;
2575 Arg al [25];
2576 int ac;
2577
2578 BLOCK_INPUT;
2579
2580 /* Use the resource name as the top-level widget name
2581 for looking up resources. Make a non-Lisp copy
2582 for the window manager, so GC relocation won't bother it.
2583
2584 Elsewhere we specify the window name for the window manager. */
2585
2586 {
2587 char *str = (char *) SDATA (Vx_resource_name);
2588 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2589 strcpy (f->namebuf, str);
2590 }
2591
2592 ac = 0;
2593 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2594 XtSetArg (al[ac], XtNinput, 1); ac++;
2595 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2596 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2597 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2598 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2599 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2600 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2601 applicationShellWidgetClass,
2602 FRAME_X_DISPLAY (f), al, ac);
2603
2604 f->output_data.x->widget = shell_widget;
2605 /* maybe_set_screen_title_format (shell_widget); */
2606
2607 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2608 (widget_value *) NULL,
2609 shell_widget, False,
2610 (lw_callback) NULL,
2611 (lw_callback) NULL,
2612 (lw_callback) NULL,
2613 (lw_callback) NULL);
2614
2615 ac = 0;
2616 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2617 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2618 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2619 XtSetValues (pane_widget, al, ac);
2620 f->output_data.x->column_widget = pane_widget;
2621
2622 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2623 the emacs screen when changing menubar. This reduces flickering. */
2624
2625 ac = 0;
2626 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2627 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2628 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2629 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2630 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
2631 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2632 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2633 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2634 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
2635 al, ac);
2636
2637 f->output_data.x->edit_widget = frame_widget;
2638
2639 XtManageChild (frame_widget);
2640
2641 /* Do some needed geometry management. */
2642 {
2643 int len;
2644 char *tem, shell_position[32];
2645 Arg al[2];
2646 int ac = 0;
2647 int extra_borders = 0;
2648 int menubar_size
2649 = (f->output_data.x->menubar_widget
2650 ? (f->output_data.x->menubar_widget->core.height
2651 + f->output_data.x->menubar_widget->core.border_width)
2652 : 0);
2653
2654 #if 0 /* Experimentally, we now get the right results
2655 for -geometry -0-0 without this. 24 Aug 96, rms. */
2656 if (FRAME_EXTERNAL_MENU_BAR (f))
2657 {
2658 Dimension ibw = 0;
2659 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2660 menubar_size += ibw;
2661 }
2662 #endif
2663
2664 f->output_data.x->menubar_height = menubar_size;
2665
2666 #ifndef USE_LUCID
2667 /* Motif seems to need this amount added to the sizes
2668 specified for the shell widget. The Athena/Lucid widgets don't.
2669 Both conclusions reached experimentally. -- rms. */
2670 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2671 &extra_borders, NULL);
2672 extra_borders *= 2;
2673 #endif
2674
2675 /* Convert our geometry parameters into a geometry string
2676 and specify it.
2677 Note that we do not specify here whether the position
2678 is a user-specified or program-specified one.
2679 We pass that information later, in x_wm_set_size_hints. */
2680 {
2681 int left = f->left_pos;
2682 int xneg = window_prompting & XNegative;
2683 int top = f->top_pos;
2684 int yneg = window_prompting & YNegative;
2685 if (xneg)
2686 left = -left;
2687 if (yneg)
2688 top = -top;
2689
2690 if (window_prompting & USPosition)
2691 sprintf (shell_position, "=%dx%d%c%d%c%d",
2692 FRAME_PIXEL_WIDTH (f) + extra_borders,
2693 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2694 (xneg ? '-' : '+'), left,
2695 (yneg ? '-' : '+'), top);
2696 else
2697 sprintf (shell_position, "=%dx%d",
2698 FRAME_PIXEL_WIDTH (f) + extra_borders,
2699 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2700 }
2701
2702 len = strlen (shell_position) + 1;
2703 /* We don't free this because we don't know whether
2704 it is safe to free it while the frame exists.
2705 It isn't worth the trouble of arranging to free it
2706 when the frame is deleted. */
2707 tem = (char *) xmalloc (len);
2708 strncpy (tem, shell_position, len);
2709 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2710 XtSetValues (shell_widget, al, ac);
2711 }
2712
2713 XtManageChild (pane_widget);
2714 XtRealizeWidget (shell_widget);
2715
2716 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2717
2718 validate_x_resource_name ();
2719
2720 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2721 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2722 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2723
2724 #ifdef HAVE_X_I18N
2725 FRAME_XIC (f) = NULL;
2726 if (use_xim)
2727 create_frame_xic (f);
2728 #endif
2729
2730 f->output_data.x->wm_hints.input = True;
2731 f->output_data.x->wm_hints.flags |= InputHint;
2732 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2733 &f->output_data.x->wm_hints);
2734
2735 hack_wm_protocols (f, shell_widget);
2736
2737 #ifdef HACK_EDITRES
2738 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2739 #endif
2740
2741 /* Do a stupid property change to force the server to generate a
2742 PropertyNotify event so that the event_stream server timestamp will
2743 be initialized to something relevant to the time we created the window.
2744 */
2745 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2746 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2747 XA_ATOM, 32, PropModeAppend,
2748 (unsigned char*) NULL, 0);
2749
2750 /* Make all the standard events reach the Emacs frame. */
2751 attributes.event_mask = STANDARD_EVENT_SET;
2752
2753 #ifdef HAVE_X_I18N
2754 if (FRAME_XIC (f))
2755 {
2756 /* XIM server might require some X events. */
2757 unsigned long fevent = NoEventMask;
2758 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2759 attributes.event_mask |= fevent;
2760 }
2761 #endif /* HAVE_X_I18N */
2762
2763 attribute_mask = CWEventMask;
2764 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2765 attribute_mask, &attributes);
2766
2767 XtMapWidget (frame_widget);
2768
2769 /* x_set_name normally ignores requests to set the name if the
2770 requested name is the same as the current name. This is the one
2771 place where that assumption isn't correct; f->name is set, but
2772 the X server hasn't been told. */
2773 {
2774 Lisp_Object name;
2775 int explicit = f->explicit_name;
2776
2777 f->explicit_name = 0;
2778 name = f->name;
2779 f->name = Qnil;
2780 x_set_name (f, name, explicit);
2781 }
2782
2783 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2784 f->output_data.x->text_cursor);
2785
2786 UNBLOCK_INPUT;
2787
2788 /* This is a no-op, except under Motif. Make sure main areas are
2789 set to something reasonable, in case we get an error later. */
2790 lw_set_main_areas (pane_widget, 0, frame_widget);
2791 }
2792
2793 #else /* not USE_X_TOOLKIT */
2794 #ifdef USE_GTK
2795 void
2796 x_window (f)
2797 FRAME_PTR f;
2798 {
2799 if (! xg_create_frame_widgets (f))
2800 error ("Unable to create window");
2801
2802 #ifdef HAVE_X_I18N
2803 FRAME_XIC (f) = NULL;
2804 if (use_xim)
2805 {
2806 BLOCK_INPUT;
2807 create_frame_xic (f);
2808 if (FRAME_XIC (f))
2809 {
2810 /* XIM server might require some X events. */
2811 unsigned long fevent = NoEventMask;
2812 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2813
2814 if (fevent != NoEventMask)
2815 {
2816 XSetWindowAttributes attributes;
2817 XWindowAttributes wattr;
2818 unsigned long attribute_mask;
2819
2820 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2821 &wattr);
2822 attributes.event_mask = wattr.your_event_mask | fevent;
2823 attribute_mask = CWEventMask;
2824 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2825 attribute_mask, &attributes);
2826 }
2827 }
2828 UNBLOCK_INPUT;
2829 }
2830 #endif
2831 }
2832
2833 #else /*! USE_GTK */
2834 /* Create and set up the X window for frame F. */
2835
2836 void
2837 x_window (f)
2838 struct frame *f;
2839
2840 {
2841 XClassHint class_hints;
2842 XSetWindowAttributes attributes;
2843 unsigned long attribute_mask;
2844
2845 attributes.background_pixel = f->output_data.x->background_pixel;
2846 attributes.border_pixel = f->output_data.x->border_pixel;
2847 attributes.bit_gravity = StaticGravity;
2848 attributes.backing_store = NotUseful;
2849 attributes.save_under = True;
2850 attributes.event_mask = STANDARD_EVENT_SET;
2851 attributes.colormap = FRAME_X_COLORMAP (f);
2852 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2853 | CWColormap);
2854
2855 BLOCK_INPUT;
2856 FRAME_X_WINDOW (f)
2857 = XCreateWindow (FRAME_X_DISPLAY (f),
2858 f->output_data.x->parent_desc,
2859 f->left_pos,
2860 f->top_pos,
2861 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2862 f->border_width,
2863 CopyFromParent, /* depth */
2864 InputOutput, /* class */
2865 FRAME_X_VISUAL (f),
2866 attribute_mask, &attributes);
2867
2868 #ifdef HAVE_X_I18N
2869 if (use_xim)
2870 {
2871 create_frame_xic (f);
2872 if (FRAME_XIC (f))
2873 {
2874 /* XIM server might require some X events. */
2875 unsigned long fevent = NoEventMask;
2876 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2877 attributes.event_mask |= fevent;
2878 attribute_mask = CWEventMask;
2879 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2880 attribute_mask, &attributes);
2881 }
2882 }
2883 #endif /* HAVE_X_I18N */
2884
2885 validate_x_resource_name ();
2886
2887 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2888 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2889 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
2890
2891 /* The menubar is part of the ordinary display;
2892 it does not count in addition to the height of the window. */
2893 f->output_data.x->menubar_height = 0;
2894
2895 /* This indicates that we use the "Passive Input" input model.
2896 Unless we do this, we don't get the Focus{In,Out} events that we
2897 need to draw the cursor correctly. Accursed bureaucrats.
2898 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2899
2900 f->output_data.x->wm_hints.input = True;
2901 f->output_data.x->wm_hints.flags |= InputHint;
2902 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2903 &f->output_data.x->wm_hints);
2904 f->output_data.x->wm_hints.icon_pixmap = None;
2905
2906 /* Request "save yourself" and "delete window" commands from wm. */
2907 {
2908 Atom protocols[2];
2909 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2910 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2911 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
2912 }
2913
2914 /* x_set_name normally ignores requests to set the name if the
2915 requested name is the same as the current name. This is the one
2916 place where that assumption isn't correct; f->name is set, but
2917 the X server hasn't been told. */
2918 {
2919 Lisp_Object name;
2920 int explicit = f->explicit_name;
2921
2922 f->explicit_name = 0;
2923 name = f->name;
2924 f->name = Qnil;
2925 x_set_name (f, name, explicit);
2926 }
2927
2928 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2929 f->output_data.x->text_cursor);
2930
2931 UNBLOCK_INPUT;
2932
2933 if (FRAME_X_WINDOW (f) == 0)
2934 error ("Unable to create window");
2935 }
2936
2937 #endif /* not USE_GTK */
2938 #endif /* not USE_X_TOOLKIT */
2939
2940 /* Handle the icon stuff for this window. Perhaps later we might
2941 want an x_set_icon_position which can be called interactively as
2942 well. */
2943
2944 static void
2945 x_icon (f, parms)
2946 struct frame *f;
2947 Lisp_Object parms;
2948 {
2949 Lisp_Object icon_x, icon_y;
2950 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2951
2952 /* Set the position of the icon. Note that twm groups all
2953 icons in an icon window. */
2954 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2955 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2956 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2957 {
2958 CHECK_NUMBER (icon_x);
2959 CHECK_NUMBER (icon_y);
2960 }
2961 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2962 error ("Both left and top icon corners of icon must be specified");
2963
2964 BLOCK_INPUT;
2965
2966 if (! EQ (icon_x, Qunbound))
2967 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2968
2969 /* Start up iconic or window? */
2970 x_wm_set_window_state
2971 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
2972 Qicon)
2973 ? IconicState
2974 : NormalState));
2975
2976 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
2977 ? f->icon_name
2978 : f->name)));
2979
2980 UNBLOCK_INPUT;
2981 }
2982
2983 /* Make the GCs needed for this window, setting the
2984 background, border and mouse colors; also create the
2985 mouse cursor and the gray border tile. */
2986
2987 static char cursor_bits[] =
2988 {
2989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2993 };
2994
2995 static void
2996 x_make_gc (f)
2997 struct frame *f;
2998 {
2999 XGCValues gc_values;
3000
3001 BLOCK_INPUT;
3002
3003 /* Create the GCs of this frame.
3004 Note that many default values are used. */
3005
3006 /* Normal video */
3007 gc_values.font = FRAME_FONT (f)->fid;
3008 gc_values.foreground = f->output_data.x->foreground_pixel;
3009 gc_values.background = f->output_data.x->background_pixel;
3010 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3011 f->output_data.x->normal_gc
3012 = XCreateGC (FRAME_X_DISPLAY (f),
3013 FRAME_X_WINDOW (f),
3014 GCLineWidth | GCFont | GCForeground | GCBackground,
3015 &gc_values);
3016
3017 /* Reverse video style. */
3018 gc_values.foreground = f->output_data.x->background_pixel;
3019 gc_values.background = f->output_data.x->foreground_pixel;
3020 f->output_data.x->reverse_gc
3021 = XCreateGC (FRAME_X_DISPLAY (f),
3022 FRAME_X_WINDOW (f),
3023 GCFont | GCForeground | GCBackground | GCLineWidth,
3024 &gc_values);
3025
3026 /* Cursor has cursor-color background, background-color foreground. */
3027 gc_values.foreground = f->output_data.x->background_pixel;
3028 gc_values.background = f->output_data.x->cursor_pixel;
3029 gc_values.fill_style = FillOpaqueStippled;
3030 gc_values.stipple
3031 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3032 FRAME_X_DISPLAY_INFO (f)->root_window,
3033 cursor_bits, 16, 16);
3034 f->output_data.x->cursor_gc
3035 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3036 (GCFont | GCForeground | GCBackground
3037 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3038 &gc_values);
3039
3040 /* Reliefs. */
3041 f->output_data.x->white_relief.gc = 0;
3042 f->output_data.x->black_relief.gc = 0;
3043
3044 /* Create the gray border tile used when the pointer is not in
3045 the frame. Since this depends on the frame's pixel values,
3046 this must be done on a per-frame basis. */
3047 f->output_data.x->border_tile
3048 = (XCreatePixmapFromBitmapData
3049 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3050 gray_bits, gray_width, gray_height,
3051 f->output_data.x->foreground_pixel,
3052 f->output_data.x->background_pixel,
3053 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
3054
3055 UNBLOCK_INPUT;
3056 }
3057
3058
3059 /* Free what was was allocated in x_make_gc. */
3060
3061 void
3062 x_free_gcs (f)
3063 struct frame *f;
3064 {
3065 Display *dpy = FRAME_X_DISPLAY (f);
3066
3067 BLOCK_INPUT;
3068
3069 if (f->output_data.x->normal_gc)
3070 {
3071 XFreeGC (dpy, f->output_data.x->normal_gc);
3072 f->output_data.x->normal_gc = 0;
3073 }
3074
3075 if (f->output_data.x->reverse_gc)
3076 {
3077 XFreeGC (dpy, f->output_data.x->reverse_gc);
3078 f->output_data.x->reverse_gc = 0;
3079 }
3080
3081 if (f->output_data.x->cursor_gc)
3082 {
3083 XFreeGC (dpy, f->output_data.x->cursor_gc);
3084 f->output_data.x->cursor_gc = 0;
3085 }
3086
3087 if (f->output_data.x->border_tile)
3088 {
3089 XFreePixmap (dpy, f->output_data.x->border_tile);
3090 f->output_data.x->border_tile = 0;
3091 }
3092
3093 UNBLOCK_INPUT;
3094 }
3095
3096
3097 /* Handler for signals raised during x_create_frame and
3098 x_create_top_frame. FRAME is the frame which is partially
3099 constructed. */
3100
3101 static Lisp_Object
3102 unwind_create_frame (frame)
3103 Lisp_Object frame;
3104 {
3105 struct frame *f = XFRAME (frame);
3106
3107 /* If frame is ``official'', nothing to do. */
3108 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
3109 {
3110 #if GLYPH_DEBUG
3111 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3112 #endif
3113
3114 x_free_frame_resources (f);
3115
3116 /* Check that reference counts are indeed correct. */
3117 xassert (dpyinfo->reference_count == dpyinfo_refcount);
3118 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
3119 return Qt;
3120 }
3121
3122 return Qnil;
3123 }
3124
3125
3126 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3127 1, 1, 0,
3128 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
3129 Returns an Emacs frame object.
3130 ALIST is an alist of frame parameters.
3131 If the parameters specify that the frame should not have a minibuffer,
3132 and do not specify a specific minibuffer window to use,
3133 then `default-minibuffer-frame' must be a frame whose minibuffer can
3134 be shared by the new frame.
3135
3136 This function is an internal primitive--use `make-frame' instead. */)
3137 (parms)
3138 Lisp_Object parms;
3139 {
3140 struct frame *f;
3141 Lisp_Object frame, tem;
3142 Lisp_Object name;
3143 int minibuffer_only = 0;
3144 long window_prompting = 0;
3145 int width, height;
3146 int count = SPECPDL_INDEX ();
3147 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3148 Lisp_Object display;
3149 struct x_display_info *dpyinfo = NULL;
3150 Lisp_Object parent;
3151 struct kboard *kb;
3152
3153 check_x ();
3154
3155 /* Use this general default value to start with
3156 until we know if this frame has a specified name. */
3157 Vx_resource_name = Vinvocation_name;
3158
3159 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3160 if (EQ (display, Qunbound))
3161 display = Qnil;
3162 dpyinfo = check_x_display_info (display);
3163 #ifdef MULTI_KBOARD
3164 kb = dpyinfo->kboard;
3165 #else
3166 kb = &the_only_kboard;
3167 #endif
3168
3169 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3170 if (!STRINGP (name)
3171 && ! EQ (name, Qunbound)
3172 && ! NILP (name))
3173 error ("Invalid frame name--not a string or nil");
3174
3175 if (STRINGP (name))
3176 Vx_resource_name = name;
3177
3178 /* See if parent window is specified. */
3179 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3180 if (EQ (parent, Qunbound))
3181 parent = Qnil;
3182 if (! NILP (parent))
3183 CHECK_NUMBER (parent);
3184
3185 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3186 /* No need to protect DISPLAY because that's not used after passing
3187 it to make_frame_without_minibuffer. */
3188 frame = Qnil;
3189 GCPRO4 (parms, parent, name, frame);
3190 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3191 RES_TYPE_SYMBOL);
3192 if (EQ (tem, Qnone) || NILP (tem))
3193 f = make_frame_without_minibuffer (Qnil, kb, display);
3194 else if (EQ (tem, Qonly))
3195 {
3196 f = make_minibuffer_frame ();
3197 minibuffer_only = 1;
3198 }
3199 else if (WINDOWP (tem))
3200 f = make_frame_without_minibuffer (tem, kb, display);
3201 else
3202 f = make_frame (1);
3203
3204 XSETFRAME (frame, f);
3205
3206 /* Note that X Windows does support scroll bars. */
3207 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3208
3209 f->output_method = output_x_window;
3210 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3211 bzero (f->output_data.x, sizeof (struct x_output));
3212 f->output_data.x->icon_bitmap = -1;
3213 FRAME_FONTSET (f) = -1;
3214 f->output_data.x->scroll_bar_foreground_pixel = -1;
3215 f->output_data.x->scroll_bar_background_pixel = -1;
3216 #ifdef USE_TOOLKIT_SCROLL_BARS
3217 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3218 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3219 #endif /* USE_TOOLKIT_SCROLL_BARS */
3220 record_unwind_protect (unwind_create_frame, frame);
3221
3222 f->icon_name
3223 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3224 RES_TYPE_STRING);
3225 if (! STRINGP (f->icon_name))
3226 f->icon_name = Qnil;
3227
3228 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3229 #if GLYPH_DEBUG
3230 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
3231 dpyinfo_refcount = dpyinfo->reference_count;
3232 #endif /* GLYPH_DEBUG */
3233 #ifdef MULTI_KBOARD
3234 FRAME_KBOARD (f) = kb;
3235 #endif
3236
3237 /* These colors will be set anyway later, but it's important
3238 to get the color reference counts right, so initialize them! */
3239 {
3240 Lisp_Object black;
3241 struct gcpro gcpro1;
3242
3243 /* Function x_decode_color can signal an error. Make
3244 sure to initialize color slots so that we won't try
3245 to free colors we haven't allocated. */
3246 f->output_data.x->foreground_pixel = -1;
3247 f->output_data.x->background_pixel = -1;
3248 f->output_data.x->cursor_pixel = -1;
3249 f->output_data.x->cursor_foreground_pixel = -1;
3250 f->output_data.x->border_pixel = -1;
3251 f->output_data.x->mouse_pixel = -1;
3252
3253 black = build_string ("black");
3254 GCPRO1 (black);
3255 f->output_data.x->foreground_pixel
3256 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3257 f->output_data.x->background_pixel
3258 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3259 f->output_data.x->cursor_pixel
3260 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3261 f->output_data.x->cursor_foreground_pixel
3262 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3263 f->output_data.x->border_pixel
3264 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3265 f->output_data.x->mouse_pixel
3266 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3267 UNGCPRO;
3268 }
3269
3270 /* Specify the parent under which to make this X window. */
3271
3272 if (!NILP (parent))
3273 {
3274 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3275 f->output_data.x->explicit_parent = 1;
3276 }
3277 else
3278 {
3279 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3280 f->output_data.x->explicit_parent = 0;
3281 }
3282
3283 /* Set the name; the functions to which we pass f expect the name to
3284 be set. */
3285 if (EQ (name, Qunbound) || NILP (name))
3286 {
3287 f->name = build_string (dpyinfo->x_id_name);
3288 f->explicit_name = 0;
3289 }
3290 else
3291 {
3292 f->name = name;
3293 f->explicit_name = 1;
3294 /* use the frame's title when getting resources for this frame. */
3295 specbind (Qx_resource_name, name);
3296 }
3297
3298 /* Extract the window parameters from the supplied values
3299 that are needed to determine window geometry. */
3300 {
3301 Lisp_Object font;
3302
3303 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3304
3305 BLOCK_INPUT;
3306 /* First, try whatever font the caller has specified. */
3307 if (STRINGP (font))
3308 {
3309 tem = Fquery_fontset (font, Qnil);
3310 if (STRINGP (tem))
3311 font = x_new_fontset (f, SDATA (tem));
3312 else
3313 font = x_new_font (f, SDATA (font));
3314 }
3315
3316 /* Try out a font which we hope has bold and italic variations. */
3317 if (!STRINGP (font))
3318 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3319 if (!STRINGP (font))
3320 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3321 if (! STRINGP (font))
3322 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3323 if (! STRINGP (font))
3324 /* This was formerly the first thing tried, but it finds too many fonts
3325 and takes too long. */
3326 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3327 /* If those didn't work, look for something which will at least work. */
3328 if (! STRINGP (font))
3329 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3330 UNBLOCK_INPUT;
3331 if (! STRINGP (font))
3332 font = build_string ("fixed");
3333
3334 x_default_parameter (f, parms, Qfont, font,
3335 "font", "Font", RES_TYPE_STRING);
3336 }
3337
3338 #ifdef USE_LUCID
3339 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3340 whereby it fails to get any font. */
3341 xlwmenu_default_font = FRAME_FONT (f);
3342 #endif
3343
3344 x_default_parameter (f, parms, Qborder_width, make_number (2),
3345 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3346
3347 /* This defaults to 1 in order to match xterm. We recognize either
3348 internalBorderWidth or internalBorder (which is what xterm calls
3349 it). */
3350 if (NILP (Fassq (Qinternal_border_width, parms)))
3351 {
3352 Lisp_Object value;
3353
3354 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3355 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3356 if (! EQ (value, Qunbound))
3357 parms = Fcons (Fcons (Qinternal_border_width, value),
3358 parms);
3359 }
3360 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3361 "internalBorderWidth", "internalBorderWidth",
3362 RES_TYPE_NUMBER);
3363 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3364 "verticalScrollBars", "ScrollBars",
3365 RES_TYPE_SYMBOL);
3366
3367 /* Also do the stuff which must be set before the window exists. */
3368 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3369 "foreground", "Foreground", RES_TYPE_STRING);
3370 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3371 "background", "Background", RES_TYPE_STRING);
3372 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3373 "pointerColor", "Foreground", RES_TYPE_STRING);
3374 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3375 "cursorColor", "Foreground", RES_TYPE_STRING);
3376 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3377 "borderColor", "BorderColor", RES_TYPE_STRING);
3378 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3379 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3380 x_default_parameter (f, parms, Qline_spacing, Qnil,
3381 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3382 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3383 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3384 x_default_parameter (f, parms, Qright_fringe, Qnil,
3385 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3386
3387 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3388 "scrollBarForeground",
3389 "ScrollBarForeground", 1);
3390 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3391 "scrollBarBackground",
3392 "ScrollBarBackground", 0);
3393
3394 /* Init faces before x_default_parameter is called for scroll-bar
3395 parameters because that function calls x_set_scroll_bar_width,
3396 which calls change_frame_size, which calls Fset_window_buffer,
3397 which runs hooks, which call Fvertical_motion. At the end, we
3398 end up in init_iterator with a null face cache, which should not
3399 happen. */
3400 init_frame_faces (f);
3401
3402 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3403 "menuBar", "MenuBar", RES_TYPE_NUMBER);
3404 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
3405 "toolBar", "ToolBar", RES_TYPE_NUMBER);
3406 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3407 "bufferPredicate", "BufferPredicate",
3408 RES_TYPE_SYMBOL);
3409 x_default_parameter (f, parms, Qtitle, Qnil,
3410 "title", "Title", RES_TYPE_STRING);
3411 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3412 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3413 x_default_parameter (f, parms, Qfullscreen, Qnil,
3414 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3415
3416 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3417
3418 /* Compute the size of the X window. */
3419 window_prompting = x_figure_window_size (f, parms, 1);
3420
3421 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3422 f->no_split = minibuffer_only || EQ (tem, Qt);
3423
3424 /* Create the X widget or window. */
3425 #ifdef USE_X_TOOLKIT
3426 x_window (f, window_prompting, minibuffer_only);
3427 #else
3428 x_window (f);
3429 #endif
3430
3431 x_icon (f, parms);
3432 x_make_gc (f);
3433
3434 /* Now consider the frame official. */
3435 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3436 Vframe_list = Fcons (frame, Vframe_list);
3437
3438 /* We need to do this after creating the X window, so that the
3439 icon-creation functions can say whose icon they're describing. */
3440 x_default_parameter (f, parms, Qicon_type, Qnil,
3441 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
3442
3443 x_default_parameter (f, parms, Qauto_raise, Qnil,
3444 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3445 x_default_parameter (f, parms, Qauto_lower, Qnil,
3446 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3447 x_default_parameter (f, parms, Qcursor_type, Qbox,
3448 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3449 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3450 "scrollBarWidth", "ScrollBarWidth",
3451 RES_TYPE_NUMBER);
3452
3453 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
3454 Change will not be effected unless different from the current
3455 FRAME_LINES (f). */
3456 width = FRAME_COLS (f);
3457 height = FRAME_LINES (f);
3458
3459 SET_FRAME_COLS (f, 0);
3460 FRAME_LINES (f) = 0;
3461 change_frame_size (f, height, width, 1, 0, 0);
3462
3463 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3464 /* Create the menu bar. */
3465 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3466 {
3467 /* If this signals an error, we haven't set size hints for the
3468 frame and we didn't make it visible. */
3469 initialize_frame_menubar (f);
3470
3471 #ifndef USE_GTK
3472 /* This is a no-op, except under Motif where it arranges the
3473 main window for the widgets on it. */
3474 lw_set_main_areas (f->output_data.x->column_widget,
3475 f->output_data.x->menubar_widget,
3476 f->output_data.x->edit_widget);
3477 #endif /* not USE_GTK */
3478 }
3479 #endif /* USE_X_TOOLKIT || USE_GTK */
3480
3481 /* Tell the server what size and position, etc, we want, and how
3482 badly we want them. This should be done after we have the menu
3483 bar so that its size can be taken into account. */
3484 BLOCK_INPUT;
3485 x_wm_set_size_hint (f, window_prompting, 0);
3486 UNBLOCK_INPUT;
3487
3488 /* Make the window appear on the frame and enable display, unless
3489 the caller says not to. However, with explicit parent, Emacs
3490 cannot control visibility, so don't try. */
3491 if (! f->output_data.x->explicit_parent)
3492 {
3493 Lisp_Object visibility;
3494
3495 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3496 RES_TYPE_SYMBOL);
3497 if (EQ (visibility, Qunbound))
3498 visibility = Qt;
3499
3500 if (EQ (visibility, Qicon))
3501 x_iconify_frame (f);
3502 else if (! NILP (visibility))
3503 x_make_frame_visible (f);
3504 else
3505 /* Must have been Qnil. */
3506 ;
3507 }
3508
3509 UNGCPRO;
3510
3511 /* Make sure windows on this frame appear in calls to next-window
3512 and similar functions. */
3513 Vwindow_list = Qnil;
3514
3515 return unbind_to (count, frame);
3516 }
3517
3518
3519 /* FRAME is used only to get a handle on the X display. We don't pass the
3520 display info directly because we're called from frame.c, which doesn't
3521 know about that structure. */
3522
3523 Lisp_Object
3524 x_get_focus_frame (frame)
3525 struct frame *frame;
3526 {
3527 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3528 Lisp_Object xfocus;
3529 if (! dpyinfo->x_focus_frame)
3530 return Qnil;
3531
3532 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3533 return xfocus;
3534 }
3535
3536
3537 /* In certain situations, when the window manager follows a
3538 click-to-focus policy, there seems to be no way around calling
3539 XSetInputFocus to give another frame the input focus .
3540
3541 In an ideal world, XSetInputFocus should generally be avoided so
3542 that applications don't interfere with the window manager's focus
3543 policy. But I think it's okay to use when it's clearly done
3544 following a user-command. */
3545
3546 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
3547 doc: /* Set the input focus to FRAME.
3548 FRAME nil means use the selected frame. */)
3549 (frame)
3550 Lisp_Object frame;
3551 {
3552 struct frame *f = check_x_frame (frame);
3553 Display *dpy = FRAME_X_DISPLAY (f);
3554 int count;
3555
3556 BLOCK_INPUT;
3557 count = x_catch_errors (dpy);
3558 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3559 RevertToParent, CurrentTime);
3560 x_uncatch_errors (dpy, count);
3561 UNBLOCK_INPUT;
3562
3563 return Qnil;
3564 }
3565
3566 \f
3567 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3568 doc: /* Internal function called by `color-defined-p', which see. */)
3569 (color, frame)
3570 Lisp_Object color, frame;
3571 {
3572 XColor foo;
3573 FRAME_PTR f = check_x_frame (frame);
3574
3575 CHECK_STRING (color);
3576
3577 if (x_defined_color (f, SDATA (color), &foo, 0))
3578 return Qt;
3579 else
3580 return Qnil;
3581 }
3582
3583 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3584 doc: /* Internal function called by `color-values', which see. */)
3585 (color, frame)
3586 Lisp_Object color, frame;
3587 {
3588 XColor foo;
3589 FRAME_PTR f = check_x_frame (frame);
3590
3591 CHECK_STRING (color);
3592
3593 if (x_defined_color (f, SDATA (color), &foo, 0))
3594 {
3595 Lisp_Object rgb[3];
3596
3597 rgb[0] = make_number (foo.red);
3598 rgb[1] = make_number (foo.green);
3599 rgb[2] = make_number (foo.blue);
3600 return Flist (3, rgb);
3601 }
3602 else
3603 return Qnil;
3604 }
3605
3606 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3607 doc: /* Internal function called by `display-color-p', which see. */)
3608 (display)
3609 Lisp_Object display;
3610 {
3611 struct x_display_info *dpyinfo = check_x_display_info (display);
3612
3613 if (dpyinfo->n_planes <= 2)
3614 return Qnil;
3615
3616 switch (dpyinfo->visual->class)
3617 {
3618 case StaticColor:
3619 case PseudoColor:
3620 case TrueColor:
3621 case DirectColor:
3622 return Qt;
3623
3624 default:
3625 return Qnil;
3626 }
3627 }
3628
3629 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3630 0, 1, 0,
3631 doc: /* Return t if the X display supports shades of gray.
3632 Note that color displays do support shades of gray.
3633 The optional argument DISPLAY specifies which display to ask about.
3634 DISPLAY should be either a frame or a display name (a string).
3635 If omitted or nil, that stands for the selected frame's display. */)
3636 (display)
3637 Lisp_Object display;
3638 {
3639 struct x_display_info *dpyinfo = check_x_display_info (display);
3640
3641 if (dpyinfo->n_planes <= 1)
3642 return Qnil;
3643
3644 switch (dpyinfo->visual->class)
3645 {
3646 case StaticColor:
3647 case PseudoColor:
3648 case TrueColor:
3649 case DirectColor:
3650 case StaticGray:
3651 case GrayScale:
3652 return Qt;
3653
3654 default:
3655 return Qnil;
3656 }
3657 }
3658
3659 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3660 0, 1, 0,
3661 doc: /* Returns the width in pixels of the X display DISPLAY.
3662 The optional argument DISPLAY specifies which display to ask about.
3663 DISPLAY should be either a frame or a display name (a string).
3664 If omitted or nil, that stands for the selected frame's display. */)
3665 (display)
3666 Lisp_Object display;
3667 {
3668 struct x_display_info *dpyinfo = check_x_display_info (display);
3669
3670 return make_number (dpyinfo->width);
3671 }
3672
3673 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3674 Sx_display_pixel_height, 0, 1, 0,
3675 doc: /* Returns the height in pixels of the X display DISPLAY.
3676 The optional argument DISPLAY specifies which display to ask about.
3677 DISPLAY should be either a frame or a display name (a string).
3678 If omitted or nil, that stands for the selected frame's display. */)
3679 (display)
3680 Lisp_Object display;
3681 {
3682 struct x_display_info *dpyinfo = check_x_display_info (display);
3683
3684 return make_number (dpyinfo->height);
3685 }
3686
3687 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3688 0, 1, 0,
3689 doc: /* Returns the number of bitplanes of the X display DISPLAY.
3690 The optional argument DISPLAY specifies which display to ask about.
3691 DISPLAY should be either a frame or a display name (a string).
3692 If omitted or nil, that stands for the selected frame's display. */)
3693 (display)
3694 Lisp_Object display;
3695 {
3696 struct x_display_info *dpyinfo = check_x_display_info (display);
3697
3698 return make_number (dpyinfo->n_planes);
3699 }
3700
3701 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3702 0, 1, 0,
3703 doc: /* Returns the number of color cells of the X display DISPLAY.
3704 The optional argument DISPLAY specifies which display to ask about.
3705 DISPLAY should be either a frame or a display name (a string).
3706 If omitted or nil, that stands for the selected frame's display. */)
3707 (display)
3708 Lisp_Object display;
3709 {
3710 struct x_display_info *dpyinfo = check_x_display_info (display);
3711
3712 return make_number (DisplayCells (dpyinfo->display,
3713 XScreenNumberOfScreen (dpyinfo->screen)));
3714 }
3715
3716 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3717 Sx_server_max_request_size,
3718 0, 1, 0,
3719 doc: /* Returns the maximum request size of the X server of display DISPLAY.
3720 The optional argument DISPLAY specifies which display to ask about.
3721 DISPLAY should be either a frame or a display name (a string).
3722 If omitted or nil, that stands for the selected frame's display. */)
3723 (display)
3724 Lisp_Object display;
3725 {
3726 struct x_display_info *dpyinfo = check_x_display_info (display);
3727
3728 return make_number (MAXREQUEST (dpyinfo->display));
3729 }
3730
3731 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3732 doc: /* Returns the vendor ID string of the X server of display DISPLAY.
3733 The optional argument DISPLAY specifies which display to ask about.
3734 DISPLAY should be either a frame or a display name (a string).
3735 If omitted or nil, that stands for the selected frame's display. */)
3736 (display)
3737 Lisp_Object display;
3738 {
3739 struct x_display_info *dpyinfo = check_x_display_info (display);
3740 char *vendor = ServerVendor (dpyinfo->display);
3741
3742 if (! vendor) vendor = "";
3743 return build_string (vendor);
3744 }
3745
3746 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3747 doc: /* Returns the version numbers of the X server of display DISPLAY.
3748 The value is a list of three integers: the major and minor
3749 version numbers of the X Protocol in use, and the vendor-specific release
3750 number. See also the function `x-server-vendor'.
3751
3752 The optional argument DISPLAY specifies which display to ask about.
3753 DISPLAY should be either a frame or a display name (a string).
3754 If omitted or nil, that stands for the selected frame's display. */)
3755 (display)
3756 Lisp_Object display;
3757 {
3758 struct x_display_info *dpyinfo = check_x_display_info (display);
3759 Display *dpy = dpyinfo->display;
3760
3761 return Fcons (make_number (ProtocolVersion (dpy)),
3762 Fcons (make_number (ProtocolRevision (dpy)),
3763 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3764 }
3765
3766 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3767 doc: /* Return the number of screens on the X server of display DISPLAY.
3768 The optional argument DISPLAY specifies which display to ask about.
3769 DISPLAY should be either a frame or a display name (a string).
3770 If omitted or nil, that stands for the selected frame's display. */)
3771 (display)
3772 Lisp_Object display;
3773 {
3774 struct x_display_info *dpyinfo = check_x_display_info (display);
3775
3776 return make_number (ScreenCount (dpyinfo->display));
3777 }
3778
3779 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3780 doc: /* Return the height in millimeters of the X display DISPLAY.
3781 The optional argument DISPLAY specifies which display to ask about.
3782 DISPLAY should be either a frame or a display name (a string).
3783 If omitted or nil, that stands for the selected frame's display. */)
3784 (display)
3785 Lisp_Object display;
3786 {
3787 struct x_display_info *dpyinfo = check_x_display_info (display);
3788
3789 return make_number (HeightMMOfScreen (dpyinfo->screen));
3790 }
3791
3792 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3793 doc: /* Return the width in millimeters of the X display DISPLAY.
3794 The optional argument DISPLAY specifies which display to ask about.
3795 DISPLAY should be either a frame or a display name (a string).
3796 If omitted or nil, that stands for the selected frame's display. */)
3797 (display)
3798 Lisp_Object display;
3799 {
3800 struct x_display_info *dpyinfo = check_x_display_info (display);
3801
3802 return make_number (WidthMMOfScreen (dpyinfo->screen));
3803 }
3804
3805 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3806 Sx_display_backing_store, 0, 1, 0,
3807 doc: /* Returns an indication of whether X display DISPLAY does backing store.
3808 The value may be `always', `when-mapped', or `not-useful'.
3809 The optional argument DISPLAY specifies which display to ask about.
3810 DISPLAY should be either a frame or a display name (a string).
3811 If omitted or nil, that stands for the selected frame's display. */)
3812 (display)
3813 Lisp_Object display;
3814 {
3815 struct x_display_info *dpyinfo = check_x_display_info (display);
3816 Lisp_Object result;
3817
3818 switch (DoesBackingStore (dpyinfo->screen))
3819 {
3820 case Always:
3821 result = intern ("always");
3822 break;
3823
3824 case WhenMapped:
3825 result = intern ("when-mapped");
3826 break;
3827
3828 case NotUseful:
3829 result = intern ("not-useful");
3830 break;
3831
3832 default:
3833 error ("Strange value for BackingStore parameter of screen");
3834 result = Qnil;
3835 }
3836
3837 return result;
3838 }
3839
3840 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3841 Sx_display_visual_class, 0, 1, 0,
3842 doc: /* Return the visual class of the X display DISPLAY.
3843 The value is one of the symbols `static-gray', `gray-scale',
3844 `static-color', `pseudo-color', `true-color', or `direct-color'.
3845
3846 The optional argument DISPLAY specifies which display to ask about.
3847 DISPLAY should be either a frame or a display name (a string).
3848 If omitted or nil, that stands for the selected frame's display. */)
3849 (display)
3850 Lisp_Object display;
3851 {
3852 struct x_display_info *dpyinfo = check_x_display_info (display);
3853 Lisp_Object result;
3854
3855 switch (dpyinfo->visual->class)
3856 {
3857 case StaticGray:
3858 result = intern ("static-gray");
3859 break;
3860 case GrayScale:
3861 result = intern ("gray-scale");
3862 break;
3863 case StaticColor:
3864 result = intern ("static-color");
3865 break;
3866 case PseudoColor:
3867 result = intern ("pseudo-color");
3868 break;
3869 case TrueColor:
3870 result = intern ("true-color");
3871 break;
3872 case DirectColor:
3873 result = intern ("direct-color");
3874 break;
3875 default:
3876 error ("Display has an unknown visual class");
3877 result = Qnil;
3878 }
3879
3880 return result;
3881 }
3882
3883 DEFUN ("x-display-save-under", Fx_display_save_under,
3884 Sx_display_save_under, 0, 1, 0,
3885 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
3886 The optional argument DISPLAY specifies which display to ask about.
3887 DISPLAY should be either a frame or a display name (a string).
3888 If omitted or nil, that stands for the selected frame's display. */)
3889 (display)
3890 Lisp_Object display;
3891 {
3892 struct x_display_info *dpyinfo = check_x_display_info (display);
3893
3894 if (DoesSaveUnders (dpyinfo->screen) == True)
3895 return Qt;
3896 else
3897 return Qnil;
3898 }
3899 \f
3900 int
3901 x_pixel_width (f)
3902 register struct frame *f;
3903 {
3904 return FRAME_PIXEL_WIDTH (f);
3905 }
3906
3907 int
3908 x_pixel_height (f)
3909 register struct frame *f;
3910 {
3911 return FRAME_PIXEL_HEIGHT (f);
3912 }
3913
3914 int
3915 x_char_width (f)
3916 register struct frame *f;
3917 {
3918 return FRAME_COLUMN_WIDTH (f);
3919 }
3920
3921 int
3922 x_char_height (f)
3923 register struct frame *f;
3924 {
3925 return FRAME_LINE_HEIGHT (f);
3926 }
3927
3928 int
3929 x_screen_planes (f)
3930 register struct frame *f;
3931 {
3932 return FRAME_X_DISPLAY_INFO (f)->n_planes;
3933 }
3934
3935
3936 \f
3937 /************************************************************************
3938 X Displays
3939 ************************************************************************/
3940
3941 \f
3942 /* Mapping visual names to visuals. */
3943
3944 static struct visual_class
3945 {
3946 char *name;
3947 int class;
3948 }
3949 visual_classes[] =
3950 {
3951 {"StaticGray", StaticGray},
3952 {"GrayScale", GrayScale},
3953 {"StaticColor", StaticColor},
3954 {"PseudoColor", PseudoColor},
3955 {"TrueColor", TrueColor},
3956 {"DirectColor", DirectColor},
3957 {NULL, 0}
3958 };
3959
3960
3961 #ifndef HAVE_XSCREENNUMBEROFSCREEN
3962
3963 /* Value is the screen number of screen SCR. This is a substitute for
3964 the X function with the same name when that doesn't exist. */
3965
3966 int
3967 XScreenNumberOfScreen (scr)
3968 register Screen *scr;
3969 {
3970 Display *dpy = scr->display;
3971 int i;
3972
3973 for (i = 0; i < dpy->nscreens; ++i)
3974 if (scr == dpy->screens + i)
3975 break;
3976
3977 return i;
3978 }
3979
3980 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
3981
3982
3983 /* Select the visual that should be used on display DPYINFO. Set
3984 members of DPYINFO appropriately. Called from x_term_init. */
3985
3986 void
3987 select_visual (dpyinfo)
3988 struct x_display_info *dpyinfo;
3989 {
3990 Display *dpy = dpyinfo->display;
3991 Screen *screen = dpyinfo->screen;
3992 Lisp_Object value;
3993
3994 /* See if a visual is specified. */
3995 value = display_x_get_resource (dpyinfo,
3996 build_string ("visualClass"),
3997 build_string ("VisualClass"),
3998 Qnil, Qnil);
3999 if (STRINGP (value))
4000 {
4001 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4002 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4003 depth, a decimal number. NAME is compared with case ignored. */
4004 char *s = (char *) alloca (SBYTES (value) + 1);
4005 char *dash;
4006 int i, class = -1;
4007 XVisualInfo vinfo;
4008
4009 strcpy (s, SDATA (value));
4010 dash = index (s, '-');
4011 if (dash)
4012 {
4013 dpyinfo->n_planes = atoi (dash + 1);
4014 *dash = '\0';
4015 }
4016 else
4017 /* We won't find a matching visual with depth 0, so that
4018 an error will be printed below. */
4019 dpyinfo->n_planes = 0;
4020
4021 /* Determine the visual class. */
4022 for (i = 0; visual_classes[i].name; ++i)
4023 if (xstricmp (s, visual_classes[i].name) == 0)
4024 {
4025 class = visual_classes[i].class;
4026 break;
4027 }
4028
4029 /* Look up a matching visual for the specified class. */
4030 if (class == -1
4031 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4032 dpyinfo->n_planes, class, &vinfo))
4033 fatal ("Invalid visual specification `%s'", SDATA (value));
4034
4035 dpyinfo->visual = vinfo.visual;
4036 }
4037 else
4038 {
4039 int n_visuals;
4040 XVisualInfo *vinfo, vinfo_template;
4041
4042 dpyinfo->visual = DefaultVisualOfScreen (screen);
4043
4044 #ifdef HAVE_X11R4
4045 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
4046 #else
4047 vinfo_template.visualid = dpyinfo->visual->visualid;
4048 #endif
4049 vinfo_template.screen = XScreenNumberOfScreen (screen);
4050 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
4051 &vinfo_template, &n_visuals);
4052 if (n_visuals != 1)
4053 fatal ("Can't get proper X visual info");
4054
4055 dpyinfo->n_planes = vinfo->depth;
4056 XFree ((char *) vinfo);
4057 }
4058 }
4059
4060
4061 /* Return the X display structure for the display named NAME.
4062 Open a new connection if necessary. */
4063
4064 struct x_display_info *
4065 x_display_info_for_name (name)
4066 Lisp_Object name;
4067 {
4068 Lisp_Object names;
4069 struct x_display_info *dpyinfo;
4070
4071 CHECK_STRING (name);
4072
4073 if (! EQ (Vwindow_system, intern ("x")))
4074 error ("Not using X Windows");
4075
4076 for (dpyinfo = x_display_list, names = x_display_name_list;
4077 dpyinfo;
4078 dpyinfo = dpyinfo->next, names = XCDR (names))
4079 {
4080 Lisp_Object tem;
4081 tem = Fstring_equal (XCAR (XCAR (names)), name);
4082 if (!NILP (tem))
4083 return dpyinfo;
4084 }
4085
4086 /* Use this general default value to start with. */
4087 Vx_resource_name = Vinvocation_name;
4088
4089 validate_x_resource_name ();
4090
4091 dpyinfo = x_term_init (name, (char *)0,
4092 (char *) SDATA (Vx_resource_name));
4093
4094 if (dpyinfo == 0)
4095 error ("Cannot connect to X server %s", SDATA (name));
4096
4097 x_in_use = 1;
4098 XSETFASTINT (Vwindow_system_version, 11);
4099
4100 return dpyinfo;
4101 }
4102
4103
4104 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4105 1, 3, 0,
4106 doc: /* Open a connection to an X server.
4107 DISPLAY is the name of the display to connect to.
4108 Optional second arg XRM-STRING is a string of resources in xrdb format.
4109 If the optional third arg MUST-SUCCEED is non-nil,
4110 terminate Emacs if we can't open the connection. */)
4111 (display, xrm_string, must_succeed)
4112 Lisp_Object display, xrm_string, must_succeed;
4113 {
4114 unsigned char *xrm_option;
4115 struct x_display_info *dpyinfo;
4116
4117 CHECK_STRING (display);
4118 if (! NILP (xrm_string))
4119 CHECK_STRING (xrm_string);
4120
4121 if (! EQ (Vwindow_system, intern ("x")))
4122 error ("Not using X Windows");
4123
4124 if (! NILP (xrm_string))
4125 xrm_option = (unsigned char *) SDATA (xrm_string);
4126 else
4127 xrm_option = (unsigned char *) 0;
4128
4129 validate_x_resource_name ();
4130
4131 /* This is what opens the connection and sets x_current_display.
4132 This also initializes many symbols, such as those used for input. */
4133 dpyinfo = x_term_init (display, xrm_option,
4134 (char *) SDATA (Vx_resource_name));
4135
4136 if (dpyinfo == 0)
4137 {
4138 if (!NILP (must_succeed))
4139 fatal ("Cannot connect to X server %s.\n\
4140 Check the DISPLAY environment variable or use `-d'.\n\
4141 Also use the `xauth' program to verify that you have the proper\n\
4142 authorization information needed to connect the X server.\n\
4143 An insecure way to solve the problem may be to use `xhost'.\n",
4144 SDATA (display));
4145 else
4146 error ("Cannot connect to X server %s", SDATA (display));
4147 }
4148
4149 x_in_use = 1;
4150
4151 XSETFASTINT (Vwindow_system_version, 11);
4152 return Qnil;
4153 }
4154
4155 DEFUN ("x-close-connection", Fx_close_connection,
4156 Sx_close_connection, 1, 1, 0,
4157 doc: /* Close the connection to DISPLAY's X server.
4158 For DISPLAY, specify either a frame or a display name (a string).
4159 If DISPLAY is nil, that stands for the selected frame's display. */)
4160 (display)
4161 Lisp_Object display;
4162 {
4163 struct x_display_info *dpyinfo = check_x_display_info (display);
4164 int i;
4165
4166 if (dpyinfo->reference_count > 0)
4167 error ("Display still has frames on it");
4168
4169 BLOCK_INPUT;
4170 /* Free the fonts in the font table. */
4171 for (i = 0; i < dpyinfo->n_fonts; i++)
4172 if (dpyinfo->font_table[i].name)
4173 {
4174 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4175 xfree (dpyinfo->font_table[i].full_name);
4176 xfree (dpyinfo->font_table[i].name);
4177 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4178 }
4179
4180 x_destroy_all_bitmaps (dpyinfo);
4181 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4182
4183 #ifdef USE_X_TOOLKIT
4184 XtCloseDisplay (dpyinfo->display);
4185 #else
4186 XCloseDisplay (dpyinfo->display);
4187 #endif
4188
4189 x_delete_display (dpyinfo);
4190 UNBLOCK_INPUT;
4191
4192 return Qnil;
4193 }
4194
4195 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4196 doc: /* Return the list of display names that Emacs has connections to. */)
4197 ()
4198 {
4199 Lisp_Object tail, result;
4200
4201 result = Qnil;
4202 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4203 result = Fcons (XCAR (XCAR (tail)), result);
4204
4205 return result;
4206 }
4207
4208 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4209 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
4210 If ON is nil, allow buffering of requests.
4211 Turning on synchronization prohibits the Xlib routines from buffering
4212 requests and seriously degrades performance, but makes debugging much
4213 easier.
4214 The optional second argument DISPLAY specifies which display to act on.
4215 DISPLAY should be either a frame or a display name (a string).
4216 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
4217 (on, display)
4218 Lisp_Object display, on;
4219 {
4220 struct x_display_info *dpyinfo = check_x_display_info (display);
4221
4222 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
4223
4224 return Qnil;
4225 }
4226
4227 /* Wait for responses to all X commands issued so far for frame F. */
4228
4229 void
4230 x_sync (f)
4231 FRAME_PTR f;
4232 {
4233 BLOCK_INPUT;
4234 XSync (FRAME_X_DISPLAY (f), False);
4235 UNBLOCK_INPUT;
4236 }
4237
4238 \f
4239 /***********************************************************************
4240 Image types
4241 ***********************************************************************/
4242
4243 /* Value is the number of elements of vector VECTOR. */
4244
4245 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4246
4247 /* List of supported image types. Use define_image_type to add new
4248 types. Use lookup_image_type to find a type for a given symbol. */
4249
4250 static struct image_type *image_types;
4251
4252 /* The symbol `image' which is the car of the lists used to represent
4253 images in Lisp. */
4254
4255 extern Lisp_Object Qimage;
4256
4257 /* The symbol `xbm' which is used as the type symbol for XBM images. */
4258
4259 Lisp_Object Qxbm;
4260
4261 /* Keywords. */
4262
4263 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
4264 extern Lisp_Object QCdata, QCtype;
4265 Lisp_Object QCascent, QCmargin, QCrelief;
4266 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
4267 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
4268
4269 /* Other symbols. */
4270
4271 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
4272
4273 /* Time in seconds after which images should be removed from the cache
4274 if not displayed. */
4275
4276 Lisp_Object Vimage_cache_eviction_delay;
4277
4278 /* Function prototypes. */
4279
4280 static void define_image_type P_ ((struct image_type *type));
4281 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
4282 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
4283 static void x_laplace P_ ((struct frame *, struct image *));
4284 static void x_emboss P_ ((struct frame *, struct image *));
4285 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
4286 Lisp_Object));
4287
4288
4289 /* Define a new image type from TYPE. This adds a copy of TYPE to
4290 image_types and adds the symbol *TYPE->type to Vimage_types. */
4291
4292 static void
4293 define_image_type (type)
4294 struct image_type *type;
4295 {
4296 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
4297 The initialized data segment is read-only. */
4298 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
4299 bcopy (type, p, sizeof *p);
4300 p->next = image_types;
4301 image_types = p;
4302 Vimage_types = Fcons (*p->type, Vimage_types);
4303 }
4304
4305
4306 /* Look up image type SYMBOL, and return a pointer to its image_type
4307 structure. Value is null if SYMBOL is not a known image type. */
4308
4309 static INLINE struct image_type *
4310 lookup_image_type (symbol)
4311 Lisp_Object symbol;
4312 {
4313 struct image_type *type;
4314
4315 for (type = image_types; type; type = type->next)
4316 if (EQ (symbol, *type->type))
4317 break;
4318
4319 return type;
4320 }
4321
4322
4323 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
4324 valid image specification is a list whose car is the symbol
4325 `image', and whose rest is a property list. The property list must
4326 contain a value for key `:type'. That value must be the name of a
4327 supported image type. The rest of the property list depends on the
4328 image type. */
4329
4330 int
4331 valid_image_p (object)
4332 Lisp_Object object;
4333 {
4334 int valid_p = 0;
4335
4336 if (CONSP (object) && EQ (XCAR (object), Qimage))
4337 {
4338 Lisp_Object tem;
4339
4340 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
4341 if (EQ (XCAR (tem), QCtype))
4342 {
4343 tem = XCDR (tem);
4344 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
4345 {
4346 struct image_type *type;
4347 type = lookup_image_type (XCAR (tem));
4348 if (type)
4349 valid_p = type->valid_p (object);
4350 }
4351
4352 break;
4353 }
4354 }
4355
4356 return valid_p;
4357 }
4358
4359
4360 /* Log error message with format string FORMAT and argument ARG.
4361 Signaling an error, e.g. when an image cannot be loaded, is not a
4362 good idea because this would interrupt redisplay, and the error
4363 message display would lead to another redisplay. This function
4364 therefore simply displays a message. */
4365
4366 static void
4367 image_error (format, arg1, arg2)
4368 char *format;
4369 Lisp_Object arg1, arg2;
4370 {
4371 add_to_log (format, arg1, arg2);
4372 }
4373
4374
4375 \f
4376 /***********************************************************************
4377 Image specifications
4378 ***********************************************************************/
4379
4380 enum image_value_type
4381 {
4382 IMAGE_DONT_CHECK_VALUE_TYPE,
4383 IMAGE_STRING_VALUE,
4384 IMAGE_STRING_OR_NIL_VALUE,
4385 IMAGE_SYMBOL_VALUE,
4386 IMAGE_POSITIVE_INTEGER_VALUE,
4387 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
4388 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
4389 IMAGE_ASCENT_VALUE,
4390 IMAGE_INTEGER_VALUE,
4391 IMAGE_FUNCTION_VALUE,
4392 IMAGE_NUMBER_VALUE,
4393 IMAGE_BOOL_VALUE
4394 };
4395
4396 /* Structure used when parsing image specifications. */
4397
4398 struct image_keyword
4399 {
4400 /* Name of keyword. */
4401 char *name;
4402
4403 /* The type of value allowed. */
4404 enum image_value_type type;
4405
4406 /* Non-zero means key must be present. */
4407 int mandatory_p;
4408
4409 /* Used to recognize duplicate keywords in a property list. */
4410 int count;
4411
4412 /* The value that was found. */
4413 Lisp_Object value;
4414 };
4415
4416
4417 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
4418 int, Lisp_Object));
4419 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
4420
4421
4422 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
4423 has the format (image KEYWORD VALUE ...). One of the keyword/
4424 value pairs must be `:type TYPE'. KEYWORDS is a vector of
4425 image_keywords structures of size NKEYWORDS describing other
4426 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
4427
4428 static int
4429 parse_image_spec (spec, keywords, nkeywords, type)
4430 Lisp_Object spec;
4431 struct image_keyword *keywords;
4432 int nkeywords;
4433 Lisp_Object type;
4434 {
4435 int i;
4436 Lisp_Object plist;
4437
4438 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
4439 return 0;
4440
4441 plist = XCDR (spec);
4442 while (CONSP (plist))
4443 {
4444 Lisp_Object key, value;
4445
4446 /* First element of a pair must be a symbol. */
4447 key = XCAR (plist);
4448 plist = XCDR (plist);
4449 if (!SYMBOLP (key))
4450 return 0;
4451
4452 /* There must follow a value. */
4453 if (!CONSP (plist))
4454 return 0;
4455 value = XCAR (plist);
4456 plist = XCDR (plist);
4457
4458 /* Find key in KEYWORDS. Error if not found. */
4459 for (i = 0; i < nkeywords; ++i)
4460 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
4461 break;
4462
4463 if (i == nkeywords)
4464 continue;
4465
4466 /* Record that we recognized the keyword. If a keywords
4467 was found more than once, it's an error. */
4468 keywords[i].value = value;
4469 ++keywords[i].count;
4470
4471 if (keywords[i].count > 1)
4472 return 0;
4473
4474 /* Check type of value against allowed type. */
4475 switch (keywords[i].type)
4476 {
4477 case IMAGE_STRING_VALUE:
4478 if (!STRINGP (value))
4479 return 0;
4480 break;
4481
4482 case IMAGE_STRING_OR_NIL_VALUE:
4483 if (!STRINGP (value) && !NILP (value))
4484 return 0;
4485 break;
4486
4487 case IMAGE_SYMBOL_VALUE:
4488 if (!SYMBOLP (value))
4489 return 0;
4490 break;
4491
4492 case IMAGE_POSITIVE_INTEGER_VALUE:
4493 if (!INTEGERP (value) || XINT (value) <= 0)
4494 return 0;
4495 break;
4496
4497 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
4498 if (INTEGERP (value) && XINT (value) >= 0)
4499 break;
4500 if (CONSP (value)
4501 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
4502 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
4503 break;
4504 return 0;
4505
4506 case IMAGE_ASCENT_VALUE:
4507 if (SYMBOLP (value) && EQ (value, Qcenter))
4508 break;
4509 else if (INTEGERP (value)
4510 && XINT (value) >= 0
4511 && XINT (value) <= 100)
4512 break;
4513 return 0;
4514
4515 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
4516 if (!INTEGERP (value) || XINT (value) < 0)
4517 return 0;
4518 break;
4519
4520 case IMAGE_DONT_CHECK_VALUE_TYPE:
4521 break;
4522
4523 case IMAGE_FUNCTION_VALUE:
4524 value = indirect_function (value);
4525 if (SUBRP (value)
4526 || COMPILEDP (value)
4527 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
4528 break;
4529 return 0;
4530
4531 case IMAGE_NUMBER_VALUE:
4532 if (!INTEGERP (value) && !FLOATP (value))
4533 return 0;
4534 break;
4535
4536 case IMAGE_INTEGER_VALUE:
4537 if (!INTEGERP (value))
4538 return 0;
4539 break;
4540
4541 case IMAGE_BOOL_VALUE:
4542 if (!NILP (value) && !EQ (value, Qt))
4543 return 0;
4544 break;
4545
4546 default:
4547 abort ();
4548 break;
4549 }
4550
4551 if (EQ (key, QCtype) && !EQ (type, value))
4552 return 0;
4553 }
4554
4555 /* Check that all mandatory fields are present. */
4556 for (i = 0; i < nkeywords; ++i)
4557 if (keywords[i].mandatory_p && keywords[i].count == 0)
4558 return 0;
4559
4560 return NILP (plist);
4561 }
4562
4563
4564 /* Return the value of KEY in image specification SPEC. Value is nil
4565 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
4566 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
4567
4568 static Lisp_Object
4569 image_spec_value (spec, key, found)
4570 Lisp_Object spec, key;
4571 int *found;
4572 {
4573 Lisp_Object tail;
4574
4575 xassert (valid_image_p (spec));
4576
4577 for (tail = XCDR (spec);
4578 CONSP (tail) && CONSP (XCDR (tail));
4579 tail = XCDR (XCDR (tail)))
4580 {
4581 if (EQ (XCAR (tail), key))
4582 {
4583 if (found)
4584 *found = 1;
4585 return XCAR (XCDR (tail));
4586 }
4587 }
4588
4589 if (found)
4590 *found = 0;
4591 return Qnil;
4592 }
4593
4594
4595 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
4596 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
4597 PIXELS non-nil means return the size in pixels, otherwise return the
4598 size in canonical character units.
4599 FRAME is the frame on which the image will be displayed. FRAME nil
4600 or omitted means use the selected frame. */)
4601 (spec, pixels, frame)
4602 Lisp_Object spec, pixels, frame;
4603 {
4604 Lisp_Object size;
4605
4606 size = Qnil;
4607 if (valid_image_p (spec))
4608 {
4609 struct frame *f = check_x_frame (frame);
4610 int id = lookup_image (f, spec);
4611 struct image *img = IMAGE_FROM_ID (f, id);
4612 int width = img->width + 2 * img->hmargin;
4613 int height = img->height + 2 * img->vmargin;
4614
4615 if (NILP (pixels))
4616 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
4617 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
4618 else
4619 size = Fcons (make_number (width), make_number (height));
4620 }
4621 else
4622 error ("Invalid image specification");
4623
4624 return size;
4625 }
4626
4627
4628 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
4629 doc: /* Return t if image SPEC has a mask bitmap.
4630 FRAME is the frame on which the image will be displayed. FRAME nil
4631 or omitted means use the selected frame. */)
4632 (spec, frame)
4633 Lisp_Object spec, frame;
4634 {
4635 Lisp_Object mask;
4636
4637 mask = Qnil;
4638 if (valid_image_p (spec))
4639 {
4640 struct frame *f = check_x_frame (frame);
4641 int id = lookup_image (f, spec);
4642 struct image *img = IMAGE_FROM_ID (f, id);
4643 if (img->mask)
4644 mask = Qt;
4645 }
4646 else
4647 error ("Invalid image specification");
4648
4649 return mask;
4650 }
4651
4652
4653 \f
4654 /***********************************************************************
4655 Image type independent image structures
4656 ***********************************************************************/
4657
4658 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
4659 static void free_image P_ ((struct frame *f, struct image *img));
4660
4661
4662 /* Allocate and return a new image structure for image specification
4663 SPEC. SPEC has a hash value of HASH. */
4664
4665 static struct image *
4666 make_image (spec, hash)
4667 Lisp_Object spec;
4668 unsigned hash;
4669 {
4670 struct image *img = (struct image *) xmalloc (sizeof *img);
4671
4672 xassert (valid_image_p (spec));
4673 bzero (img, sizeof *img);
4674 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
4675 xassert (img->type != NULL);
4676 img->spec = spec;
4677 img->data.lisp_val = Qnil;
4678 img->ascent = DEFAULT_IMAGE_ASCENT;
4679 img->hash = hash;
4680 return img;
4681 }
4682
4683
4684 /* Free image IMG which was used on frame F, including its resources. */
4685
4686 static void
4687 free_image (f, img)
4688 struct frame *f;
4689 struct image *img;
4690 {
4691 if (img)
4692 {
4693 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4694
4695 /* Remove IMG from the hash table of its cache. */
4696 if (img->prev)
4697 img->prev->next = img->next;
4698 else
4699 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
4700
4701 if (img->next)
4702 img->next->prev = img->prev;
4703
4704 c->images[img->id] = NULL;
4705
4706 /* Free resources, then free IMG. */
4707 img->type->free (f, img);
4708 xfree (img);
4709 }
4710 }
4711
4712
4713 /* Prepare image IMG for display on frame F. Must be called before
4714 drawing an image. */
4715
4716 void
4717 prepare_image_for_display (f, img)
4718 struct frame *f;
4719 struct image *img;
4720 {
4721 EMACS_TIME t;
4722
4723 /* We're about to display IMG, so set its timestamp to `now'. */
4724 EMACS_GET_TIME (t);
4725 img->timestamp = EMACS_SECS (t);
4726
4727 /* If IMG doesn't have a pixmap yet, load it now, using the image
4728 type dependent loader function. */
4729 if (img->pixmap == None && !img->load_failed_p)
4730 img->load_failed_p = img->type->load (f, img) == 0;
4731 }
4732
4733
4734 /* Value is the number of pixels for the ascent of image IMG when
4735 drawn in face FACE. */
4736
4737 int
4738 image_ascent (img, face)
4739 struct image *img;
4740 struct face *face;
4741 {
4742 int height = img->height + img->vmargin;
4743 int ascent;
4744
4745 if (img->ascent == CENTERED_IMAGE_ASCENT)
4746 {
4747 if (face->font)
4748 /* This expression is arranged so that if the image can't be
4749 exactly centered, it will be moved slightly up. This is
4750 because a typical font is `top-heavy' (due to the presence
4751 uppercase letters), so the image placement should err towards
4752 being top-heavy too. It also just generally looks better. */
4753 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
4754 else
4755 ascent = height / 2;
4756 }
4757 else
4758 ascent = height * img->ascent / 100.0;
4759
4760 return ascent;
4761 }
4762
4763 \f
4764 /* Image background colors. */
4765
4766 static unsigned long
4767 four_corners_best (ximg, width, height)
4768 XImage *ximg;
4769 unsigned long width, height;
4770 {
4771 unsigned long corners[4], best;
4772 int i, best_count;
4773
4774 /* Get the colors at the corners of ximg. */
4775 corners[0] = XGetPixel (ximg, 0, 0);
4776 corners[1] = XGetPixel (ximg, width - 1, 0);
4777 corners[2] = XGetPixel (ximg, width - 1, height - 1);
4778 corners[3] = XGetPixel (ximg, 0, height - 1);
4779
4780 /* Choose the most frequently found color as background. */
4781 for (i = best_count = 0; i < 4; ++i)
4782 {
4783 int j, n;
4784
4785 for (j = n = 0; j < 4; ++j)
4786 if (corners[i] == corners[j])
4787 ++n;
4788
4789 if (n > best_count)
4790 best = corners[i], best_count = n;
4791 }
4792
4793 return best;
4794 }
4795
4796 /* Return the `background' field of IMG. If IMG doesn't have one yet,
4797 it is guessed heuristically. If non-zero, XIMG is an existing XImage
4798 object to use for the heuristic. */
4799
4800 unsigned long
4801 image_background (img, f, ximg)
4802 struct image *img;
4803 struct frame *f;
4804 XImage *ximg;
4805 {
4806 if (! img->background_valid)
4807 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4808 {
4809 int free_ximg = !ximg;
4810
4811 if (! ximg)
4812 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4813 0, 0, img->width, img->height, ~0, ZPixmap);
4814
4815 img->background = four_corners_best (ximg, img->width, img->height);
4816
4817 if (free_ximg)
4818 XDestroyImage (ximg);
4819
4820 img->background_valid = 1;
4821 }
4822
4823 return img->background;
4824 }
4825
4826 /* Return the `background_transparent' field of IMG. If IMG doesn't
4827 have one yet, it is guessed heuristically. If non-zero, MASK is an
4828 existing XImage object to use for the heuristic. */
4829
4830 int
4831 image_background_transparent (img, f, mask)
4832 struct image *img;
4833 struct frame *f;
4834 XImage *mask;
4835 {
4836 if (! img->background_transparent_valid)
4837 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4838 {
4839 if (img->mask)
4840 {
4841 int free_mask = !mask;
4842
4843 if (! mask)
4844 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
4845 0, 0, img->width, img->height, ~0, ZPixmap);
4846
4847 img->background_transparent
4848 = !four_corners_best (mask, img->width, img->height);
4849
4850 if (free_mask)
4851 XDestroyImage (mask);
4852 }
4853 else
4854 img->background_transparent = 0;
4855
4856 img->background_transparent_valid = 1;
4857 }
4858
4859 return img->background_transparent;
4860 }
4861
4862 \f
4863 /***********************************************************************
4864 Helper functions for X image types
4865 ***********************************************************************/
4866
4867 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
4868 int, int));
4869 static void x_clear_image P_ ((struct frame *f, struct image *img));
4870 static unsigned long x_alloc_image_color P_ ((struct frame *f,
4871 struct image *img,
4872 Lisp_Object color_name,
4873 unsigned long dflt));
4874
4875
4876 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
4877 free the pixmap if any. MASK_P non-zero means clear the mask
4878 pixmap if any. COLORS_P non-zero means free colors allocated for
4879 the image, if any. */
4880
4881 static void
4882 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
4883 struct frame *f;
4884 struct image *img;
4885 int pixmap_p, mask_p, colors_p;
4886 {
4887 if (pixmap_p && img->pixmap)
4888 {
4889 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
4890 img->pixmap = None;
4891 img->background_valid = 0;
4892 }
4893
4894 if (mask_p && img->mask)
4895 {
4896 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
4897 img->mask = None;
4898 img->background_transparent_valid = 0;
4899 }
4900
4901 if (colors_p && img->ncolors)
4902 {
4903 x_free_colors (f, img->colors, img->ncolors);
4904 xfree (img->colors);
4905 img->colors = NULL;
4906 img->ncolors = 0;
4907 }
4908 }
4909
4910 /* Free X resources of image IMG which is used on frame F. */
4911
4912 static void
4913 x_clear_image (f, img)
4914 struct frame *f;
4915 struct image *img;
4916 {
4917 BLOCK_INPUT;
4918 x_clear_image_1 (f, img, 1, 1, 1);
4919 UNBLOCK_INPUT;
4920 }
4921
4922
4923 /* Allocate color COLOR_NAME for image IMG on frame F. If color
4924 cannot be allocated, use DFLT. Add a newly allocated color to
4925 IMG->colors, so that it can be freed again. Value is the pixel
4926 color. */
4927
4928 static unsigned long
4929 x_alloc_image_color (f, img, color_name, dflt)
4930 struct frame *f;
4931 struct image *img;
4932 Lisp_Object color_name;
4933 unsigned long dflt;
4934 {
4935 XColor color;
4936 unsigned long result;
4937
4938 xassert (STRINGP (color_name));
4939
4940 if (x_defined_color (f, SDATA (color_name), &color, 1))
4941 {
4942 /* This isn't called frequently so we get away with simply
4943 reallocating the color vector to the needed size, here. */
4944 ++img->ncolors;
4945 img->colors =
4946 (unsigned long *) xrealloc (img->colors,
4947 img->ncolors * sizeof *img->colors);
4948 img->colors[img->ncolors - 1] = color.pixel;
4949 result = color.pixel;
4950 }
4951 else
4952 result = dflt;
4953
4954 return result;
4955 }
4956
4957
4958 \f
4959 /***********************************************************************
4960 Image Cache
4961 ***********************************************************************/
4962
4963 static void cache_image P_ ((struct frame *f, struct image *img));
4964 static void postprocess_image P_ ((struct frame *, struct image *));
4965
4966
4967 /* Return a new, initialized image cache that is allocated from the
4968 heap. Call free_image_cache to free an image cache. */
4969
4970 struct image_cache *
4971 make_image_cache ()
4972 {
4973 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
4974 int size;
4975
4976 bzero (c, sizeof *c);
4977 c->size = 50;
4978 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
4979 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4980 c->buckets = (struct image **) xmalloc (size);
4981 bzero (c->buckets, size);
4982 return c;
4983 }
4984
4985
4986 /* Free image cache of frame F. Be aware that X frames share images
4987 caches. */
4988
4989 void
4990 free_image_cache (f)
4991 struct frame *f;
4992 {
4993 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4994 if (c)
4995 {
4996 int i;
4997
4998 /* Cache should not be referenced by any frame when freed. */
4999 xassert (c->refcount == 0);
5000
5001 for (i = 0; i < c->used; ++i)
5002 free_image (f, c->images[i]);
5003 xfree (c->images);
5004 xfree (c->buckets);
5005 xfree (c);
5006 FRAME_X_IMAGE_CACHE (f) = NULL;
5007 }
5008 }
5009
5010
5011 /* Clear image cache of frame F. FORCE_P non-zero means free all
5012 images. FORCE_P zero means clear only images that haven't been
5013 displayed for some time. Should be called from time to time to
5014 reduce the number of loaded images. If image-eviction-seconds is
5015 non-nil, this frees images in the cache which weren't displayed for
5016 at least that many seconds. */
5017
5018 void
5019 clear_image_cache (f, force_p)
5020 struct frame *f;
5021 int force_p;
5022 {
5023 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5024
5025 if (c && INTEGERP (Vimage_cache_eviction_delay))
5026 {
5027 EMACS_TIME t;
5028 unsigned long old;
5029 int i, nfreed;
5030
5031 EMACS_GET_TIME (t);
5032 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5033
5034 /* Block input so that we won't be interrupted by a SIGIO
5035 while being in an inconsistent state. */
5036 BLOCK_INPUT;
5037
5038 for (i = nfreed = 0; i < c->used; ++i)
5039 {
5040 struct image *img = c->images[i];
5041 if (img != NULL
5042 && (force_p || img->timestamp < old))
5043 {
5044 free_image (f, img);
5045 ++nfreed;
5046 }
5047 }
5048
5049 /* We may be clearing the image cache because, for example,
5050 Emacs was iconified for a longer period of time. In that
5051 case, current matrices may still contain references to
5052 images freed above. So, clear these matrices. */
5053 if (nfreed)
5054 {
5055 Lisp_Object tail, frame;
5056
5057 FOR_EACH_FRAME (tail, frame)
5058 {
5059 struct frame *f = XFRAME (frame);
5060 if (FRAME_X_P (f)
5061 && FRAME_X_IMAGE_CACHE (f) == c)
5062 clear_current_matrices (f);
5063 }
5064
5065 ++windows_or_buffers_changed;
5066 }
5067
5068 UNBLOCK_INPUT;
5069 }
5070 }
5071
5072
5073 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5074 0, 1, 0,
5075 doc: /* Clear the image cache of FRAME.
5076 FRAME nil or omitted means use the selected frame.
5077 FRAME t means clear the image caches of all frames. */)
5078 (frame)
5079 Lisp_Object frame;
5080 {
5081 if (EQ (frame, Qt))
5082 {
5083 Lisp_Object tail;
5084
5085 FOR_EACH_FRAME (tail, frame)
5086 if (FRAME_X_P (XFRAME (frame)))
5087 clear_image_cache (XFRAME (frame), 1);
5088 }
5089 else
5090 clear_image_cache (check_x_frame (frame), 1);
5091
5092 return Qnil;
5093 }
5094
5095
5096 /* Compute masks and transform image IMG on frame F, as specified
5097 by the image's specification, */
5098
5099 static void
5100 postprocess_image (f, img)
5101 struct frame *f;
5102 struct image *img;
5103 {
5104 /* Manipulation of the image's mask. */
5105 if (img->pixmap)
5106 {
5107 Lisp_Object conversion, spec;
5108 Lisp_Object mask;
5109
5110 spec = img->spec;
5111
5112 /* `:heuristic-mask t'
5113 `:mask heuristic'
5114 means build a mask heuristically.
5115 `:heuristic-mask (R G B)'
5116 `:mask (heuristic (R G B))'
5117 means build a mask from color (R G B) in the
5118 image.
5119 `:mask nil'
5120 means remove a mask, if any. */
5121
5122 mask = image_spec_value (spec, QCheuristic_mask, NULL);
5123 if (!NILP (mask))
5124 x_build_heuristic_mask (f, img, mask);
5125 else
5126 {
5127 int found_p;
5128
5129 mask = image_spec_value (spec, QCmask, &found_p);
5130
5131 if (EQ (mask, Qheuristic))
5132 x_build_heuristic_mask (f, img, Qt);
5133 else if (CONSP (mask)
5134 && EQ (XCAR (mask), Qheuristic))
5135 {
5136 if (CONSP (XCDR (mask)))
5137 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
5138 else
5139 x_build_heuristic_mask (f, img, XCDR (mask));
5140 }
5141 else if (NILP (mask) && found_p && img->mask)
5142 {
5143 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5144 img->mask = None;
5145 }
5146 }
5147
5148
5149 /* Should we apply an image transformation algorithm? */
5150 conversion = image_spec_value (spec, QCconversion, NULL);
5151 if (EQ (conversion, Qdisabled))
5152 x_disable_image (f, img);
5153 else if (EQ (conversion, Qlaplace))
5154 x_laplace (f, img);
5155 else if (EQ (conversion, Qemboss))
5156 x_emboss (f, img);
5157 else if (CONSP (conversion)
5158 && EQ (XCAR (conversion), Qedge_detection))
5159 {
5160 Lisp_Object tem;
5161 tem = XCDR (conversion);
5162 if (CONSP (tem))
5163 x_edge_detection (f, img,
5164 Fplist_get (tem, QCmatrix),
5165 Fplist_get (tem, QCcolor_adjustment));
5166 }
5167 }
5168 }
5169
5170
5171 /* Return the id of image with Lisp specification SPEC on frame F.
5172 SPEC must be a valid Lisp image specification (see valid_image_p). */
5173
5174 int
5175 lookup_image (f, spec)
5176 struct frame *f;
5177 Lisp_Object spec;
5178 {
5179 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5180 struct image *img;
5181 int i;
5182 unsigned hash;
5183 struct gcpro gcpro1;
5184 EMACS_TIME now;
5185
5186 /* F must be a window-system frame, and SPEC must be a valid image
5187 specification. */
5188 xassert (FRAME_WINDOW_P (f));
5189 xassert (valid_image_p (spec));
5190
5191 GCPRO1 (spec);
5192
5193 /* Look up SPEC in the hash table of the image cache. */
5194 hash = sxhash (spec, 0);
5195 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5196
5197 for (img = c->buckets[i]; img; img = img->next)
5198 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5199 break;
5200
5201 /* If not found, create a new image and cache it. */
5202 if (img == NULL)
5203 {
5204 extern Lisp_Object Qpostscript;
5205
5206 BLOCK_INPUT;
5207 img = make_image (spec, hash);
5208 cache_image (f, img);
5209 img->load_failed_p = img->type->load (f, img) == 0;
5210
5211 /* If we can't load the image, and we don't have a width and
5212 height, use some arbitrary width and height so that we can
5213 draw a rectangle for it. */
5214 if (img->load_failed_p)
5215 {
5216 Lisp_Object value;
5217
5218 value = image_spec_value (spec, QCwidth, NULL);
5219 img->width = (INTEGERP (value)
5220 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5221 value = image_spec_value (spec, QCheight, NULL);
5222 img->height = (INTEGERP (value)
5223 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5224 }
5225 else
5226 {
5227 /* Handle image type independent image attributes
5228 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
5229 `:background COLOR'. */
5230 Lisp_Object ascent, margin, relief, bg;
5231
5232 ascent = image_spec_value (spec, QCascent, NULL);
5233 if (INTEGERP (ascent))
5234 img->ascent = XFASTINT (ascent);
5235 else if (EQ (ascent, Qcenter))
5236 img->ascent = CENTERED_IMAGE_ASCENT;
5237
5238 margin = image_spec_value (spec, QCmargin, NULL);
5239 if (INTEGERP (margin) && XINT (margin) >= 0)
5240 img->vmargin = img->hmargin = XFASTINT (margin);
5241 else if (CONSP (margin) && INTEGERP (XCAR (margin))
5242 && INTEGERP (XCDR (margin)))
5243 {
5244 if (XINT (XCAR (margin)) > 0)
5245 img->hmargin = XFASTINT (XCAR (margin));
5246 if (XINT (XCDR (margin)) > 0)
5247 img->vmargin = XFASTINT (XCDR (margin));
5248 }
5249
5250 relief = image_spec_value (spec, QCrelief, NULL);
5251 if (INTEGERP (relief))
5252 {
5253 img->relief = XINT (relief);
5254 img->hmargin += abs (img->relief);
5255 img->vmargin += abs (img->relief);
5256 }
5257
5258 if (! img->background_valid)
5259 {
5260 bg = image_spec_value (img->spec, QCbackground, NULL);
5261 if (!NILP (bg))
5262 {
5263 img->background
5264 = x_alloc_image_color (f, img, bg,
5265 FRAME_BACKGROUND_PIXEL (f));
5266 img->background_valid = 1;
5267 }
5268 }
5269
5270 /* Do image transformations and compute masks, unless we
5271 don't have the image yet. */
5272 if (!EQ (*img->type->type, Qpostscript))
5273 postprocess_image (f, img);
5274 }
5275
5276 UNBLOCK_INPUT;
5277 xassert (!interrupt_input_blocked);
5278 }
5279
5280 /* We're using IMG, so set its timestamp to `now'. */
5281 EMACS_GET_TIME (now);
5282 img->timestamp = EMACS_SECS (now);
5283
5284 UNGCPRO;
5285
5286 /* Value is the image id. */
5287 return img->id;
5288 }
5289
5290
5291 /* Cache image IMG in the image cache of frame F. */
5292
5293 static void
5294 cache_image (f, img)
5295 struct frame *f;
5296 struct image *img;
5297 {
5298 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5299 int i;
5300
5301 /* Find a free slot in c->images. */
5302 for (i = 0; i < c->used; ++i)
5303 if (c->images[i] == NULL)
5304 break;
5305
5306 /* If no free slot found, maybe enlarge c->images. */
5307 if (i == c->used && c->used == c->size)
5308 {
5309 c->size *= 2;
5310 c->images = (struct image **) xrealloc (c->images,
5311 c->size * sizeof *c->images);
5312 }
5313
5314 /* Add IMG to c->images, and assign IMG an id. */
5315 c->images[i] = img;
5316 img->id = i;
5317 if (i == c->used)
5318 ++c->used;
5319
5320 /* Add IMG to the cache's hash table. */
5321 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5322 img->next = c->buckets[i];
5323 if (img->next)
5324 img->next->prev = img;
5325 img->prev = NULL;
5326 c->buckets[i] = img;
5327 }
5328
5329
5330 /* Call FN on every image in the image cache of frame F. Used to mark
5331 Lisp Objects in the image cache. */
5332
5333 void
5334 forall_images_in_image_cache (f, fn)
5335 struct frame *f;
5336 void (*fn) P_ ((struct image *img));
5337 {
5338 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
5339 {
5340 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5341 if (c)
5342 {
5343 int i;
5344 for (i = 0; i < c->used; ++i)
5345 if (c->images[i])
5346 fn (c->images[i]);
5347 }
5348 }
5349 }
5350
5351
5352 \f
5353 /***********************************************************************
5354 X support code
5355 ***********************************************************************/
5356
5357 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
5358 XImage **, Pixmap *));
5359 static void x_destroy_x_image P_ ((XImage *));
5360 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
5361
5362
5363 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5364 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5365 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5366 via xmalloc. Print error messages via image_error if an error
5367 occurs. Value is non-zero if successful. */
5368
5369 static int
5370 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
5371 struct frame *f;
5372 int width, height, depth;
5373 XImage **ximg;
5374 Pixmap *pixmap;
5375 {
5376 Display *display = FRAME_X_DISPLAY (f);
5377 Screen *screen = FRAME_X_SCREEN (f);
5378 Window window = FRAME_X_WINDOW (f);
5379
5380 xassert (interrupt_input_blocked);
5381
5382 if (depth <= 0)
5383 depth = DefaultDepthOfScreen (screen);
5384 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
5385 depth, ZPixmap, 0, NULL, width, height,
5386 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
5387 if (*ximg == NULL)
5388 {
5389 image_error ("Unable to allocate X image", Qnil, Qnil);
5390 return 0;
5391 }
5392
5393 /* Allocate image raster. */
5394 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
5395
5396 /* Allocate a pixmap of the same size. */
5397 *pixmap = XCreatePixmap (display, window, width, height, depth);
5398 if (*pixmap == None)
5399 {
5400 x_destroy_x_image (*ximg);
5401 *ximg = NULL;
5402 image_error ("Unable to create X pixmap", Qnil, Qnil);
5403 return 0;
5404 }
5405
5406 return 1;
5407 }
5408
5409
5410 /* Destroy XImage XIMG. Free XIMG->data. */
5411
5412 static void
5413 x_destroy_x_image (ximg)
5414 XImage *ximg;
5415 {
5416 xassert (interrupt_input_blocked);
5417 if (ximg)
5418 {
5419 xfree (ximg->data);
5420 ximg->data = NULL;
5421 XDestroyImage (ximg);
5422 }
5423 }
5424
5425
5426 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5427 are width and height of both the image and pixmap. */
5428
5429 static void
5430 x_put_x_image (f, ximg, pixmap, width, height)
5431 struct frame *f;
5432 XImage *ximg;
5433 Pixmap pixmap;
5434 int width, height;
5435 {
5436 GC gc;
5437
5438 xassert (interrupt_input_blocked);
5439 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
5440 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
5441 XFreeGC (FRAME_X_DISPLAY (f), gc);
5442 }
5443
5444
5445 \f
5446 /***********************************************************************
5447 File Handling
5448 ***********************************************************************/
5449
5450 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
5451 static char *slurp_file P_ ((char *, int *));
5452
5453
5454 /* Find image file FILE. Look in data-directory, then
5455 x-bitmap-file-path. Value is the full name of the file found, or
5456 nil if not found. */
5457
5458 static Lisp_Object
5459 x_find_image_file (file)
5460 Lisp_Object file;
5461 {
5462 Lisp_Object file_found, search_path;
5463 struct gcpro gcpro1, gcpro2;
5464 int fd;
5465
5466 file_found = Qnil;
5467 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
5468 GCPRO2 (file_found, search_path);
5469
5470 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5471 fd = openp (search_path, file, Qnil, &file_found, Qnil);
5472
5473 if (fd == -1)
5474 file_found = Qnil;
5475 else
5476 close (fd);
5477
5478 UNGCPRO;
5479 return file_found;
5480 }
5481
5482
5483 /* Read FILE into memory. Value is a pointer to a buffer allocated
5484 with xmalloc holding FILE's contents. Value is null if an error
5485 occurred. *SIZE is set to the size of the file. */
5486
5487 static char *
5488 slurp_file (file, size)
5489 char *file;
5490 int *size;
5491 {
5492 FILE *fp = NULL;
5493 char *buf = NULL;
5494 struct stat st;
5495
5496 if (stat (file, &st) == 0
5497 && (fp = fopen (file, "r")) != NULL
5498 && (buf = (char *) xmalloc (st.st_size),
5499 fread (buf, 1, st.st_size, fp) == st.st_size))
5500 {
5501 *size = st.st_size;
5502 fclose (fp);
5503 }
5504 else
5505 {
5506 if (fp)
5507 fclose (fp);
5508 if (buf)
5509 {
5510 xfree (buf);
5511 buf = NULL;
5512 }
5513 }
5514
5515 return buf;
5516 }
5517
5518
5519 \f
5520 /***********************************************************************
5521 XBM images
5522 ***********************************************************************/
5523
5524 static int xbm_scan P_ ((char **, char *, char *, int *));
5525 static int xbm_load P_ ((struct frame *f, struct image *img));
5526 static int xbm_load_image P_ ((struct frame *f, struct image *img,
5527 char *, char *));
5528 static int xbm_image_p P_ ((Lisp_Object object));
5529 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
5530 unsigned char **));
5531 static int xbm_file_p P_ ((Lisp_Object));
5532
5533
5534 /* Indices of image specification fields in xbm_format, below. */
5535
5536 enum xbm_keyword_index
5537 {
5538 XBM_TYPE,
5539 XBM_FILE,
5540 XBM_WIDTH,
5541 XBM_HEIGHT,
5542 XBM_DATA,
5543 XBM_FOREGROUND,
5544 XBM_BACKGROUND,
5545 XBM_ASCENT,
5546 XBM_MARGIN,
5547 XBM_RELIEF,
5548 XBM_ALGORITHM,
5549 XBM_HEURISTIC_MASK,
5550 XBM_MASK,
5551 XBM_LAST
5552 };
5553
5554 /* Vector of image_keyword structures describing the format
5555 of valid XBM image specifications. */
5556
5557 static struct image_keyword xbm_format[XBM_LAST] =
5558 {
5559 {":type", IMAGE_SYMBOL_VALUE, 1},
5560 {":file", IMAGE_STRING_VALUE, 0},
5561 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5562 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5563 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5564 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5565 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
5566 {":ascent", IMAGE_ASCENT_VALUE, 0},
5567 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5568 {":relief", IMAGE_INTEGER_VALUE, 0},
5569 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5570 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5571 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5572 };
5573
5574 /* Structure describing the image type XBM. */
5575
5576 static struct image_type xbm_type =
5577 {
5578 &Qxbm,
5579 xbm_image_p,
5580 xbm_load,
5581 x_clear_image,
5582 NULL
5583 };
5584
5585 /* Tokens returned from xbm_scan. */
5586
5587 enum xbm_token
5588 {
5589 XBM_TK_IDENT = 256,
5590 XBM_TK_NUMBER
5591 };
5592
5593
5594 /* Return non-zero if OBJECT is a valid XBM-type image specification.
5595 A valid specification is a list starting with the symbol `image'
5596 The rest of the list is a property list which must contain an
5597 entry `:type xbm..
5598
5599 If the specification specifies a file to load, it must contain
5600 an entry `:file FILENAME' where FILENAME is a string.
5601
5602 If the specification is for a bitmap loaded from memory it must
5603 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
5604 WIDTH and HEIGHT are integers > 0. DATA may be:
5605
5606 1. a string large enough to hold the bitmap data, i.e. it must
5607 have a size >= (WIDTH + 7) / 8 * HEIGHT
5608
5609 2. a bool-vector of size >= WIDTH * HEIGHT
5610
5611 3. a vector of strings or bool-vectors, one for each line of the
5612 bitmap.
5613
5614 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
5615 may not be specified in this case because they are defined in the
5616 XBM file.
5617
5618 Both the file and data forms may contain the additional entries
5619 `:background COLOR' and `:foreground COLOR'. If not present,
5620 foreground and background of the frame on which the image is
5621 displayed is used. */
5622
5623 static int
5624 xbm_image_p (object)
5625 Lisp_Object object;
5626 {
5627 struct image_keyword kw[XBM_LAST];
5628
5629 bcopy (xbm_format, kw, sizeof kw);
5630 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
5631 return 0;
5632
5633 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
5634
5635 if (kw[XBM_FILE].count)
5636 {
5637 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
5638 return 0;
5639 }
5640 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
5641 {
5642 /* In-memory XBM file. */
5643 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
5644 return 0;
5645 }
5646 else
5647 {
5648 Lisp_Object data;
5649 int width, height;
5650
5651 /* Entries for `:width', `:height' and `:data' must be present. */
5652 if (!kw[XBM_WIDTH].count
5653 || !kw[XBM_HEIGHT].count
5654 || !kw[XBM_DATA].count)
5655 return 0;
5656
5657 data = kw[XBM_DATA].value;
5658 width = XFASTINT (kw[XBM_WIDTH].value);
5659 height = XFASTINT (kw[XBM_HEIGHT].value);
5660
5661 /* Check type of data, and width and height against contents of
5662 data. */
5663 if (VECTORP (data))
5664 {
5665 int i;
5666
5667 /* Number of elements of the vector must be >= height. */
5668 if (XVECTOR (data)->size < height)
5669 return 0;
5670
5671 /* Each string or bool-vector in data must be large enough
5672 for one line of the image. */
5673 for (i = 0; i < height; ++i)
5674 {
5675 Lisp_Object elt = XVECTOR (data)->contents[i];
5676
5677 if (STRINGP (elt))
5678 {
5679 if (SCHARS (elt)
5680 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
5681 return 0;
5682 }
5683 else if (BOOL_VECTOR_P (elt))
5684 {
5685 if (XBOOL_VECTOR (elt)->size < width)
5686 return 0;
5687 }
5688 else
5689 return 0;
5690 }
5691 }
5692 else if (STRINGP (data))
5693 {
5694 if (SCHARS (data)
5695 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
5696 return 0;
5697 }
5698 else if (BOOL_VECTOR_P (data))
5699 {
5700 if (XBOOL_VECTOR (data)->size < width * height)
5701 return 0;
5702 }
5703 else
5704 return 0;
5705 }
5706
5707 return 1;
5708 }
5709
5710
5711 /* Scan a bitmap file. FP is the stream to read from. Value is
5712 either an enumerator from enum xbm_token, or a character for a
5713 single-character token, or 0 at end of file. If scanning an
5714 identifier, store the lexeme of the identifier in SVAL. If
5715 scanning a number, store its value in *IVAL. */
5716
5717 static int
5718 xbm_scan (s, end, sval, ival)
5719 char **s, *end;
5720 char *sval;
5721 int *ival;
5722 {
5723 int c;
5724
5725 loop:
5726
5727 /* Skip white space. */
5728 while (*s < end && (c = *(*s)++, isspace (c)))
5729 ;
5730
5731 if (*s >= end)
5732 c = 0;
5733 else if (isdigit (c))
5734 {
5735 int value = 0, digit;
5736
5737 if (c == '0' && *s < end)
5738 {
5739 c = *(*s)++;
5740 if (c == 'x' || c == 'X')
5741 {
5742 while (*s < end)
5743 {
5744 c = *(*s)++;
5745 if (isdigit (c))
5746 digit = c - '0';
5747 else if (c >= 'a' && c <= 'f')
5748 digit = c - 'a' + 10;
5749 else if (c >= 'A' && c <= 'F')
5750 digit = c - 'A' + 10;
5751 else
5752 break;
5753 value = 16 * value + digit;
5754 }
5755 }
5756 else if (isdigit (c))
5757 {
5758 value = c - '0';
5759 while (*s < end
5760 && (c = *(*s)++, isdigit (c)))
5761 value = 8 * value + c - '0';
5762 }
5763 }
5764 else
5765 {
5766 value = c - '0';
5767 while (*s < end
5768 && (c = *(*s)++, isdigit (c)))
5769 value = 10 * value + c - '0';
5770 }
5771
5772 if (*s < end)
5773 *s = *s - 1;
5774 *ival = value;
5775 c = XBM_TK_NUMBER;
5776 }
5777 else if (isalpha (c) || c == '_')
5778 {
5779 *sval++ = c;
5780 while (*s < end
5781 && (c = *(*s)++, (isalnum (c) || c == '_')))
5782 *sval++ = c;
5783 *sval = 0;
5784 if (*s < end)
5785 *s = *s - 1;
5786 c = XBM_TK_IDENT;
5787 }
5788 else if (c == '/' && **s == '*')
5789 {
5790 /* C-style comment. */
5791 ++*s;
5792 while (**s && (**s != '*' || *(*s + 1) != '/'))
5793 ++*s;
5794 if (**s)
5795 {
5796 *s += 2;
5797 goto loop;
5798 }
5799 }
5800
5801 return c;
5802 }
5803
5804
5805 /* Replacement for XReadBitmapFileData which isn't available under old
5806 X versions. CONTENTS is a pointer to a buffer to parse; END is the
5807 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
5808 the image. Return in *DATA the bitmap data allocated with xmalloc.
5809 Value is non-zero if successful. DATA null means just test if
5810 CONTENTS looks like an in-memory XBM file. */
5811
5812 static int
5813 xbm_read_bitmap_data (contents, end, width, height, data)
5814 char *contents, *end;
5815 int *width, *height;
5816 unsigned char **data;
5817 {
5818 char *s = contents;
5819 char buffer[BUFSIZ];
5820 int padding_p = 0;
5821 int v10 = 0;
5822 int bytes_per_line, i, nbytes;
5823 unsigned char *p;
5824 int value;
5825 int LA1;
5826
5827 #define match() \
5828 LA1 = xbm_scan (&s, end, buffer, &value)
5829
5830 #define expect(TOKEN) \
5831 if (LA1 != (TOKEN)) \
5832 goto failure; \
5833 else \
5834 match ()
5835
5836 #define expect_ident(IDENT) \
5837 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
5838 match (); \
5839 else \
5840 goto failure
5841
5842 *width = *height = -1;
5843 if (data)
5844 *data = NULL;
5845 LA1 = xbm_scan (&s, end, buffer, &value);
5846
5847 /* Parse defines for width, height and hot-spots. */
5848 while (LA1 == '#')
5849 {
5850 match ();
5851 expect_ident ("define");
5852 expect (XBM_TK_IDENT);
5853
5854 if (LA1 == XBM_TK_NUMBER);
5855 {
5856 char *p = strrchr (buffer, '_');
5857 p = p ? p + 1 : buffer;
5858 if (strcmp (p, "width") == 0)
5859 *width = value;
5860 else if (strcmp (p, "height") == 0)
5861 *height = value;
5862 }
5863 expect (XBM_TK_NUMBER);
5864 }
5865
5866 if (*width < 0 || *height < 0)
5867 goto failure;
5868 else if (data == NULL)
5869 goto success;
5870
5871 /* Parse bits. Must start with `static'. */
5872 expect_ident ("static");
5873 if (LA1 == XBM_TK_IDENT)
5874 {
5875 if (strcmp (buffer, "unsigned") == 0)
5876 {
5877 match ();
5878 expect_ident ("char");
5879 }
5880 else if (strcmp (buffer, "short") == 0)
5881 {
5882 match ();
5883 v10 = 1;
5884 if (*width % 16 && *width % 16 < 9)
5885 padding_p = 1;
5886 }
5887 else if (strcmp (buffer, "char") == 0)
5888 match ();
5889 else
5890 goto failure;
5891 }
5892 else
5893 goto failure;
5894
5895 expect (XBM_TK_IDENT);
5896 expect ('[');
5897 expect (']');
5898 expect ('=');
5899 expect ('{');
5900
5901 bytes_per_line = (*width + 7) / 8 + padding_p;
5902 nbytes = bytes_per_line * *height;
5903 p = *data = (char *) xmalloc (nbytes);
5904
5905 if (v10)
5906 {
5907 for (i = 0; i < nbytes; i += 2)
5908 {
5909 int val = value;
5910 expect (XBM_TK_NUMBER);
5911
5912 *p++ = val;
5913 if (!padding_p || ((i + 2) % bytes_per_line))
5914 *p++ = value >> 8;
5915
5916 if (LA1 == ',' || LA1 == '}')
5917 match ();
5918 else
5919 goto failure;
5920 }
5921 }
5922 else
5923 {
5924 for (i = 0; i < nbytes; ++i)
5925 {
5926 int val = value;
5927 expect (XBM_TK_NUMBER);
5928
5929 *p++ = val;
5930
5931 if (LA1 == ',' || LA1 == '}')
5932 match ();
5933 else
5934 goto failure;
5935 }
5936 }
5937
5938 success:
5939 return 1;
5940
5941 failure:
5942
5943 if (data && *data)
5944 {
5945 xfree (*data);
5946 *data = NULL;
5947 }
5948 return 0;
5949
5950 #undef match
5951 #undef expect
5952 #undef expect_ident
5953 }
5954
5955
5956 /* Load XBM image IMG which will be displayed on frame F from buffer
5957 CONTENTS. END is the end of the buffer. Value is non-zero if
5958 successful. */
5959
5960 static int
5961 xbm_load_image (f, img, contents, end)
5962 struct frame *f;
5963 struct image *img;
5964 char *contents, *end;
5965 {
5966 int rc;
5967 unsigned char *data;
5968 int success_p = 0;
5969
5970 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
5971 if (rc)
5972 {
5973 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
5974 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
5975 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
5976 Lisp_Object value;
5977
5978 xassert (img->width > 0 && img->height > 0);
5979
5980 /* Get foreground and background colors, maybe allocate colors. */
5981 value = image_spec_value (img->spec, QCforeground, NULL);
5982 if (!NILP (value))
5983 foreground = x_alloc_image_color (f, img, value, foreground);
5984 value = image_spec_value (img->spec, QCbackground, NULL);
5985 if (!NILP (value))
5986 {
5987 background = x_alloc_image_color (f, img, value, background);
5988 img->background = background;
5989 img->background_valid = 1;
5990 }
5991
5992 img->pixmap
5993 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
5994 FRAME_X_WINDOW (f),
5995 data,
5996 img->width, img->height,
5997 foreground, background,
5998 depth);
5999 xfree (data);
6000
6001 if (img->pixmap == None)
6002 {
6003 x_clear_image (f, img);
6004 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6005 }
6006 else
6007 success_p = 1;
6008 }
6009 else
6010 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6011
6012 return success_p;
6013 }
6014
6015
6016 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6017
6018 static int
6019 xbm_file_p (data)
6020 Lisp_Object data;
6021 {
6022 int w, h;
6023 return (STRINGP (data)
6024 && xbm_read_bitmap_data (SDATA (data),
6025 (SDATA (data)
6026 + SBYTES (data)),
6027 &w, &h, NULL));
6028 }
6029
6030
6031 /* Fill image IMG which is used on frame F with pixmap data. Value is
6032 non-zero if successful. */
6033
6034 static int
6035 xbm_load (f, img)
6036 struct frame *f;
6037 struct image *img;
6038 {
6039 int success_p = 0;
6040 Lisp_Object file_name;
6041
6042 xassert (xbm_image_p (img->spec));
6043
6044 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6045 file_name = image_spec_value (img->spec, QCfile, NULL);
6046 if (STRINGP (file_name))
6047 {
6048 Lisp_Object file;
6049 char *contents;
6050 int size;
6051 struct gcpro gcpro1;
6052
6053 file = x_find_image_file (file_name);
6054 GCPRO1 (file);
6055 if (!STRINGP (file))
6056 {
6057 image_error ("Cannot find image file `%s'", file_name, Qnil);
6058 UNGCPRO;
6059 return 0;
6060 }
6061
6062 contents = slurp_file (SDATA (file), &size);
6063 if (contents == NULL)
6064 {
6065 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6066 UNGCPRO;
6067 return 0;
6068 }
6069
6070 success_p = xbm_load_image (f, img, contents, contents + size);
6071 UNGCPRO;
6072 }
6073 else
6074 {
6075 struct image_keyword fmt[XBM_LAST];
6076 Lisp_Object data;
6077 int depth;
6078 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6079 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6080 char *bits;
6081 int parsed_p;
6082 int in_memory_file_p = 0;
6083
6084 /* See if data looks like an in-memory XBM file. */
6085 data = image_spec_value (img->spec, QCdata, NULL);
6086 in_memory_file_p = xbm_file_p (data);
6087
6088 /* Parse the image specification. */
6089 bcopy (xbm_format, fmt, sizeof fmt);
6090 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6091 xassert (parsed_p);
6092
6093 /* Get specified width, and height. */
6094 if (!in_memory_file_p)
6095 {
6096 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6097 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6098 xassert (img->width > 0 && img->height > 0);
6099 }
6100
6101 /* Get foreground and background colors, maybe allocate colors. */
6102 if (fmt[XBM_FOREGROUND].count
6103 && STRINGP (fmt[XBM_FOREGROUND].value))
6104 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6105 foreground);
6106 if (fmt[XBM_BACKGROUND].count
6107 && STRINGP (fmt[XBM_BACKGROUND].value))
6108 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6109 background);
6110
6111 if (in_memory_file_p)
6112 success_p = xbm_load_image (f, img, SDATA (data),
6113 (SDATA (data)
6114 + SBYTES (data)));
6115 else
6116 {
6117 if (VECTORP (data))
6118 {
6119 int i;
6120 char *p;
6121 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6122
6123 p = bits = (char *) alloca (nbytes * img->height);
6124 for (i = 0; i < img->height; ++i, p += nbytes)
6125 {
6126 Lisp_Object line = XVECTOR (data)->contents[i];
6127 if (STRINGP (line))
6128 bcopy (SDATA (line), p, nbytes);
6129 else
6130 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6131 }
6132 }
6133 else if (STRINGP (data))
6134 bits = SDATA (data);
6135 else
6136 bits = XBOOL_VECTOR (data)->data;
6137
6138 /* Create the pixmap. */
6139 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6140 img->pixmap
6141 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6142 FRAME_X_WINDOW (f),
6143 bits,
6144 img->width, img->height,
6145 foreground, background,
6146 depth);
6147 if (img->pixmap)
6148 success_p = 1;
6149 else
6150 {
6151 image_error ("Unable to create pixmap for XBM image `%s'",
6152 img->spec, Qnil);
6153 x_clear_image (f, img);
6154 }
6155 }
6156 }
6157
6158 return success_p;
6159 }
6160
6161
6162 \f
6163 /***********************************************************************
6164 XPM images
6165 ***********************************************************************/
6166
6167 #if HAVE_XPM
6168
6169 static int xpm_image_p P_ ((Lisp_Object object));
6170 static int xpm_load P_ ((struct frame *f, struct image *img));
6171 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6172
6173 #include "X11/xpm.h"
6174
6175 /* The symbol `xpm' identifying XPM-format images. */
6176
6177 Lisp_Object Qxpm;
6178
6179 /* Indices of image specification fields in xpm_format, below. */
6180
6181 enum xpm_keyword_index
6182 {
6183 XPM_TYPE,
6184 XPM_FILE,
6185 XPM_DATA,
6186 XPM_ASCENT,
6187 XPM_MARGIN,
6188 XPM_RELIEF,
6189 XPM_ALGORITHM,
6190 XPM_HEURISTIC_MASK,
6191 XPM_MASK,
6192 XPM_COLOR_SYMBOLS,
6193 XPM_BACKGROUND,
6194 XPM_LAST
6195 };
6196
6197 /* Vector of image_keyword structures describing the format
6198 of valid XPM image specifications. */
6199
6200 static struct image_keyword xpm_format[XPM_LAST] =
6201 {
6202 {":type", IMAGE_SYMBOL_VALUE, 1},
6203 {":file", IMAGE_STRING_VALUE, 0},
6204 {":data", IMAGE_STRING_VALUE, 0},
6205 {":ascent", IMAGE_ASCENT_VALUE, 0},
6206 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6207 {":relief", IMAGE_INTEGER_VALUE, 0},
6208 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6209 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6210 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6211 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6212 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6213 };
6214
6215 /* Structure describing the image type XBM. */
6216
6217 static struct image_type xpm_type =
6218 {
6219 &Qxpm,
6220 xpm_image_p,
6221 xpm_load,
6222 x_clear_image,
6223 NULL
6224 };
6225
6226
6227 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
6228 functions for allocating image colors. Our own functions handle
6229 color allocation failures more gracefully than the ones on the XPM
6230 lib. */
6231
6232 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
6233 #define ALLOC_XPM_COLORS
6234 #endif
6235
6236 #ifdef ALLOC_XPM_COLORS
6237
6238 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
6239 static void xpm_free_color_cache P_ ((void));
6240 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
6241 static int xpm_color_bucket P_ ((char *));
6242 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
6243 XColor *, int));
6244
6245 /* An entry in a hash table used to cache color definitions of named
6246 colors. This cache is necessary to speed up XPM image loading in
6247 case we do color allocations ourselves. Without it, we would need
6248 a call to XParseColor per pixel in the image. */
6249
6250 struct xpm_cached_color
6251 {
6252 /* Next in collision chain. */
6253 struct xpm_cached_color *next;
6254
6255 /* Color definition (RGB and pixel color). */
6256 XColor color;
6257
6258 /* Color name. */
6259 char name[1];
6260 };
6261
6262 /* The hash table used for the color cache, and its bucket vector
6263 size. */
6264
6265 #define XPM_COLOR_CACHE_BUCKETS 1001
6266 struct xpm_cached_color **xpm_color_cache;
6267
6268 /* Initialize the color cache. */
6269
6270 static void
6271 xpm_init_color_cache (f, attrs)
6272 struct frame *f;
6273 XpmAttributes *attrs;
6274 {
6275 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
6276 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
6277 memset (xpm_color_cache, 0, nbytes);
6278 init_color_table ();
6279
6280 if (attrs->valuemask & XpmColorSymbols)
6281 {
6282 int i;
6283 XColor color;
6284
6285 for (i = 0; i < attrs->numsymbols; ++i)
6286 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
6287 attrs->colorsymbols[i].value, &color))
6288 {
6289 color.pixel = lookup_rgb_color (f, color.red, color.green,
6290 color.blue);
6291 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
6292 }
6293 }
6294 }
6295
6296
6297 /* Free the color cache. */
6298
6299 static void
6300 xpm_free_color_cache ()
6301 {
6302 struct xpm_cached_color *p, *next;
6303 int i;
6304
6305 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
6306 for (p = xpm_color_cache[i]; p; p = next)
6307 {
6308 next = p->next;
6309 xfree (p);
6310 }
6311
6312 xfree (xpm_color_cache);
6313 xpm_color_cache = NULL;
6314 free_color_table ();
6315 }
6316
6317
6318 /* Return the bucket index for color named COLOR_NAME in the color
6319 cache. */
6320
6321 static int
6322 xpm_color_bucket (color_name)
6323 char *color_name;
6324 {
6325 unsigned h = 0;
6326 char *s;
6327
6328 for (s = color_name; *s; ++s)
6329 h = (h << 2) ^ *s;
6330 return h %= XPM_COLOR_CACHE_BUCKETS;
6331 }
6332
6333
6334 /* On frame F, cache values COLOR for color with name COLOR_NAME.
6335 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
6336 entry added. */
6337
6338 static struct xpm_cached_color *
6339 xpm_cache_color (f, color_name, color, bucket)
6340 struct frame *f;
6341 char *color_name;
6342 XColor *color;
6343 int bucket;
6344 {
6345 size_t nbytes;
6346 struct xpm_cached_color *p;
6347
6348 if (bucket < 0)
6349 bucket = xpm_color_bucket (color_name);
6350
6351 nbytes = sizeof *p + strlen (color_name);
6352 p = (struct xpm_cached_color *) xmalloc (nbytes);
6353 strcpy (p->name, color_name);
6354 p->color = *color;
6355 p->next = xpm_color_cache[bucket];
6356 xpm_color_cache[bucket] = p;
6357 return p;
6358 }
6359
6360
6361 /* Look up color COLOR_NAME for frame F in the color cache. If found,
6362 return the cached definition in *COLOR. Otherwise, make a new
6363 entry in the cache and allocate the color. Value is zero if color
6364 allocation failed. */
6365
6366 static int
6367 xpm_lookup_color (f, color_name, color)
6368 struct frame *f;
6369 char *color_name;
6370 XColor *color;
6371 {
6372 struct xpm_cached_color *p;
6373 int h = xpm_color_bucket (color_name);
6374
6375 for (p = xpm_color_cache[h]; p; p = p->next)
6376 if (strcmp (p->name, color_name) == 0)
6377 break;
6378
6379 if (p != NULL)
6380 *color = p->color;
6381 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
6382 color_name, color))
6383 {
6384 color->pixel = lookup_rgb_color (f, color->red, color->green,
6385 color->blue);
6386 p = xpm_cache_color (f, color_name, color, h);
6387 }
6388 /* You get `opaque' at least from ImageMagick converting pbm to xpm
6389 with transparency, and it's useful. */
6390 else if (strcmp ("opaque", color_name) == 0)
6391 {
6392 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
6393 color->pixel = FRAME_FOREGROUND_PIXEL (f);
6394 p = xpm_cache_color (f, color_name, color, h);
6395 }
6396
6397 return p != NULL;
6398 }
6399
6400
6401 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
6402 CLOSURE is a pointer to the frame on which we allocate the
6403 color. Return in *COLOR the allocated color. Value is non-zero
6404 if successful. */
6405
6406 static int
6407 xpm_alloc_color (dpy, cmap, color_name, color, closure)
6408 Display *dpy;
6409 Colormap cmap;
6410 char *color_name;
6411 XColor *color;
6412 void *closure;
6413 {
6414 return xpm_lookup_color ((struct frame *) closure, color_name, color);
6415 }
6416
6417
6418 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
6419 is a pointer to the frame on which we allocate the color. Value is
6420 non-zero if successful. */
6421
6422 static int
6423 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
6424 Display *dpy;
6425 Colormap cmap;
6426 Pixel *pixels;
6427 int npixels;
6428 void *closure;
6429 {
6430 return 1;
6431 }
6432
6433 #endif /* ALLOC_XPM_COLORS */
6434
6435
6436 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6437 for XPM images. Such a list must consist of conses whose car and
6438 cdr are strings. */
6439
6440 static int
6441 xpm_valid_color_symbols_p (color_symbols)
6442 Lisp_Object color_symbols;
6443 {
6444 while (CONSP (color_symbols))
6445 {
6446 Lisp_Object sym = XCAR (color_symbols);
6447 if (!CONSP (sym)
6448 || !STRINGP (XCAR (sym))
6449 || !STRINGP (XCDR (sym)))
6450 break;
6451 color_symbols = XCDR (color_symbols);
6452 }
6453
6454 return NILP (color_symbols);
6455 }
6456
6457
6458 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6459
6460 static int
6461 xpm_image_p (object)
6462 Lisp_Object object;
6463 {
6464 struct image_keyword fmt[XPM_LAST];
6465 bcopy (xpm_format, fmt, sizeof fmt);
6466 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
6467 /* Either `:file' or `:data' must be present. */
6468 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
6469 /* Either no `:color-symbols' or it's a list of conses
6470 whose car and cdr are strings. */
6471 && (fmt[XPM_COLOR_SYMBOLS].count == 0
6472 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
6473 }
6474
6475
6476 /* Load image IMG which will be displayed on frame F. Value is
6477 non-zero if successful. */
6478
6479 static int
6480 xpm_load (f, img)
6481 struct frame *f;
6482 struct image *img;
6483 {
6484 int rc;
6485 XpmAttributes attrs;
6486 Lisp_Object specified_file, color_symbols;
6487
6488 /* Configure the XPM lib. Use the visual of frame F. Allocate
6489 close colors. Return colors allocated. */
6490 bzero (&attrs, sizeof attrs);
6491 attrs.visual = FRAME_X_VISUAL (f);
6492 attrs.colormap = FRAME_X_COLORMAP (f);
6493 attrs.valuemask |= XpmVisual;
6494 attrs.valuemask |= XpmColormap;
6495
6496 #ifdef ALLOC_XPM_COLORS
6497 /* Allocate colors with our own functions which handle
6498 failing color allocation more gracefully. */
6499 attrs.color_closure = f;
6500 attrs.alloc_color = xpm_alloc_color;
6501 attrs.free_colors = xpm_free_colors;
6502 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
6503 #else /* not ALLOC_XPM_COLORS */
6504 /* Let the XPM lib allocate colors. */
6505 attrs.valuemask |= XpmReturnAllocPixels;
6506 #ifdef XpmAllocCloseColors
6507 attrs.alloc_close_colors = 1;
6508 attrs.valuemask |= XpmAllocCloseColors;
6509 #else /* not XpmAllocCloseColors */
6510 attrs.closeness = 600;
6511 attrs.valuemask |= XpmCloseness;
6512 #endif /* not XpmAllocCloseColors */
6513 #endif /* ALLOC_XPM_COLORS */
6514
6515 /* If image specification contains symbolic color definitions, add
6516 these to `attrs'. */
6517 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
6518 if (CONSP (color_symbols))
6519 {
6520 Lisp_Object tail;
6521 XpmColorSymbol *xpm_syms;
6522 int i, size;
6523
6524 attrs.valuemask |= XpmColorSymbols;
6525
6526 /* Count number of symbols. */
6527 attrs.numsymbols = 0;
6528 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
6529 ++attrs.numsymbols;
6530
6531 /* Allocate an XpmColorSymbol array. */
6532 size = attrs.numsymbols * sizeof *xpm_syms;
6533 xpm_syms = (XpmColorSymbol *) alloca (size);
6534 bzero (xpm_syms, size);
6535 attrs.colorsymbols = xpm_syms;
6536
6537 /* Fill the color symbol array. */
6538 for (tail = color_symbols, i = 0;
6539 CONSP (tail);
6540 ++i, tail = XCDR (tail))
6541 {
6542 Lisp_Object name = XCAR (XCAR (tail));
6543 Lisp_Object color = XCDR (XCAR (tail));
6544 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
6545 strcpy (xpm_syms[i].name, SDATA (name));
6546 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
6547 strcpy (xpm_syms[i].value, SDATA (color));
6548 }
6549 }
6550
6551 /* Create a pixmap for the image, either from a file, or from a
6552 string buffer containing data in the same format as an XPM file. */
6553 #ifdef ALLOC_XPM_COLORS
6554 xpm_init_color_cache (f, &attrs);
6555 #endif
6556
6557 specified_file = image_spec_value (img->spec, QCfile, NULL);
6558 if (STRINGP (specified_file))
6559 {
6560 Lisp_Object file = x_find_image_file (specified_file);
6561 if (!STRINGP (file))
6562 {
6563 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6564 return 0;
6565 }
6566
6567 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6568 SDATA (file), &img->pixmap, &img->mask,
6569 &attrs);
6570 }
6571 else
6572 {
6573 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
6574 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6575 SDATA (buffer),
6576 &img->pixmap, &img->mask,
6577 &attrs);
6578 }
6579
6580 if (rc == XpmSuccess)
6581 {
6582 #ifdef ALLOC_XPM_COLORS
6583 img->colors = colors_in_color_table (&img->ncolors);
6584 #else /* not ALLOC_XPM_COLORS */
6585 int i;
6586
6587 img->ncolors = attrs.nalloc_pixels;
6588 img->colors = (unsigned long *) xmalloc (img->ncolors
6589 * sizeof *img->colors);
6590 for (i = 0; i < attrs.nalloc_pixels; ++i)
6591 {
6592 img->colors[i] = attrs.alloc_pixels[i];
6593 #ifdef DEBUG_X_COLORS
6594 register_color (img->colors[i]);
6595 #endif
6596 }
6597 #endif /* not ALLOC_XPM_COLORS */
6598
6599 img->width = attrs.width;
6600 img->height = attrs.height;
6601 xassert (img->width > 0 && img->height > 0);
6602
6603 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6604 XpmFreeAttributes (&attrs);
6605 }
6606 else
6607 {
6608 switch (rc)
6609 {
6610 case XpmOpenFailed:
6611 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
6612 break;
6613
6614 case XpmFileInvalid:
6615 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
6616 break;
6617
6618 case XpmNoMemory:
6619 image_error ("Out of memory (%s)", img->spec, Qnil);
6620 break;
6621
6622 case XpmColorFailed:
6623 image_error ("Color allocation error (%s)", img->spec, Qnil);
6624 break;
6625
6626 default:
6627 image_error ("Unknown error (%s)", img->spec, Qnil);
6628 break;
6629 }
6630 }
6631
6632 #ifdef ALLOC_XPM_COLORS
6633 xpm_free_color_cache ();
6634 #endif
6635 return rc == XpmSuccess;
6636 }
6637
6638 #endif /* HAVE_XPM != 0 */
6639
6640 \f
6641 /***********************************************************************
6642 Color table
6643 ***********************************************************************/
6644
6645 /* An entry in the color table mapping an RGB color to a pixel color. */
6646
6647 struct ct_color
6648 {
6649 int r, g, b;
6650 unsigned long pixel;
6651
6652 /* Next in color table collision list. */
6653 struct ct_color *next;
6654 };
6655
6656 /* The bucket vector size to use. Must be prime. */
6657
6658 #define CT_SIZE 101
6659
6660 /* Value is a hash of the RGB color given by R, G, and B. */
6661
6662 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6663
6664 /* The color hash table. */
6665
6666 struct ct_color **ct_table;
6667
6668 /* Number of entries in the color table. */
6669
6670 int ct_colors_allocated;
6671
6672 /* Initialize the color table. */
6673
6674 static void
6675 init_color_table ()
6676 {
6677 int size = CT_SIZE * sizeof (*ct_table);
6678 ct_table = (struct ct_color **) xmalloc (size);
6679 bzero (ct_table, size);
6680 ct_colors_allocated = 0;
6681 }
6682
6683
6684 /* Free memory associated with the color table. */
6685
6686 static void
6687 free_color_table ()
6688 {
6689 int i;
6690 struct ct_color *p, *next;
6691
6692 for (i = 0; i < CT_SIZE; ++i)
6693 for (p = ct_table[i]; p; p = next)
6694 {
6695 next = p->next;
6696 xfree (p);
6697 }
6698
6699 xfree (ct_table);
6700 ct_table = NULL;
6701 }
6702
6703
6704 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6705 entry for that color already is in the color table, return the
6706 pixel color of that entry. Otherwise, allocate a new color for R,
6707 G, B, and make an entry in the color table. */
6708
6709 static unsigned long
6710 lookup_rgb_color (f, r, g, b)
6711 struct frame *f;
6712 int r, g, b;
6713 {
6714 unsigned hash = CT_HASH_RGB (r, g, b);
6715 int i = hash % CT_SIZE;
6716 struct ct_color *p;
6717
6718 for (p = ct_table[i]; p; p = p->next)
6719 if (p->r == r && p->g == g && p->b == b)
6720 break;
6721
6722 if (p == NULL)
6723 {
6724 XColor color;
6725 Colormap cmap;
6726 int rc;
6727
6728 color.red = r;
6729 color.green = g;
6730 color.blue = b;
6731
6732 cmap = FRAME_X_COLORMAP (f);
6733 rc = x_alloc_nearest_color (f, cmap, &color);
6734
6735 if (rc)
6736 {
6737 ++ct_colors_allocated;
6738
6739 p = (struct ct_color *) xmalloc (sizeof *p);
6740 p->r = r;
6741 p->g = g;
6742 p->b = b;
6743 p->pixel = color.pixel;
6744 p->next = ct_table[i];
6745 ct_table[i] = p;
6746 }
6747 else
6748 return FRAME_FOREGROUND_PIXEL (f);
6749 }
6750
6751 return p->pixel;
6752 }
6753
6754
6755 /* Look up pixel color PIXEL which is used on frame F in the color
6756 table. If not already present, allocate it. Value is PIXEL. */
6757
6758 static unsigned long
6759 lookup_pixel_color (f, pixel)
6760 struct frame *f;
6761 unsigned long pixel;
6762 {
6763 int i = pixel % CT_SIZE;
6764 struct ct_color *p;
6765
6766 for (p = ct_table[i]; p; p = p->next)
6767 if (p->pixel == pixel)
6768 break;
6769
6770 if (p == NULL)
6771 {
6772 XColor color;
6773 Colormap cmap;
6774 int rc;
6775
6776 cmap = FRAME_X_COLORMAP (f);
6777 color.pixel = pixel;
6778 x_query_color (f, &color);
6779 rc = x_alloc_nearest_color (f, cmap, &color);
6780
6781 if (rc)
6782 {
6783 ++ct_colors_allocated;
6784
6785 p = (struct ct_color *) xmalloc (sizeof *p);
6786 p->r = color.red;
6787 p->g = color.green;
6788 p->b = color.blue;
6789 p->pixel = pixel;
6790 p->next = ct_table[i];
6791 ct_table[i] = p;
6792 }
6793 else
6794 return FRAME_FOREGROUND_PIXEL (f);
6795 }
6796
6797 return p->pixel;
6798 }
6799
6800
6801 /* Value is a vector of all pixel colors contained in the color table,
6802 allocated via xmalloc. Set *N to the number of colors. */
6803
6804 static unsigned long *
6805 colors_in_color_table (n)
6806 int *n;
6807 {
6808 int i, j;
6809 struct ct_color *p;
6810 unsigned long *colors;
6811
6812 if (ct_colors_allocated == 0)
6813 {
6814 *n = 0;
6815 colors = NULL;
6816 }
6817 else
6818 {
6819 colors = (unsigned long *) xmalloc (ct_colors_allocated
6820 * sizeof *colors);
6821 *n = ct_colors_allocated;
6822
6823 for (i = j = 0; i < CT_SIZE; ++i)
6824 for (p = ct_table[i]; p; p = p->next)
6825 colors[j++] = p->pixel;
6826 }
6827
6828 return colors;
6829 }
6830
6831
6832 \f
6833 /***********************************************************************
6834 Algorithms
6835 ***********************************************************************/
6836
6837 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
6838 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
6839 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
6840
6841 /* Non-zero means draw a cross on images having `:conversion
6842 disabled'. */
6843
6844 int cross_disabled_images;
6845
6846 /* Edge detection matrices for different edge-detection
6847 strategies. */
6848
6849 static int emboss_matrix[9] = {
6850 /* x - 1 x x + 1 */
6851 2, -1, 0, /* y - 1 */
6852 -1, 0, 1, /* y */
6853 0, 1, -2 /* y + 1 */
6854 };
6855
6856 static int laplace_matrix[9] = {
6857 /* x - 1 x x + 1 */
6858 1, 0, 0, /* y - 1 */
6859 0, 0, 0, /* y */
6860 0, 0, -1 /* y + 1 */
6861 };
6862
6863 /* Value is the intensity of the color whose red/green/blue values
6864 are R, G, and B. */
6865
6866 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
6867
6868
6869 /* On frame F, return an array of XColor structures describing image
6870 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
6871 non-zero means also fill the red/green/blue members of the XColor
6872 structures. Value is a pointer to the array of XColors structures,
6873 allocated with xmalloc; it must be freed by the caller. */
6874
6875 static XColor *
6876 x_to_xcolors (f, img, rgb_p)
6877 struct frame *f;
6878 struct image *img;
6879 int rgb_p;
6880 {
6881 int x, y;
6882 XColor *colors, *p;
6883 XImage *ximg;
6884
6885 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
6886
6887 /* Get the X image IMG->pixmap. */
6888 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
6889 0, 0, img->width, img->height, ~0, ZPixmap);
6890
6891 /* Fill the `pixel' members of the XColor array. I wished there
6892 were an easy and portable way to circumvent XGetPixel. */
6893 p = colors;
6894 for (y = 0; y < img->height; ++y)
6895 {
6896 XColor *row = p;
6897
6898 for (x = 0; x < img->width; ++x, ++p)
6899 p->pixel = XGetPixel (ximg, x, y);
6900
6901 if (rgb_p)
6902 x_query_colors (f, row, img->width);
6903 }
6904
6905 XDestroyImage (ximg);
6906 return colors;
6907 }
6908
6909
6910 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
6911 RGB members are set. F is the frame on which this all happens.
6912 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
6913
6914 static void
6915 x_from_xcolors (f, img, colors)
6916 struct frame *f;
6917 struct image *img;
6918 XColor *colors;
6919 {
6920 int x, y;
6921 XImage *oimg;
6922 Pixmap pixmap;
6923 XColor *p;
6924
6925 init_color_table ();
6926
6927 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
6928 &oimg, &pixmap);
6929 p = colors;
6930 for (y = 0; y < img->height; ++y)
6931 for (x = 0; x < img->width; ++x, ++p)
6932 {
6933 unsigned long pixel;
6934 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
6935 XPutPixel (oimg, x, y, pixel);
6936 }
6937
6938 xfree (colors);
6939 x_clear_image_1 (f, img, 1, 0, 1);
6940
6941 x_put_x_image (f, oimg, pixmap, img->width, img->height);
6942 x_destroy_x_image (oimg);
6943 img->pixmap = pixmap;
6944 img->colors = colors_in_color_table (&img->ncolors);
6945 free_color_table ();
6946 }
6947
6948
6949 /* On frame F, perform edge-detection on image IMG.
6950
6951 MATRIX is a nine-element array specifying the transformation
6952 matrix. See emboss_matrix for an example.
6953
6954 COLOR_ADJUST is a color adjustment added to each pixel of the
6955 outgoing image. */
6956
6957 static void
6958 x_detect_edges (f, img, matrix, color_adjust)
6959 struct frame *f;
6960 struct image *img;
6961 int matrix[9], color_adjust;
6962 {
6963 XColor *colors = x_to_xcolors (f, img, 1);
6964 XColor *new, *p;
6965 int x, y, i, sum;
6966
6967 for (i = sum = 0; i < 9; ++i)
6968 sum += abs (matrix[i]);
6969
6970 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
6971
6972 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
6973
6974 for (y = 0; y < img->height; ++y)
6975 {
6976 p = COLOR (new, 0, y);
6977 p->red = p->green = p->blue = 0xffff/2;
6978 p = COLOR (new, img->width - 1, y);
6979 p->red = p->green = p->blue = 0xffff/2;
6980 }
6981
6982 for (x = 1; x < img->width - 1; ++x)
6983 {
6984 p = COLOR (new, x, 0);
6985 p->red = p->green = p->blue = 0xffff/2;
6986 p = COLOR (new, x, img->height - 1);
6987 p->red = p->green = p->blue = 0xffff/2;
6988 }
6989
6990 for (y = 1; y < img->height - 1; ++y)
6991 {
6992 p = COLOR (new, 1, y);
6993
6994 for (x = 1; x < img->width - 1; ++x, ++p)
6995 {
6996 int r, g, b, y1, x1;
6997
6998 r = g = b = i = 0;
6999 for (y1 = y - 1; y1 < y + 2; ++y1)
7000 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
7001 if (matrix[i])
7002 {
7003 XColor *t = COLOR (colors, x1, y1);
7004 r += matrix[i] * t->red;
7005 g += matrix[i] * t->green;
7006 b += matrix[i] * t->blue;
7007 }
7008
7009 r = (r / sum + color_adjust) & 0xffff;
7010 g = (g / sum + color_adjust) & 0xffff;
7011 b = (b / sum + color_adjust) & 0xffff;
7012 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
7013 }
7014 }
7015
7016 xfree (colors);
7017 x_from_xcolors (f, img, new);
7018
7019 #undef COLOR
7020 }
7021
7022
7023 /* Perform the pre-defined `emboss' edge-detection on image IMG
7024 on frame F. */
7025
7026 static void
7027 x_emboss (f, img)
7028 struct frame *f;
7029 struct image *img;
7030 {
7031 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
7032 }
7033
7034
7035 /* Perform the pre-defined `laplace' edge-detection on image IMG
7036 on frame F. */
7037
7038 static void
7039 x_laplace (f, img)
7040 struct frame *f;
7041 struct image *img;
7042 {
7043 x_detect_edges (f, img, laplace_matrix, 45000);
7044 }
7045
7046
7047 /* Perform edge-detection on image IMG on frame F, with specified
7048 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7049
7050 MATRIX must be either
7051
7052 - a list of at least 9 numbers in row-major form
7053 - a vector of at least 9 numbers
7054
7055 COLOR_ADJUST nil means use a default; otherwise it must be a
7056 number. */
7057
7058 static void
7059 x_edge_detection (f, img, matrix, color_adjust)
7060 struct frame *f;
7061 struct image *img;
7062 Lisp_Object matrix, color_adjust;
7063 {
7064 int i = 0;
7065 int trans[9];
7066
7067 if (CONSP (matrix))
7068 {
7069 for (i = 0;
7070 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
7071 ++i, matrix = XCDR (matrix))
7072 trans[i] = XFLOATINT (XCAR (matrix));
7073 }
7074 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
7075 {
7076 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
7077 trans[i] = XFLOATINT (AREF (matrix, i));
7078 }
7079
7080 if (NILP (color_adjust))
7081 color_adjust = make_number (0xffff / 2);
7082
7083 if (i == 9 && NUMBERP (color_adjust))
7084 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
7085 }
7086
7087
7088 /* Transform image IMG on frame F so that it looks disabled. */
7089
7090 static void
7091 x_disable_image (f, img)
7092 struct frame *f;
7093 struct image *img;
7094 {
7095 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7096
7097 if (dpyinfo->n_planes >= 2)
7098 {
7099 /* Color (or grayscale). Convert to gray, and equalize. Just
7100 drawing such images with a stipple can look very odd, so
7101 we're using this method instead. */
7102 XColor *colors = x_to_xcolors (f, img, 1);
7103 XColor *p, *end;
7104 const int h = 15000;
7105 const int l = 30000;
7106
7107 for (p = colors, end = colors + img->width * img->height;
7108 p < end;
7109 ++p)
7110 {
7111 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
7112 int i2 = (0xffff - h - l) * i / 0xffff + l;
7113 p->red = p->green = p->blue = i2;
7114 }
7115
7116 x_from_xcolors (f, img, colors);
7117 }
7118
7119 /* Draw a cross over the disabled image, if we must or if we
7120 should. */
7121 if (dpyinfo->n_planes < 2 || cross_disabled_images)
7122 {
7123 Display *dpy = FRAME_X_DISPLAY (f);
7124 GC gc;
7125
7126 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
7127 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
7128 XDrawLine (dpy, img->pixmap, gc, 0, 0,
7129 img->width - 1, img->height - 1);
7130 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
7131 img->width - 1, 0);
7132 XFreeGC (dpy, gc);
7133
7134 if (img->mask)
7135 {
7136 gc = XCreateGC (dpy, img->mask, 0, NULL);
7137 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
7138 XDrawLine (dpy, img->mask, gc, 0, 0,
7139 img->width - 1, img->height - 1);
7140 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
7141 img->width - 1, 0);
7142 XFreeGC (dpy, gc);
7143 }
7144 }
7145 }
7146
7147
7148 /* Build a mask for image IMG which is used on frame F. FILE is the
7149 name of an image file, for error messages. HOW determines how to
7150 determine the background color of IMG. If it is a list '(R G B)',
7151 with R, G, and B being integers >= 0, take that as the color of the
7152 background. Otherwise, determine the background color of IMG
7153 heuristically. Value is non-zero if successful. */
7154
7155 static int
7156 x_build_heuristic_mask (f, img, how)
7157 struct frame *f;
7158 struct image *img;
7159 Lisp_Object how;
7160 {
7161 Display *dpy = FRAME_X_DISPLAY (f);
7162 XImage *ximg, *mask_img;
7163 int x, y, rc, use_img_background;
7164 unsigned long bg = 0;
7165
7166 if (img->mask)
7167 {
7168 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
7169 img->mask = None;
7170 img->background_transparent_valid = 0;
7171 }
7172
7173 /* Create an image and pixmap serving as mask. */
7174 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7175 &mask_img, &img->mask);
7176 if (!rc)
7177 return 0;
7178
7179 /* Get the X image of IMG->pixmap. */
7180 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7181 ~0, ZPixmap);
7182
7183 /* Determine the background color of ximg. If HOW is `(R G B)'
7184 take that as color. Otherwise, use the image's background color. */
7185 use_img_background = 1;
7186
7187 if (CONSP (how))
7188 {
7189 int rgb[3], i;
7190
7191 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
7192 {
7193 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
7194 how = XCDR (how);
7195 }
7196
7197 if (i == 3 && NILP (how))
7198 {
7199 char color_name[30];
7200 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
7201 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
7202 use_img_background = 0;
7203 }
7204 }
7205
7206 if (use_img_background)
7207 bg = four_corners_best (ximg, img->width, img->height);
7208
7209 /* Set all bits in mask_img to 1 whose color in ximg is different
7210 from the background color bg. */
7211 for (y = 0; y < img->height; ++y)
7212 for (x = 0; x < img->width; ++x)
7213 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7214
7215 /* Fill in the background_transparent field while we have the mask handy. */
7216 image_background_transparent (img, f, mask_img);
7217
7218 /* Put mask_img into img->mask. */
7219 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7220 x_destroy_x_image (mask_img);
7221 XDestroyImage (ximg);
7222
7223 return 1;
7224 }
7225
7226
7227 \f
7228 /***********************************************************************
7229 PBM (mono, gray, color)
7230 ***********************************************************************/
7231
7232 static int pbm_image_p P_ ((Lisp_Object object));
7233 static int pbm_load P_ ((struct frame *f, struct image *img));
7234 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7235
7236 /* The symbol `pbm' identifying images of this type. */
7237
7238 Lisp_Object Qpbm;
7239
7240 /* Indices of image specification fields in gs_format, below. */
7241
7242 enum pbm_keyword_index
7243 {
7244 PBM_TYPE,
7245 PBM_FILE,
7246 PBM_DATA,
7247 PBM_ASCENT,
7248 PBM_MARGIN,
7249 PBM_RELIEF,
7250 PBM_ALGORITHM,
7251 PBM_HEURISTIC_MASK,
7252 PBM_MASK,
7253 PBM_FOREGROUND,
7254 PBM_BACKGROUND,
7255 PBM_LAST
7256 };
7257
7258 /* Vector of image_keyword structures describing the format
7259 of valid user-defined image specifications. */
7260
7261 static struct image_keyword pbm_format[PBM_LAST] =
7262 {
7263 {":type", IMAGE_SYMBOL_VALUE, 1},
7264 {":file", IMAGE_STRING_VALUE, 0},
7265 {":data", IMAGE_STRING_VALUE, 0},
7266 {":ascent", IMAGE_ASCENT_VALUE, 0},
7267 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7268 {":relief", IMAGE_INTEGER_VALUE, 0},
7269 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7270 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7271 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7272 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
7273 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7274 };
7275
7276 /* Structure describing the image type `pbm'. */
7277
7278 static struct image_type pbm_type =
7279 {
7280 &Qpbm,
7281 pbm_image_p,
7282 pbm_load,
7283 x_clear_image,
7284 NULL
7285 };
7286
7287
7288 /* Return non-zero if OBJECT is a valid PBM image specification. */
7289
7290 static int
7291 pbm_image_p (object)
7292 Lisp_Object object;
7293 {
7294 struct image_keyword fmt[PBM_LAST];
7295
7296 bcopy (pbm_format, fmt, sizeof fmt);
7297
7298 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
7299 return 0;
7300
7301 /* Must specify either :data or :file. */
7302 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7303 }
7304
7305
7306 /* Scan a decimal number from *S and return it. Advance *S while
7307 reading the number. END is the end of the string. Value is -1 at
7308 end of input. */
7309
7310 static int
7311 pbm_scan_number (s, end)
7312 unsigned char **s, *end;
7313 {
7314 int c = 0, val = -1;
7315
7316 while (*s < end)
7317 {
7318 /* Skip white-space. */
7319 while (*s < end && (c = *(*s)++, isspace (c)))
7320 ;
7321
7322 if (c == '#')
7323 {
7324 /* Skip comment to end of line. */
7325 while (*s < end && (c = *(*s)++, c != '\n'))
7326 ;
7327 }
7328 else if (isdigit (c))
7329 {
7330 /* Read decimal number. */
7331 val = c - '0';
7332 while (*s < end && (c = *(*s)++, isdigit (c)))
7333 val = 10 * val + c - '0';
7334 break;
7335 }
7336 else
7337 break;
7338 }
7339
7340 return val;
7341 }
7342
7343
7344 /* Load PBM image IMG for use on frame F. */
7345
7346 static int
7347 pbm_load (f, img)
7348 struct frame *f;
7349 struct image *img;
7350 {
7351 int raw_p, x, y;
7352 int width, height, max_color_idx = 0;
7353 XImage *ximg;
7354 Lisp_Object file, specified_file;
7355 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7356 struct gcpro gcpro1;
7357 unsigned char *contents = NULL;
7358 unsigned char *end, *p;
7359 int size;
7360
7361 specified_file = image_spec_value (img->spec, QCfile, NULL);
7362 file = Qnil;
7363 GCPRO1 (file);
7364
7365 if (STRINGP (specified_file))
7366 {
7367 file = x_find_image_file (specified_file);
7368 if (!STRINGP (file))
7369 {
7370 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7371 UNGCPRO;
7372 return 0;
7373 }
7374
7375 contents = slurp_file (SDATA (file), &size);
7376 if (contents == NULL)
7377 {
7378 image_error ("Error reading `%s'", file, Qnil);
7379 UNGCPRO;
7380 return 0;
7381 }
7382
7383 p = contents;
7384 end = contents + size;
7385 }
7386 else
7387 {
7388 Lisp_Object data;
7389 data = image_spec_value (img->spec, QCdata, NULL);
7390 p = SDATA (data);
7391 end = p + SBYTES (data);
7392 }
7393
7394 /* Check magic number. */
7395 if (end - p < 2 || *p++ != 'P')
7396 {
7397 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7398 error:
7399 xfree (contents);
7400 UNGCPRO;
7401 return 0;
7402 }
7403
7404 switch (*p++)
7405 {
7406 case '1':
7407 raw_p = 0, type = PBM_MONO;
7408 break;
7409
7410 case '2':
7411 raw_p = 0, type = PBM_GRAY;
7412 break;
7413
7414 case '3':
7415 raw_p = 0, type = PBM_COLOR;
7416 break;
7417
7418 case '4':
7419 raw_p = 1, type = PBM_MONO;
7420 break;
7421
7422 case '5':
7423 raw_p = 1, type = PBM_GRAY;
7424 break;
7425
7426 case '6':
7427 raw_p = 1, type = PBM_COLOR;
7428 break;
7429
7430 default:
7431 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7432 goto error;
7433 }
7434
7435 /* Read width, height, maximum color-component. Characters
7436 starting with `#' up to the end of a line are ignored. */
7437 width = pbm_scan_number (&p, end);
7438 height = pbm_scan_number (&p, end);
7439
7440 if (type != PBM_MONO)
7441 {
7442 max_color_idx = pbm_scan_number (&p, end);
7443 if (raw_p && max_color_idx > 255)
7444 max_color_idx = 255;
7445 }
7446
7447 if (width < 0
7448 || height < 0
7449 || (type != PBM_MONO && max_color_idx < 0))
7450 goto error;
7451
7452 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7453 &ximg, &img->pixmap))
7454 goto error;
7455
7456 /* Initialize the color hash table. */
7457 init_color_table ();
7458
7459 if (type == PBM_MONO)
7460 {
7461 int c = 0, g;
7462 struct image_keyword fmt[PBM_LAST];
7463 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
7464 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
7465
7466 /* Parse the image specification. */
7467 bcopy (pbm_format, fmt, sizeof fmt);
7468 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
7469
7470 /* Get foreground and background colors, maybe allocate colors. */
7471 if (fmt[PBM_FOREGROUND].count
7472 && STRINGP (fmt[PBM_FOREGROUND].value))
7473 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
7474 if (fmt[PBM_BACKGROUND].count
7475 && STRINGP (fmt[PBM_BACKGROUND].value))
7476 {
7477 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
7478 img->background = bg;
7479 img->background_valid = 1;
7480 }
7481
7482 for (y = 0; y < height; ++y)
7483 for (x = 0; x < width; ++x)
7484 {
7485 if (raw_p)
7486 {
7487 if ((x & 7) == 0)
7488 c = *p++;
7489 g = c & 0x80;
7490 c <<= 1;
7491 }
7492 else
7493 g = pbm_scan_number (&p, end);
7494
7495 XPutPixel (ximg, x, y, g ? fg : bg);
7496 }
7497 }
7498 else
7499 {
7500 for (y = 0; y < height; ++y)
7501 for (x = 0; x < width; ++x)
7502 {
7503 int r, g, b;
7504
7505 if (type == PBM_GRAY)
7506 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
7507 else if (raw_p)
7508 {
7509 r = *p++;
7510 g = *p++;
7511 b = *p++;
7512 }
7513 else
7514 {
7515 r = pbm_scan_number (&p, end);
7516 g = pbm_scan_number (&p, end);
7517 b = pbm_scan_number (&p, end);
7518 }
7519
7520 if (r < 0 || g < 0 || b < 0)
7521 {
7522 xfree (ximg->data);
7523 ximg->data = NULL;
7524 XDestroyImage (ximg);
7525 image_error ("Invalid pixel value in image `%s'",
7526 img->spec, Qnil);
7527 goto error;
7528 }
7529
7530 /* RGB values are now in the range 0..max_color_idx.
7531 Scale this to the range 0..0xffff supported by X. */
7532 r = (double) r * 65535 / max_color_idx;
7533 g = (double) g * 65535 / max_color_idx;
7534 b = (double) b * 65535 / max_color_idx;
7535 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7536 }
7537 }
7538
7539 /* Store in IMG->colors the colors allocated for the image, and
7540 free the color table. */
7541 img->colors = colors_in_color_table (&img->ncolors);
7542 free_color_table ();
7543
7544 /* Maybe fill in the background field while we have ximg handy. */
7545 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7546 IMAGE_BACKGROUND (img, f, ximg);
7547
7548 /* Put the image into a pixmap. */
7549 x_put_x_image (f, ximg, img->pixmap, width, height);
7550 x_destroy_x_image (ximg);
7551
7552 img->width = width;
7553 img->height = height;
7554
7555 UNGCPRO;
7556 xfree (contents);
7557 return 1;
7558 }
7559
7560
7561 \f
7562 /***********************************************************************
7563 PNG
7564 ***********************************************************************/
7565
7566 #if HAVE_PNG
7567
7568 #if defined HAVE_LIBPNG_PNG_H
7569 # include <libpng/png.h>
7570 #else
7571 # include <png.h>
7572 #endif
7573
7574 /* Function prototypes. */
7575
7576 static int png_image_p P_ ((Lisp_Object object));
7577 static int png_load P_ ((struct frame *f, struct image *img));
7578
7579 /* The symbol `png' identifying images of this type. */
7580
7581 Lisp_Object Qpng;
7582
7583 /* Indices of image specification fields in png_format, below. */
7584
7585 enum png_keyword_index
7586 {
7587 PNG_TYPE,
7588 PNG_DATA,
7589 PNG_FILE,
7590 PNG_ASCENT,
7591 PNG_MARGIN,
7592 PNG_RELIEF,
7593 PNG_ALGORITHM,
7594 PNG_HEURISTIC_MASK,
7595 PNG_MASK,
7596 PNG_BACKGROUND,
7597 PNG_LAST
7598 };
7599
7600 /* Vector of image_keyword structures describing the format
7601 of valid user-defined image specifications. */
7602
7603 static struct image_keyword png_format[PNG_LAST] =
7604 {
7605 {":type", IMAGE_SYMBOL_VALUE, 1},
7606 {":data", IMAGE_STRING_VALUE, 0},
7607 {":file", IMAGE_STRING_VALUE, 0},
7608 {":ascent", IMAGE_ASCENT_VALUE, 0},
7609 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7610 {":relief", IMAGE_INTEGER_VALUE, 0},
7611 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7612 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7613 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7614 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7615 };
7616
7617 /* Structure describing the image type `png'. */
7618
7619 static struct image_type png_type =
7620 {
7621 &Qpng,
7622 png_image_p,
7623 png_load,
7624 x_clear_image,
7625 NULL
7626 };
7627
7628
7629 /* Return non-zero if OBJECT is a valid PNG image specification. */
7630
7631 static int
7632 png_image_p (object)
7633 Lisp_Object object;
7634 {
7635 struct image_keyword fmt[PNG_LAST];
7636 bcopy (png_format, fmt, sizeof fmt);
7637
7638 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
7639 return 0;
7640
7641 /* Must specify either the :data or :file keyword. */
7642 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7643 }
7644
7645
7646 /* Error and warning handlers installed when the PNG library
7647 is initialized. */
7648
7649 static void
7650 my_png_error (png_ptr, msg)
7651 png_struct *png_ptr;
7652 char *msg;
7653 {
7654 xassert (png_ptr != NULL);
7655 image_error ("PNG error: %s", build_string (msg), Qnil);
7656 longjmp (png_ptr->jmpbuf, 1);
7657 }
7658
7659
7660 static void
7661 my_png_warning (png_ptr, msg)
7662 png_struct *png_ptr;
7663 char *msg;
7664 {
7665 xassert (png_ptr != NULL);
7666 image_error ("PNG warning: %s", build_string (msg), Qnil);
7667 }
7668
7669 /* Memory source for PNG decoding. */
7670
7671 struct png_memory_storage
7672 {
7673 unsigned char *bytes; /* The data */
7674 size_t len; /* How big is it? */
7675 int index; /* Where are we? */
7676 };
7677
7678
7679 /* Function set as reader function when reading PNG image from memory.
7680 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7681 bytes from the input to DATA. */
7682
7683 static void
7684 png_read_from_memory (png_ptr, data, length)
7685 png_structp png_ptr;
7686 png_bytep data;
7687 png_size_t length;
7688 {
7689 struct png_memory_storage *tbr
7690 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
7691
7692 if (length > tbr->len - tbr->index)
7693 png_error (png_ptr, "Read error");
7694
7695 bcopy (tbr->bytes + tbr->index, data, length);
7696 tbr->index = tbr->index + length;
7697 }
7698
7699 /* Load PNG image IMG for use on frame F. Value is non-zero if
7700 successful. */
7701
7702 static int
7703 png_load (f, img)
7704 struct frame *f;
7705 struct image *img;
7706 {
7707 Lisp_Object file, specified_file;
7708 Lisp_Object specified_data;
7709 int x, y, i;
7710 XImage *ximg, *mask_img = NULL;
7711 struct gcpro gcpro1;
7712 png_struct *png_ptr = NULL;
7713 png_info *info_ptr = NULL, *end_info = NULL;
7714 FILE *volatile fp = NULL;
7715 png_byte sig[8];
7716 png_byte * volatile pixels = NULL;
7717 png_byte ** volatile rows = NULL;
7718 png_uint_32 width, height;
7719 int bit_depth, color_type, interlace_type;
7720 png_byte channels;
7721 png_uint_32 row_bytes;
7722 int transparent_p;
7723 double screen_gamma;
7724 struct png_memory_storage tbr; /* Data to be read */
7725
7726 /* Find out what file to load. */
7727 specified_file = image_spec_value (img->spec, QCfile, NULL);
7728 specified_data = image_spec_value (img->spec, QCdata, NULL);
7729 file = Qnil;
7730 GCPRO1 (file);
7731
7732 if (NILP (specified_data))
7733 {
7734 file = x_find_image_file (specified_file);
7735 if (!STRINGP (file))
7736 {
7737 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7738 UNGCPRO;
7739 return 0;
7740 }
7741
7742 /* Open the image file. */
7743 fp = fopen (SDATA (file), "rb");
7744 if (!fp)
7745 {
7746 image_error ("Cannot open image file `%s'", file, Qnil);
7747 UNGCPRO;
7748 fclose (fp);
7749 return 0;
7750 }
7751
7752 /* Check PNG signature. */
7753 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7754 || !png_check_sig (sig, sizeof sig))
7755 {
7756 image_error ("Not a PNG file: `%s'", file, Qnil);
7757 UNGCPRO;
7758 fclose (fp);
7759 return 0;
7760 }
7761 }
7762 else
7763 {
7764 /* Read from memory. */
7765 tbr.bytes = SDATA (specified_data);
7766 tbr.len = SBYTES (specified_data);
7767 tbr.index = 0;
7768
7769 /* Check PNG signature. */
7770 if (tbr.len < sizeof sig
7771 || !png_check_sig (tbr.bytes, sizeof sig))
7772 {
7773 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
7774 UNGCPRO;
7775 return 0;
7776 }
7777
7778 /* Need to skip past the signature. */
7779 tbr.bytes += sizeof (sig);
7780 }
7781
7782 /* Initialize read and info structs for PNG lib. */
7783 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7784 my_png_error, my_png_warning);
7785 if (!png_ptr)
7786 {
7787 if (fp) fclose (fp);
7788 UNGCPRO;
7789 return 0;
7790 }
7791
7792 info_ptr = png_create_info_struct (png_ptr);
7793 if (!info_ptr)
7794 {
7795 png_destroy_read_struct (&png_ptr, NULL, NULL);
7796 if (fp) fclose (fp);
7797 UNGCPRO;
7798 return 0;
7799 }
7800
7801 end_info = png_create_info_struct (png_ptr);
7802 if (!end_info)
7803 {
7804 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7805 if (fp) fclose (fp);
7806 UNGCPRO;
7807 return 0;
7808 }
7809
7810 /* Set error jump-back. We come back here when the PNG library
7811 detects an error. */
7812 if (setjmp (png_ptr->jmpbuf))
7813 {
7814 error:
7815 if (png_ptr)
7816 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7817 xfree (pixels);
7818 xfree (rows);
7819 if (fp) fclose (fp);
7820 UNGCPRO;
7821 return 0;
7822 }
7823
7824 /* Read image info. */
7825 if (!NILP (specified_data))
7826 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
7827 else
7828 png_init_io (png_ptr, fp);
7829
7830 png_set_sig_bytes (png_ptr, sizeof sig);
7831 png_read_info (png_ptr, info_ptr);
7832 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
7833 &interlace_type, NULL, NULL);
7834
7835 /* If image contains simply transparency data, we prefer to
7836 construct a clipping mask. */
7837 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
7838 transparent_p = 1;
7839 else
7840 transparent_p = 0;
7841
7842 /* This function is easier to write if we only have to handle
7843 one data format: RGB or RGBA with 8 bits per channel. Let's
7844 transform other formats into that format. */
7845
7846 /* Strip more than 8 bits per channel. */
7847 if (bit_depth == 16)
7848 png_set_strip_16 (png_ptr);
7849
7850 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7851 if available. */
7852 png_set_expand (png_ptr);
7853
7854 /* Convert grayscale images to RGB. */
7855 if (color_type == PNG_COLOR_TYPE_GRAY
7856 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7857 png_set_gray_to_rgb (png_ptr);
7858
7859 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
7860
7861 #if 0 /* Avoid double gamma correction for PNG images. */
7862 { /* Tell the PNG lib to handle gamma correction for us. */
7863 int intent;
7864 double image_gamma;
7865 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7866 if (png_get_sRGB (png_ptr, info_ptr, &intent))
7867 /* The libpng documentation says this is right in this case. */
7868 png_set_gamma (png_ptr, screen_gamma, 0.45455);
7869 else
7870 #endif
7871 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
7872 /* Image contains gamma information. */
7873 png_set_gamma (png_ptr, screen_gamma, image_gamma);
7874 else
7875 /* Use the standard default for the image gamma. */
7876 png_set_gamma (png_ptr, screen_gamma, 0.45455);
7877 }
7878 #endif /* if 0 */
7879
7880 /* Handle alpha channel by combining the image with a background
7881 color. Do this only if a real alpha channel is supplied. For
7882 simple transparency, we prefer a clipping mask. */
7883 if (!transparent_p)
7884 {
7885 png_color_16 *image_bg;
7886 Lisp_Object specified_bg
7887 = image_spec_value (img->spec, QCbackground, NULL);
7888
7889 if (STRINGP (specified_bg))
7890 /* The user specified `:background', use that. */
7891 {
7892 XColor color;
7893 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
7894 {
7895 png_color_16 user_bg;
7896
7897 bzero (&user_bg, sizeof user_bg);
7898 user_bg.red = color.red;
7899 user_bg.green = color.green;
7900 user_bg.blue = color.blue;
7901
7902 png_set_background (png_ptr, &user_bg,
7903 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7904 }
7905 }
7906 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
7907 /* Image contains a background color with which to
7908 combine the image. */
7909 png_set_background (png_ptr, image_bg,
7910 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
7911 else
7912 {
7913 /* Image does not contain a background color with which
7914 to combine the image data via an alpha channel. Use
7915 the frame's background instead. */
7916 XColor color;
7917 Colormap cmap;
7918 png_color_16 frame_background;
7919
7920 cmap = FRAME_X_COLORMAP (f);
7921 color.pixel = FRAME_BACKGROUND_PIXEL (f);
7922 x_query_color (f, &color);
7923
7924 bzero (&frame_background, sizeof frame_background);
7925 frame_background.red = color.red;
7926 frame_background.green = color.green;
7927 frame_background.blue = color.blue;
7928
7929 png_set_background (png_ptr, &frame_background,
7930 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7931 }
7932 }
7933
7934 /* Update info structure. */
7935 png_read_update_info (png_ptr, info_ptr);
7936
7937 /* Get number of channels. Valid values are 1 for grayscale images
7938 and images with a palette, 2 for grayscale images with transparency
7939 information (alpha channel), 3 for RGB images, and 4 for RGB
7940 images with alpha channel, i.e. RGBA. If conversions above were
7941 sufficient we should only have 3 or 4 channels here. */
7942 channels = png_get_channels (png_ptr, info_ptr);
7943 xassert (channels == 3 || channels == 4);
7944
7945 /* Number of bytes needed for one row of the image. */
7946 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
7947
7948 /* Allocate memory for the image. */
7949 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
7950 rows = (png_byte **) xmalloc (height * sizeof *rows);
7951 for (i = 0; i < height; ++i)
7952 rows[i] = pixels + i * row_bytes;
7953
7954 /* Read the entire image. */
7955 png_read_image (png_ptr, rows);
7956 png_read_end (png_ptr, info_ptr);
7957 if (fp)
7958 {
7959 fclose (fp);
7960 fp = NULL;
7961 }
7962
7963 /* Create the X image and pixmap. */
7964 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7965 &img->pixmap))
7966 goto error;
7967
7968 /* Create an image and pixmap serving as mask if the PNG image
7969 contains an alpha channel. */
7970 if (channels == 4
7971 && !transparent_p
7972 && !x_create_x_image_and_pixmap (f, width, height, 1,
7973 &mask_img, &img->mask))
7974 {
7975 x_destroy_x_image (ximg);
7976 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
7977 img->pixmap = None;
7978 goto error;
7979 }
7980
7981 /* Fill the X image and mask from PNG data. */
7982 init_color_table ();
7983
7984 for (y = 0; y < height; ++y)
7985 {
7986 png_byte *p = rows[y];
7987
7988 for (x = 0; x < width; ++x)
7989 {
7990 unsigned r, g, b;
7991
7992 r = *p++ << 8;
7993 g = *p++ << 8;
7994 b = *p++ << 8;
7995 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7996
7997 /* An alpha channel, aka mask channel, associates variable
7998 transparency with an image. Where other image formats
7999 support binary transparency---fully transparent or fully
8000 opaque---PNG allows up to 254 levels of partial transparency.
8001 The PNG library implements partial transparency by combining
8002 the image with a specified background color.
8003
8004 I'm not sure how to handle this here nicely: because the
8005 background on which the image is displayed may change, for
8006 real alpha channel support, it would be necessary to create
8007 a new image for each possible background.
8008
8009 What I'm doing now is that a mask is created if we have
8010 boolean transparency information. Otherwise I'm using
8011 the frame's background color to combine the image with. */
8012
8013 if (channels == 4)
8014 {
8015 if (mask_img)
8016 XPutPixel (mask_img, x, y, *p > 0);
8017 ++p;
8018 }
8019 }
8020 }
8021
8022 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8023 /* Set IMG's background color from the PNG image, unless the user
8024 overrode it. */
8025 {
8026 png_color_16 *bg;
8027 if (png_get_bKGD (png_ptr, info_ptr, &bg))
8028 {
8029 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
8030 img->background_valid = 1;
8031 }
8032 }
8033
8034 /* Remember colors allocated for this image. */
8035 img->colors = colors_in_color_table (&img->ncolors);
8036 free_color_table ();
8037
8038 /* Clean up. */
8039 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8040 xfree (rows);
8041 xfree (pixels);
8042
8043 img->width = width;
8044 img->height = height;
8045
8046 /* Maybe fill in the background field while we have ximg handy. */
8047 IMAGE_BACKGROUND (img, f, ximg);
8048
8049 /* Put the image into the pixmap, then free the X image and its buffer. */
8050 x_put_x_image (f, ximg, img->pixmap, width, height);
8051 x_destroy_x_image (ximg);
8052
8053 /* Same for the mask. */
8054 if (mask_img)
8055 {
8056 /* Fill in the background_transparent field while we have the mask
8057 handy. */
8058 image_background_transparent (img, f, mask_img);
8059
8060 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8061 x_destroy_x_image (mask_img);
8062 }
8063
8064 UNGCPRO;
8065 return 1;
8066 }
8067
8068 #endif /* HAVE_PNG != 0 */
8069
8070
8071 \f
8072 /***********************************************************************
8073 JPEG
8074 ***********************************************************************/
8075
8076 #if HAVE_JPEG
8077
8078 /* Work around a warning about HAVE_STDLIB_H being redefined in
8079 jconfig.h. */
8080 #ifdef HAVE_STDLIB_H
8081 #define HAVE_STDLIB_H_1
8082 #undef HAVE_STDLIB_H
8083 #endif /* HAVE_STLIB_H */
8084
8085 #include <jpeglib.h>
8086 #include <jerror.h>
8087 #include <setjmp.h>
8088
8089 #ifdef HAVE_STLIB_H_1
8090 #define HAVE_STDLIB_H 1
8091 #endif
8092
8093 static int jpeg_image_p P_ ((Lisp_Object object));
8094 static int jpeg_load P_ ((struct frame *f, struct image *img));
8095
8096 /* The symbol `jpeg' identifying images of this type. */
8097
8098 Lisp_Object Qjpeg;
8099
8100 /* Indices of image specification fields in gs_format, below. */
8101
8102 enum jpeg_keyword_index
8103 {
8104 JPEG_TYPE,
8105 JPEG_DATA,
8106 JPEG_FILE,
8107 JPEG_ASCENT,
8108 JPEG_MARGIN,
8109 JPEG_RELIEF,
8110 JPEG_ALGORITHM,
8111 JPEG_HEURISTIC_MASK,
8112 JPEG_MASK,
8113 JPEG_BACKGROUND,
8114 JPEG_LAST
8115 };
8116
8117 /* Vector of image_keyword structures describing the format
8118 of valid user-defined image specifications. */
8119
8120 static struct image_keyword jpeg_format[JPEG_LAST] =
8121 {
8122 {":type", IMAGE_SYMBOL_VALUE, 1},
8123 {":data", IMAGE_STRING_VALUE, 0},
8124 {":file", IMAGE_STRING_VALUE, 0},
8125 {":ascent", IMAGE_ASCENT_VALUE, 0},
8126 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8127 {":relief", IMAGE_INTEGER_VALUE, 0},
8128 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8129 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8130 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8131 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8132 };
8133
8134 /* Structure describing the image type `jpeg'. */
8135
8136 static struct image_type jpeg_type =
8137 {
8138 &Qjpeg,
8139 jpeg_image_p,
8140 jpeg_load,
8141 x_clear_image,
8142 NULL
8143 };
8144
8145
8146 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8147
8148 static int
8149 jpeg_image_p (object)
8150 Lisp_Object object;
8151 {
8152 struct image_keyword fmt[JPEG_LAST];
8153
8154 bcopy (jpeg_format, fmt, sizeof fmt);
8155
8156 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8157 return 0;
8158
8159 /* Must specify either the :data or :file keyword. */
8160 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8161 }
8162
8163
8164 struct my_jpeg_error_mgr
8165 {
8166 struct jpeg_error_mgr pub;
8167 jmp_buf setjmp_buffer;
8168 };
8169
8170
8171 static void
8172 my_error_exit (cinfo)
8173 j_common_ptr cinfo;
8174 {
8175 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8176 longjmp (mgr->setjmp_buffer, 1);
8177 }
8178
8179
8180 /* Init source method for JPEG data source manager. Called by
8181 jpeg_read_header() before any data is actually read. See
8182 libjpeg.doc from the JPEG lib distribution. */
8183
8184 static void
8185 our_init_source (cinfo)
8186 j_decompress_ptr cinfo;
8187 {
8188 }
8189
8190
8191 /* Fill input buffer method for JPEG data source manager. Called
8192 whenever more data is needed. We read the whole image in one step,
8193 so this only adds a fake end of input marker at the end. */
8194
8195 static boolean
8196 our_fill_input_buffer (cinfo)
8197 j_decompress_ptr cinfo;
8198 {
8199 /* Insert a fake EOI marker. */
8200 struct jpeg_source_mgr *src = cinfo->src;
8201 static JOCTET buffer[2];
8202
8203 buffer[0] = (JOCTET) 0xFF;
8204 buffer[1] = (JOCTET) JPEG_EOI;
8205
8206 src->next_input_byte = buffer;
8207 src->bytes_in_buffer = 2;
8208 return TRUE;
8209 }
8210
8211
8212 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8213 is the JPEG data source manager. */
8214
8215 static void
8216 our_skip_input_data (cinfo, num_bytes)
8217 j_decompress_ptr cinfo;
8218 long num_bytes;
8219 {
8220 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
8221
8222 if (src)
8223 {
8224 if (num_bytes > src->bytes_in_buffer)
8225 ERREXIT (cinfo, JERR_INPUT_EOF);
8226
8227 src->bytes_in_buffer -= num_bytes;
8228 src->next_input_byte += num_bytes;
8229 }
8230 }
8231
8232
8233 /* Method to terminate data source. Called by
8234 jpeg_finish_decompress() after all data has been processed. */
8235
8236 static void
8237 our_term_source (cinfo)
8238 j_decompress_ptr cinfo;
8239 {
8240 }
8241
8242
8243 /* Set up the JPEG lib for reading an image from DATA which contains
8244 LEN bytes. CINFO is the decompression info structure created for
8245 reading the image. */
8246
8247 static void
8248 jpeg_memory_src (cinfo, data, len)
8249 j_decompress_ptr cinfo;
8250 JOCTET *data;
8251 unsigned int len;
8252 {
8253 struct jpeg_source_mgr *src;
8254
8255 if (cinfo->src == NULL)
8256 {
8257 /* First time for this JPEG object? */
8258 cinfo->src = (struct jpeg_source_mgr *)
8259 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
8260 sizeof (struct jpeg_source_mgr));
8261 src = (struct jpeg_source_mgr *) cinfo->src;
8262 src->next_input_byte = data;
8263 }
8264
8265 src = (struct jpeg_source_mgr *) cinfo->src;
8266 src->init_source = our_init_source;
8267 src->fill_input_buffer = our_fill_input_buffer;
8268 src->skip_input_data = our_skip_input_data;
8269 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
8270 src->term_source = our_term_source;
8271 src->bytes_in_buffer = len;
8272 src->next_input_byte = data;
8273 }
8274
8275
8276 /* Load image IMG for use on frame F. Patterned after example.c
8277 from the JPEG lib. */
8278
8279 static int
8280 jpeg_load (f, img)
8281 struct frame *f;
8282 struct image *img;
8283 {
8284 struct jpeg_decompress_struct cinfo;
8285 struct my_jpeg_error_mgr mgr;
8286 Lisp_Object file, specified_file;
8287 Lisp_Object specified_data;
8288 FILE * volatile fp = NULL;
8289 JSAMPARRAY buffer;
8290 int row_stride, x, y;
8291 XImage *ximg = NULL;
8292 int rc;
8293 unsigned long *colors;
8294 int width, height;
8295 struct gcpro gcpro1;
8296
8297 /* Open the JPEG file. */
8298 specified_file = image_spec_value (img->spec, QCfile, NULL);
8299 specified_data = image_spec_value (img->spec, QCdata, NULL);
8300 file = Qnil;
8301 GCPRO1 (file);
8302
8303 if (NILP (specified_data))
8304 {
8305 file = x_find_image_file (specified_file);
8306 if (!STRINGP (file))
8307 {
8308 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8309 UNGCPRO;
8310 return 0;
8311 }
8312
8313 fp = fopen (SDATA (file), "r");
8314 if (fp == NULL)
8315 {
8316 image_error ("Cannot open `%s'", file, Qnil);
8317 UNGCPRO;
8318 return 0;
8319 }
8320 }
8321
8322 /* Customize libjpeg's error handling to call my_error_exit when an
8323 error is detected. This function will perform a longjmp. */
8324 cinfo.err = jpeg_std_error (&mgr.pub);
8325 mgr.pub.error_exit = my_error_exit;
8326
8327 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8328 {
8329 if (rc == 1)
8330 {
8331 /* Called from my_error_exit. Display a JPEG error. */
8332 char buffer[JMSG_LENGTH_MAX];
8333 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8334 image_error ("Error reading JPEG image `%s': %s", img->spec,
8335 build_string (buffer));
8336 }
8337
8338 /* Close the input file and destroy the JPEG object. */
8339 if (fp)
8340 fclose ((FILE *) fp);
8341 jpeg_destroy_decompress (&cinfo);
8342
8343 /* If we already have an XImage, free that. */
8344 x_destroy_x_image (ximg);
8345
8346 /* Free pixmap and colors. */
8347 x_clear_image (f, img);
8348
8349 UNGCPRO;
8350 return 0;
8351 }
8352
8353 /* Create the JPEG decompression object. Let it read from fp.
8354 Read the JPEG image header. */
8355 jpeg_create_decompress (&cinfo);
8356
8357 if (NILP (specified_data))
8358 jpeg_stdio_src (&cinfo, (FILE *) fp);
8359 else
8360 jpeg_memory_src (&cinfo, SDATA (specified_data),
8361 SBYTES (specified_data));
8362
8363 jpeg_read_header (&cinfo, TRUE);
8364
8365 /* Customize decompression so that color quantization will be used.
8366 Start decompression. */
8367 cinfo.quantize_colors = TRUE;
8368 jpeg_start_decompress (&cinfo);
8369 width = img->width = cinfo.output_width;
8370 height = img->height = cinfo.output_height;
8371
8372 /* Create X image and pixmap. */
8373 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8374 longjmp (mgr.setjmp_buffer, 2);
8375
8376 /* Allocate colors. When color quantization is used,
8377 cinfo.actual_number_of_colors has been set with the number of
8378 colors generated, and cinfo.colormap is a two-dimensional array
8379 of color indices in the range 0..cinfo.actual_number_of_colors.
8380 No more than 255 colors will be generated. */
8381 {
8382 int i, ir, ig, ib;
8383
8384 if (cinfo.out_color_components > 2)
8385 ir = 0, ig = 1, ib = 2;
8386 else if (cinfo.out_color_components > 1)
8387 ir = 0, ig = 1, ib = 0;
8388 else
8389 ir = 0, ig = 0, ib = 0;
8390
8391 /* Use the color table mechanism because it handles colors that
8392 cannot be allocated nicely. Such colors will be replaced with
8393 a default color, and we don't have to care about which colors
8394 can be freed safely, and which can't. */
8395 init_color_table ();
8396 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8397 * sizeof *colors);
8398
8399 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8400 {
8401 /* Multiply RGB values with 255 because X expects RGB values
8402 in the range 0..0xffff. */
8403 int r = cinfo.colormap[ir][i] << 8;
8404 int g = cinfo.colormap[ig][i] << 8;
8405 int b = cinfo.colormap[ib][i] << 8;
8406 colors[i] = lookup_rgb_color (f, r, g, b);
8407 }
8408
8409 /* Remember those colors actually allocated. */
8410 img->colors = colors_in_color_table (&img->ncolors);
8411 free_color_table ();
8412 }
8413
8414 /* Read pixels. */
8415 row_stride = width * cinfo.output_components;
8416 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
8417 row_stride, 1);
8418 for (y = 0; y < height; ++y)
8419 {
8420 jpeg_read_scanlines (&cinfo, buffer, 1);
8421 for (x = 0; x < cinfo.output_width; ++x)
8422 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
8423 }
8424
8425 /* Clean up. */
8426 jpeg_finish_decompress (&cinfo);
8427 jpeg_destroy_decompress (&cinfo);
8428 if (fp)
8429 fclose ((FILE *) fp);
8430
8431 /* Maybe fill in the background field while we have ximg handy. */
8432 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8433 IMAGE_BACKGROUND (img, f, ximg);
8434
8435 /* Put the image into the pixmap. */
8436 x_put_x_image (f, ximg, img->pixmap, width, height);
8437 x_destroy_x_image (ximg);
8438 UNGCPRO;
8439 return 1;
8440 }
8441
8442 #endif /* HAVE_JPEG */
8443
8444
8445 \f
8446 /***********************************************************************
8447 TIFF
8448 ***********************************************************************/
8449
8450 #if HAVE_TIFF
8451
8452 #include <tiffio.h>
8453
8454 static int tiff_image_p P_ ((Lisp_Object object));
8455 static int tiff_load P_ ((struct frame *f, struct image *img));
8456
8457 /* The symbol `tiff' identifying images of this type. */
8458
8459 Lisp_Object Qtiff;
8460
8461 /* Indices of image specification fields in tiff_format, below. */
8462
8463 enum tiff_keyword_index
8464 {
8465 TIFF_TYPE,
8466 TIFF_DATA,
8467 TIFF_FILE,
8468 TIFF_ASCENT,
8469 TIFF_MARGIN,
8470 TIFF_RELIEF,
8471 TIFF_ALGORITHM,
8472 TIFF_HEURISTIC_MASK,
8473 TIFF_MASK,
8474 TIFF_BACKGROUND,
8475 TIFF_LAST
8476 };
8477
8478 /* Vector of image_keyword structures describing the format
8479 of valid user-defined image specifications. */
8480
8481 static struct image_keyword tiff_format[TIFF_LAST] =
8482 {
8483 {":type", IMAGE_SYMBOL_VALUE, 1},
8484 {":data", IMAGE_STRING_VALUE, 0},
8485 {":file", IMAGE_STRING_VALUE, 0},
8486 {":ascent", IMAGE_ASCENT_VALUE, 0},
8487 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8488 {":relief", IMAGE_INTEGER_VALUE, 0},
8489 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8490 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8491 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8492 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8493 };
8494
8495 /* Structure describing the image type `tiff'. */
8496
8497 static struct image_type tiff_type =
8498 {
8499 &Qtiff,
8500 tiff_image_p,
8501 tiff_load,
8502 x_clear_image,
8503 NULL
8504 };
8505
8506
8507 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8508
8509 static int
8510 tiff_image_p (object)
8511 Lisp_Object object;
8512 {
8513 struct image_keyword fmt[TIFF_LAST];
8514 bcopy (tiff_format, fmt, sizeof fmt);
8515
8516 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
8517 return 0;
8518
8519 /* Must specify either the :data or :file keyword. */
8520 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8521 }
8522
8523
8524 /* Reading from a memory buffer for TIFF images Based on the PNG
8525 memory source, but we have to provide a lot of extra functions.
8526 Blah.
8527
8528 We really only need to implement read and seek, but I am not
8529 convinced that the TIFF library is smart enough not to destroy
8530 itself if we only hand it the function pointers we need to
8531 override. */
8532
8533 typedef struct
8534 {
8535 unsigned char *bytes;
8536 size_t len;
8537 int index;
8538 }
8539 tiff_memory_source;
8540
8541
8542 static size_t
8543 tiff_read_from_memory (data, buf, size)
8544 thandle_t data;
8545 tdata_t buf;
8546 tsize_t size;
8547 {
8548 tiff_memory_source *src = (tiff_memory_source *) data;
8549
8550 if (size > src->len - src->index)
8551 return (size_t) -1;
8552 bcopy (src->bytes + src->index, buf, size);
8553 src->index += size;
8554 return size;
8555 }
8556
8557
8558 static size_t
8559 tiff_write_from_memory (data, buf, size)
8560 thandle_t data;
8561 tdata_t buf;
8562 tsize_t size;
8563 {
8564 return (size_t) -1;
8565 }
8566
8567
8568 static toff_t
8569 tiff_seek_in_memory (data, off, whence)
8570 thandle_t data;
8571 toff_t off;
8572 int whence;
8573 {
8574 tiff_memory_source *src = (tiff_memory_source *) data;
8575 int idx;
8576
8577 switch (whence)
8578 {
8579 case SEEK_SET: /* Go from beginning of source. */
8580 idx = off;
8581 break;
8582
8583 case SEEK_END: /* Go from end of source. */
8584 idx = src->len + off;
8585 break;
8586
8587 case SEEK_CUR: /* Go from current position. */
8588 idx = src->index + off;
8589 break;
8590
8591 default: /* Invalid `whence'. */
8592 return -1;
8593 }
8594
8595 if (idx > src->len || idx < 0)
8596 return -1;
8597
8598 src->index = idx;
8599 return src->index;
8600 }
8601
8602
8603 static int
8604 tiff_close_memory (data)
8605 thandle_t data;
8606 {
8607 /* NOOP */
8608 return 0;
8609 }
8610
8611
8612 static int
8613 tiff_mmap_memory (data, pbase, psize)
8614 thandle_t data;
8615 tdata_t *pbase;
8616 toff_t *psize;
8617 {
8618 /* It is already _IN_ memory. */
8619 return 0;
8620 }
8621
8622
8623 static void
8624 tiff_unmap_memory (data, base, size)
8625 thandle_t data;
8626 tdata_t base;
8627 toff_t size;
8628 {
8629 /* We don't need to do this. */
8630 }
8631
8632
8633 static toff_t
8634 tiff_size_of_memory (data)
8635 thandle_t data;
8636 {
8637 return ((tiff_memory_source *) data)->len;
8638 }
8639
8640
8641 static void
8642 tiff_error_handler (title, format, ap)
8643 const char *title, *format;
8644 va_list ap;
8645 {
8646 char buf[512];
8647 int len;
8648
8649 len = sprintf (buf, "TIFF error: %s ", title);
8650 vsprintf (buf + len, format, ap);
8651 add_to_log (buf, Qnil, Qnil);
8652 }
8653
8654
8655 static void
8656 tiff_warning_handler (title, format, ap)
8657 const char *title, *format;
8658 va_list ap;
8659 {
8660 char buf[512];
8661 int len;
8662
8663 len = sprintf (buf, "TIFF warning: %s ", title);
8664 vsprintf (buf + len, format, ap);
8665 add_to_log (buf, Qnil, Qnil);
8666 }
8667
8668
8669 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8670 successful. */
8671
8672 static int
8673 tiff_load (f, img)
8674 struct frame *f;
8675 struct image *img;
8676 {
8677 Lisp_Object file, specified_file;
8678 Lisp_Object specified_data;
8679 TIFF *tiff;
8680 int width, height, x, y;
8681 uint32 *buf;
8682 int rc;
8683 XImage *ximg;
8684 struct gcpro gcpro1;
8685 tiff_memory_source memsrc;
8686
8687 specified_file = image_spec_value (img->spec, QCfile, NULL);
8688 specified_data = image_spec_value (img->spec, QCdata, NULL);
8689 file = Qnil;
8690 GCPRO1 (file);
8691
8692 TIFFSetErrorHandler (tiff_error_handler);
8693 TIFFSetWarningHandler (tiff_warning_handler);
8694
8695 if (NILP (specified_data))
8696 {
8697 /* Read from a file */
8698 file = x_find_image_file (specified_file);
8699 if (!STRINGP (file))
8700 {
8701 image_error ("Cannot find image file `%s'", file, Qnil);
8702 UNGCPRO;
8703 return 0;
8704 }
8705
8706 /* Try to open the image file. */
8707 tiff = TIFFOpen (SDATA (file), "r");
8708 if (tiff == NULL)
8709 {
8710 image_error ("Cannot open `%s'", file, Qnil);
8711 UNGCPRO;
8712 return 0;
8713 }
8714 }
8715 else
8716 {
8717 /* Memory source! */
8718 memsrc.bytes = SDATA (specified_data);
8719 memsrc.len = SBYTES (specified_data);
8720 memsrc.index = 0;
8721
8722 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8723 (TIFFReadWriteProc) tiff_read_from_memory,
8724 (TIFFReadWriteProc) tiff_write_from_memory,
8725 tiff_seek_in_memory,
8726 tiff_close_memory,
8727 tiff_size_of_memory,
8728 tiff_mmap_memory,
8729 tiff_unmap_memory);
8730
8731 if (!tiff)
8732 {
8733 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
8734 UNGCPRO;
8735 return 0;
8736 }
8737 }
8738
8739 /* Get width and height of the image, and allocate a raster buffer
8740 of width x height 32-bit values. */
8741 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8742 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8743 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8744
8745 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8746 TIFFClose (tiff);
8747 if (!rc)
8748 {
8749 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8750 xfree (buf);
8751 UNGCPRO;
8752 return 0;
8753 }
8754
8755 /* Create the X image and pixmap. */
8756 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8757 {
8758 xfree (buf);
8759 UNGCPRO;
8760 return 0;
8761 }
8762
8763 /* Initialize the color table. */
8764 init_color_table ();
8765
8766 /* Process the pixel raster. Origin is in the lower-left corner. */
8767 for (y = 0; y < height; ++y)
8768 {
8769 uint32 *row = buf + y * width;
8770
8771 for (x = 0; x < width; ++x)
8772 {
8773 uint32 abgr = row[x];
8774 int r = TIFFGetR (abgr) << 8;
8775 int g = TIFFGetG (abgr) << 8;
8776 int b = TIFFGetB (abgr) << 8;
8777 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8778 }
8779 }
8780
8781 /* Remember the colors allocated for the image. Free the color table. */
8782 img->colors = colors_in_color_table (&img->ncolors);
8783 free_color_table ();
8784
8785 img->width = width;
8786 img->height = height;
8787
8788 /* Maybe fill in the background field while we have ximg handy. */
8789 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8790 IMAGE_BACKGROUND (img, f, ximg);
8791
8792 /* Put the image into the pixmap, then free the X image and its buffer. */
8793 x_put_x_image (f, ximg, img->pixmap, width, height);
8794 x_destroy_x_image (ximg);
8795 xfree (buf);
8796
8797 UNGCPRO;
8798 return 1;
8799 }
8800
8801 #endif /* HAVE_TIFF != 0 */
8802
8803
8804 \f
8805 /***********************************************************************
8806 GIF
8807 ***********************************************************************/
8808
8809 #if HAVE_GIF
8810
8811 #include <gif_lib.h>
8812
8813 static int gif_image_p P_ ((Lisp_Object object));
8814 static int gif_load P_ ((struct frame *f, struct image *img));
8815
8816 /* The symbol `gif' identifying images of this type. */
8817
8818 Lisp_Object Qgif;
8819
8820 /* Indices of image specification fields in gif_format, below. */
8821
8822 enum gif_keyword_index
8823 {
8824 GIF_TYPE,
8825 GIF_DATA,
8826 GIF_FILE,
8827 GIF_ASCENT,
8828 GIF_MARGIN,
8829 GIF_RELIEF,
8830 GIF_ALGORITHM,
8831 GIF_HEURISTIC_MASK,
8832 GIF_MASK,
8833 GIF_IMAGE,
8834 GIF_BACKGROUND,
8835 GIF_LAST
8836 };
8837
8838 /* Vector of image_keyword structures describing the format
8839 of valid user-defined image specifications. */
8840
8841 static struct image_keyword gif_format[GIF_LAST] =
8842 {
8843 {":type", IMAGE_SYMBOL_VALUE, 1},
8844 {":data", IMAGE_STRING_VALUE, 0},
8845 {":file", IMAGE_STRING_VALUE, 0},
8846 {":ascent", IMAGE_ASCENT_VALUE, 0},
8847 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8848 {":relief", IMAGE_INTEGER_VALUE, 0},
8849 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8850 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8851 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8852 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8853 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8854 };
8855
8856 /* Structure describing the image type `gif'. */
8857
8858 static struct image_type gif_type =
8859 {
8860 &Qgif,
8861 gif_image_p,
8862 gif_load,
8863 x_clear_image,
8864 NULL
8865 };
8866
8867
8868 /* Return non-zero if OBJECT is a valid GIF image specification. */
8869
8870 static int
8871 gif_image_p (object)
8872 Lisp_Object object;
8873 {
8874 struct image_keyword fmt[GIF_LAST];
8875 bcopy (gif_format, fmt, sizeof fmt);
8876
8877 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8878 return 0;
8879
8880 /* Must specify either the :data or :file keyword. */
8881 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8882 }
8883
8884
8885 /* Reading a GIF image from memory
8886 Based on the PNG memory stuff to a certain extent. */
8887
8888 typedef struct
8889 {
8890 unsigned char *bytes;
8891 size_t len;
8892 int index;
8893 }
8894 gif_memory_source;
8895
8896
8897 /* Make the current memory source available to gif_read_from_memory.
8898 It's done this way because not all versions of libungif support
8899 a UserData field in the GifFileType structure. */
8900 static gif_memory_source *current_gif_memory_src;
8901
8902 static int
8903 gif_read_from_memory (file, buf, len)
8904 GifFileType *file;
8905 GifByteType *buf;
8906 int len;
8907 {
8908 gif_memory_source *src = current_gif_memory_src;
8909
8910 if (len > src->len - src->index)
8911 return -1;
8912
8913 bcopy (src->bytes + src->index, buf, len);
8914 src->index += len;
8915 return len;
8916 }
8917
8918
8919 /* Load GIF image IMG for use on frame F. Value is non-zero if
8920 successful. */
8921
8922 static int
8923 gif_load (f, img)
8924 struct frame *f;
8925 struct image *img;
8926 {
8927 Lisp_Object file, specified_file;
8928 Lisp_Object specified_data;
8929 int rc, width, height, x, y, i;
8930 XImage *ximg;
8931 ColorMapObject *gif_color_map;
8932 unsigned long pixel_colors[256];
8933 GifFileType *gif;
8934 struct gcpro gcpro1;
8935 Lisp_Object image;
8936 int ino, image_left, image_top, image_width, image_height;
8937 gif_memory_source memsrc;
8938 unsigned char *raster;
8939
8940 specified_file = image_spec_value (img->spec, QCfile, NULL);
8941 specified_data = image_spec_value (img->spec, QCdata, NULL);
8942 file = Qnil;
8943 GCPRO1 (file);
8944
8945 if (NILP (specified_data))
8946 {
8947 file = x_find_image_file (specified_file);
8948 if (!STRINGP (file))
8949 {
8950 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8951 UNGCPRO;
8952 return 0;
8953 }
8954
8955 /* Open the GIF file. */
8956 gif = DGifOpenFileName (SDATA (file));
8957 if (gif == NULL)
8958 {
8959 image_error ("Cannot open `%s'", file, Qnil);
8960 UNGCPRO;
8961 return 0;
8962 }
8963 }
8964 else
8965 {
8966 /* Read from memory! */
8967 current_gif_memory_src = &memsrc;
8968 memsrc.bytes = SDATA (specified_data);
8969 memsrc.len = SBYTES (specified_data);
8970 memsrc.index = 0;
8971
8972 gif = DGifOpen(&memsrc, gif_read_from_memory);
8973 if (!gif)
8974 {
8975 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8976 UNGCPRO;
8977 return 0;
8978 }
8979 }
8980
8981 /* Read entire contents. */
8982 rc = DGifSlurp (gif);
8983 if (rc == GIF_ERROR)
8984 {
8985 image_error ("Error reading `%s'", img->spec, Qnil);
8986 DGifCloseFile (gif);
8987 UNGCPRO;
8988 return 0;
8989 }
8990
8991 image = image_spec_value (img->spec, QCindex, NULL);
8992 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8993 if (ino >= gif->ImageCount)
8994 {
8995 image_error ("Invalid image number `%s' in image `%s'",
8996 image, img->spec);
8997 DGifCloseFile (gif);
8998 UNGCPRO;
8999 return 0;
9000 }
9001
9002 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
9003 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
9004
9005 /* Create the X image and pixmap. */
9006 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9007 {
9008 DGifCloseFile (gif);
9009 UNGCPRO;
9010 return 0;
9011 }
9012
9013 /* Allocate colors. */
9014 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
9015 if (!gif_color_map)
9016 gif_color_map = gif->SColorMap;
9017 init_color_table ();
9018 bzero (pixel_colors, sizeof pixel_colors);
9019
9020 for (i = 0; i < gif_color_map->ColorCount; ++i)
9021 {
9022 int r = gif_color_map->Colors[i].Red << 8;
9023 int g = gif_color_map->Colors[i].Green << 8;
9024 int b = gif_color_map->Colors[i].Blue << 8;
9025 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9026 }
9027
9028 img->colors = colors_in_color_table (&img->ncolors);
9029 free_color_table ();
9030
9031 /* Clear the part of the screen image that are not covered by
9032 the image from the GIF file. Full animated GIF support
9033 requires more than can be done here (see the gif89 spec,
9034 disposal methods). Let's simply assume that the part
9035 not covered by a sub-image is in the frame's background color. */
9036 image_top = gif->SavedImages[ino].ImageDesc.Top;
9037 image_left = gif->SavedImages[ino].ImageDesc.Left;
9038 image_width = gif->SavedImages[ino].ImageDesc.Width;
9039 image_height = gif->SavedImages[ino].ImageDesc.Height;
9040
9041 for (y = 0; y < image_top; ++y)
9042 for (x = 0; x < width; ++x)
9043 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9044
9045 for (y = image_top + image_height; y < height; ++y)
9046 for (x = 0; x < width; ++x)
9047 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9048
9049 for (y = image_top; y < image_top + image_height; ++y)
9050 {
9051 for (x = 0; x < image_left; ++x)
9052 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9053 for (x = image_left + image_width; x < width; ++x)
9054 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9055 }
9056
9057 /* Read the GIF image into the X image. We use a local variable
9058 `raster' here because RasterBits below is a char *, and invites
9059 problems with bytes >= 0x80. */
9060 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9061
9062 if (gif->SavedImages[ino].ImageDesc.Interlace)
9063 {
9064 static int interlace_start[] = {0, 4, 2, 1};
9065 static int interlace_increment[] = {8, 8, 4, 2};
9066 int pass;
9067 int row = interlace_start[0];
9068
9069 pass = 0;
9070
9071 for (y = 0; y < image_height; y++)
9072 {
9073 if (row >= image_height)
9074 {
9075 row = interlace_start[++pass];
9076 while (row >= image_height)
9077 row = interlace_start[++pass];
9078 }
9079
9080 for (x = 0; x < image_width; x++)
9081 {
9082 int i = raster[(y * image_width) + x];
9083 XPutPixel (ximg, x + image_left, row + image_top,
9084 pixel_colors[i]);
9085 }
9086
9087 row += interlace_increment[pass];
9088 }
9089 }
9090 else
9091 {
9092 for (y = 0; y < image_height; ++y)
9093 for (x = 0; x < image_width; ++x)
9094 {
9095 int i = raster[y * image_width + x];
9096 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9097 }
9098 }
9099
9100 DGifCloseFile (gif);
9101
9102 /* Maybe fill in the background field while we have ximg handy. */
9103 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9104 IMAGE_BACKGROUND (img, f, ximg);
9105
9106 /* Put the image into the pixmap, then free the X image and its buffer. */
9107 x_put_x_image (f, ximg, img->pixmap, width, height);
9108 x_destroy_x_image (ximg);
9109
9110 UNGCPRO;
9111 return 1;
9112 }
9113
9114 #endif /* HAVE_GIF != 0 */
9115
9116
9117 \f
9118 /***********************************************************************
9119 Ghostscript
9120 ***********************************************************************/
9121
9122 static int gs_image_p P_ ((Lisp_Object object));
9123 static int gs_load P_ ((struct frame *f, struct image *img));
9124 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9125
9126 /* The symbol `postscript' identifying images of this type. */
9127
9128 Lisp_Object Qpostscript;
9129
9130 /* Keyword symbols. */
9131
9132 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9133
9134 /* Indices of image specification fields in gs_format, below. */
9135
9136 enum gs_keyword_index
9137 {
9138 GS_TYPE,
9139 GS_PT_WIDTH,
9140 GS_PT_HEIGHT,
9141 GS_FILE,
9142 GS_LOADER,
9143 GS_BOUNDING_BOX,
9144 GS_ASCENT,
9145 GS_MARGIN,
9146 GS_RELIEF,
9147 GS_ALGORITHM,
9148 GS_HEURISTIC_MASK,
9149 GS_MASK,
9150 GS_BACKGROUND,
9151 GS_LAST
9152 };
9153
9154 /* Vector of image_keyword structures describing the format
9155 of valid user-defined image specifications. */
9156
9157 static struct image_keyword gs_format[GS_LAST] =
9158 {
9159 {":type", IMAGE_SYMBOL_VALUE, 1},
9160 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9161 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9162 {":file", IMAGE_STRING_VALUE, 1},
9163 {":loader", IMAGE_FUNCTION_VALUE, 0},
9164 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9165 {":ascent", IMAGE_ASCENT_VALUE, 0},
9166 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9167 {":relief", IMAGE_INTEGER_VALUE, 0},
9168 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9169 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9170 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9171 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9172 };
9173
9174 /* Structure describing the image type `ghostscript'. */
9175
9176 static struct image_type gs_type =
9177 {
9178 &Qpostscript,
9179 gs_image_p,
9180 gs_load,
9181 gs_clear_image,
9182 NULL
9183 };
9184
9185
9186 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9187
9188 static void
9189 gs_clear_image (f, img)
9190 struct frame *f;
9191 struct image *img;
9192 {
9193 /* IMG->data.ptr_val may contain a recorded colormap. */
9194 xfree (img->data.ptr_val);
9195 x_clear_image (f, img);
9196 }
9197
9198
9199 /* Return non-zero if OBJECT is a valid Ghostscript image
9200 specification. */
9201
9202 static int
9203 gs_image_p (object)
9204 Lisp_Object object;
9205 {
9206 struct image_keyword fmt[GS_LAST];
9207 Lisp_Object tem;
9208 int i;
9209
9210 bcopy (gs_format, fmt, sizeof fmt);
9211
9212 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9213 return 0;
9214
9215 /* Bounding box must be a list or vector containing 4 integers. */
9216 tem = fmt[GS_BOUNDING_BOX].value;
9217 if (CONSP (tem))
9218 {
9219 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9220 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9221 return 0;
9222 if (!NILP (tem))
9223 return 0;
9224 }
9225 else if (VECTORP (tem))
9226 {
9227 if (XVECTOR (tem)->size != 4)
9228 return 0;
9229 for (i = 0; i < 4; ++i)
9230 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9231 return 0;
9232 }
9233 else
9234 return 0;
9235
9236 return 1;
9237 }
9238
9239
9240 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9241 if successful. */
9242
9243 static int
9244 gs_load (f, img)
9245 struct frame *f;
9246 struct image *img;
9247 {
9248 char buffer[100];
9249 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9250 struct gcpro gcpro1, gcpro2;
9251 Lisp_Object frame;
9252 double in_width, in_height;
9253 Lisp_Object pixel_colors = Qnil;
9254
9255 /* Compute pixel size of pixmap needed from the given size in the
9256 image specification. Sizes in the specification are in pt. 1 pt
9257 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9258 info. */
9259 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9260 in_width = XFASTINT (pt_width) / 72.0;
9261 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9262 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9263 in_height = XFASTINT (pt_height) / 72.0;
9264 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9265
9266 /* Create the pixmap. */
9267 xassert (img->pixmap == None);
9268 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9269 img->width, img->height,
9270 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9271
9272 if (!img->pixmap)
9273 {
9274 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9275 return 0;
9276 }
9277
9278 /* Call the loader to fill the pixmap. It returns a process object
9279 if successful. We do not record_unwind_protect here because
9280 other places in redisplay like calling window scroll functions
9281 don't either. Let the Lisp loader use `unwind-protect' instead. */
9282 GCPRO2 (window_and_pixmap_id, pixel_colors);
9283
9284 sprintf (buffer, "%lu %lu",
9285 (unsigned long) FRAME_X_WINDOW (f),
9286 (unsigned long) img->pixmap);
9287 window_and_pixmap_id = build_string (buffer);
9288
9289 sprintf (buffer, "%lu %lu",
9290 FRAME_FOREGROUND_PIXEL (f),
9291 FRAME_BACKGROUND_PIXEL (f));
9292 pixel_colors = build_string (buffer);
9293
9294 XSETFRAME (frame, f);
9295 loader = image_spec_value (img->spec, QCloader, NULL);
9296 if (NILP (loader))
9297 loader = intern ("gs-load-image");
9298
9299 img->data.lisp_val = call6 (loader, frame, img->spec,
9300 make_number (img->width),
9301 make_number (img->height),
9302 window_and_pixmap_id,
9303 pixel_colors);
9304 UNGCPRO;
9305 return PROCESSP (img->data.lisp_val);
9306 }
9307
9308
9309 /* Kill the Ghostscript process that was started to fill PIXMAP on
9310 frame F. Called from XTread_socket when receiving an event
9311 telling Emacs that Ghostscript has finished drawing. */
9312
9313 void
9314 x_kill_gs_process (pixmap, f)
9315 Pixmap pixmap;
9316 struct frame *f;
9317 {
9318 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9319 int class, i;
9320 struct image *img;
9321
9322 /* Find the image containing PIXMAP. */
9323 for (i = 0; i < c->used; ++i)
9324 if (c->images[i]->pixmap == pixmap)
9325 break;
9326
9327 /* Should someone in between have cleared the image cache, for
9328 instance, give up. */
9329 if (i == c->used)
9330 return;
9331
9332 /* Kill the GS process. We should have found PIXMAP in the image
9333 cache and its image should contain a process object. */
9334 img = c->images[i];
9335 xassert (PROCESSP (img->data.lisp_val));
9336 Fkill_process (img->data.lisp_val, Qnil);
9337 img->data.lisp_val = Qnil;
9338
9339 /* On displays with a mutable colormap, figure out the colors
9340 allocated for the image by looking at the pixels of an XImage for
9341 img->pixmap. */
9342 class = FRAME_X_VISUAL (f)->class;
9343 if (class != StaticColor && class != StaticGray && class != TrueColor)
9344 {
9345 XImage *ximg;
9346
9347 BLOCK_INPUT;
9348
9349 /* Try to get an XImage for img->pixmep. */
9350 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9351 0, 0, img->width, img->height, ~0, ZPixmap);
9352 if (ximg)
9353 {
9354 int x, y;
9355
9356 /* Initialize the color table. */
9357 init_color_table ();
9358
9359 /* For each pixel of the image, look its color up in the
9360 color table. After having done so, the color table will
9361 contain an entry for each color used by the image. */
9362 for (y = 0; y < img->height; ++y)
9363 for (x = 0; x < img->width; ++x)
9364 {
9365 unsigned long pixel = XGetPixel (ximg, x, y);
9366 lookup_pixel_color (f, pixel);
9367 }
9368
9369 /* Record colors in the image. Free color table and XImage. */
9370 img->colors = colors_in_color_table (&img->ncolors);
9371 free_color_table ();
9372 XDestroyImage (ximg);
9373
9374 #if 0 /* This doesn't seem to be the case. If we free the colors
9375 here, we get a BadAccess later in x_clear_image when
9376 freeing the colors. */
9377 /* We have allocated colors once, but Ghostscript has also
9378 allocated colors on behalf of us. So, to get the
9379 reference counts right, free them once. */
9380 if (img->ncolors)
9381 x_free_colors (f, img->colors, img->ncolors);
9382 #endif
9383 }
9384 else
9385 image_error ("Cannot get X image of `%s'; colors will not be freed",
9386 img->spec, Qnil);
9387
9388 UNBLOCK_INPUT;
9389 }
9390
9391 /* Now that we have the pixmap, compute mask and transform the
9392 image if requested. */
9393 BLOCK_INPUT;
9394 postprocess_image (f, img);
9395 UNBLOCK_INPUT;
9396 }
9397
9398
9399 \f
9400 /***********************************************************************
9401 Window properties
9402 ***********************************************************************/
9403
9404 DEFUN ("x-change-window-property", Fx_change_window_property,
9405 Sx_change_window_property, 2, 3, 0,
9406 doc: /* Change window property PROP to VALUE on the X window of FRAME.
9407 PROP and VALUE must be strings. FRAME nil or omitted means use the
9408 selected frame. Value is VALUE. */)
9409 (prop, value, frame)
9410 Lisp_Object frame, prop, value;
9411 {
9412 struct frame *f = check_x_frame (frame);
9413 Atom prop_atom;
9414
9415 CHECK_STRING (prop);
9416 CHECK_STRING (value);
9417
9418 BLOCK_INPUT;
9419 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
9420 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9421 prop_atom, XA_STRING, 8, PropModeReplace,
9422 SDATA (value), SCHARS (value));
9423
9424 /* Make sure the property is set when we return. */
9425 XFlush (FRAME_X_DISPLAY (f));
9426 UNBLOCK_INPUT;
9427
9428 return value;
9429 }
9430
9431
9432 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9433 Sx_delete_window_property, 1, 2, 0,
9434 doc: /* Remove window property PROP from X window of FRAME.
9435 FRAME nil or omitted means use the selected frame. Value is PROP. */)
9436 (prop, frame)
9437 Lisp_Object prop, frame;
9438 {
9439 struct frame *f = check_x_frame (frame);
9440 Atom prop_atom;
9441
9442 CHECK_STRING (prop);
9443 BLOCK_INPUT;
9444 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
9445 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9446
9447 /* Make sure the property is removed when we return. */
9448 XFlush (FRAME_X_DISPLAY (f));
9449 UNBLOCK_INPUT;
9450
9451 return prop;
9452 }
9453
9454
9455 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9456 1, 2, 0,
9457 doc: /* Value is the value of window property PROP on FRAME.
9458 If FRAME is nil or omitted, use the selected frame. Value is nil
9459 if FRAME hasn't a property with name PROP or if PROP has no string
9460 value. */)
9461 (prop, frame)
9462 Lisp_Object prop, frame;
9463 {
9464 struct frame *f = check_x_frame (frame);
9465 Atom prop_atom;
9466 int rc;
9467 Lisp_Object prop_value = Qnil;
9468 char *tmp_data = NULL;
9469 Atom actual_type;
9470 int actual_format;
9471 unsigned long actual_size, bytes_remaining;
9472
9473 CHECK_STRING (prop);
9474 BLOCK_INPUT;
9475 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
9476 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9477 prop_atom, 0, 0, False, XA_STRING,
9478 &actual_type, &actual_format, &actual_size,
9479 &bytes_remaining, (unsigned char **) &tmp_data);
9480 if (rc == Success)
9481 {
9482 int size = bytes_remaining;
9483
9484 XFree (tmp_data);
9485 tmp_data = NULL;
9486
9487 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9488 prop_atom, 0, bytes_remaining,
9489 False, XA_STRING,
9490 &actual_type, &actual_format,
9491 &actual_size, &bytes_remaining,
9492 (unsigned char **) &tmp_data);
9493 if (rc == Success && tmp_data)
9494 prop_value = make_string (tmp_data, size);
9495
9496 XFree (tmp_data);
9497 }
9498
9499 UNBLOCK_INPUT;
9500 return prop_value;
9501 }
9502
9503
9504 \f
9505 /***********************************************************************
9506 Busy cursor
9507 ***********************************************************************/
9508
9509 /* If non-null, an asynchronous timer that, when it expires, displays
9510 an hourglass cursor on all frames. */
9511
9512 static struct atimer *hourglass_atimer;
9513
9514 /* Non-zero means an hourglass cursor is currently shown. */
9515
9516 static int hourglass_shown_p;
9517
9518 /* Number of seconds to wait before displaying an hourglass cursor. */
9519
9520 static Lisp_Object Vhourglass_delay;
9521
9522 /* Default number of seconds to wait before displaying an hourglass
9523 cursor. */
9524
9525 #define DEFAULT_HOURGLASS_DELAY 1
9526
9527 /* Function prototypes. */
9528
9529 static void show_hourglass P_ ((struct atimer *));
9530 static void hide_hourglass P_ ((void));
9531
9532
9533 /* Cancel a currently active hourglass timer, and start a new one. */
9534
9535 void
9536 start_hourglass ()
9537 {
9538 EMACS_TIME delay;
9539 int secs, usecs = 0;
9540
9541 cancel_hourglass ();
9542
9543 if (INTEGERP (Vhourglass_delay)
9544 && XINT (Vhourglass_delay) > 0)
9545 secs = XFASTINT (Vhourglass_delay);
9546 else if (FLOATP (Vhourglass_delay)
9547 && XFLOAT_DATA (Vhourglass_delay) > 0)
9548 {
9549 Lisp_Object tem;
9550 tem = Ftruncate (Vhourglass_delay, Qnil);
9551 secs = XFASTINT (tem);
9552 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
9553 }
9554 else
9555 secs = DEFAULT_HOURGLASS_DELAY;
9556
9557 EMACS_SET_SECS_USECS (delay, secs, usecs);
9558 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
9559 show_hourglass, NULL);
9560 }
9561
9562
9563 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
9564 shown. */
9565
9566 void
9567 cancel_hourglass ()
9568 {
9569 if (hourglass_atimer)
9570 {
9571 cancel_atimer (hourglass_atimer);
9572 hourglass_atimer = NULL;
9573 }
9574
9575 if (hourglass_shown_p)
9576 hide_hourglass ();
9577 }
9578
9579
9580 /* Timer function of hourglass_atimer. TIMER is equal to
9581 hourglass_atimer.
9582
9583 Display an hourglass pointer on all frames by mapping the frames'
9584 hourglass_window. Set the hourglass_p flag in the frames'
9585 output_data.x structure to indicate that an hourglass cursor is
9586 shown on the frames. */
9587
9588 static void
9589 show_hourglass (timer)
9590 struct atimer *timer;
9591 {
9592 /* The timer implementation will cancel this timer automatically
9593 after this function has run. Set hourglass_atimer to null
9594 so that we know the timer doesn't have to be canceled. */
9595 hourglass_atimer = NULL;
9596
9597 if (!hourglass_shown_p)
9598 {
9599 Lisp_Object rest, frame;
9600
9601 BLOCK_INPUT;
9602
9603 FOR_EACH_FRAME (rest, frame)
9604 {
9605 struct frame *f = XFRAME (frame);
9606
9607 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
9608 {
9609 Display *dpy = FRAME_X_DISPLAY (f);
9610
9611 #ifdef USE_X_TOOLKIT
9612 if (f->output_data.x->widget)
9613 #else
9614 if (FRAME_OUTER_WINDOW (f))
9615 #endif
9616 {
9617 f->output_data.x->hourglass_p = 1;
9618
9619 if (!f->output_data.x->hourglass_window)
9620 {
9621 unsigned long mask = CWCursor;
9622 XSetWindowAttributes attrs;
9623
9624 attrs.cursor = f->output_data.x->hourglass_cursor;
9625
9626 f->output_data.x->hourglass_window
9627 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
9628 0, 0, 32000, 32000, 0, 0,
9629 InputOnly,
9630 CopyFromParent,
9631 mask, &attrs);
9632 }
9633
9634 XMapRaised (dpy, f->output_data.x->hourglass_window);
9635 XFlush (dpy);
9636 }
9637 }
9638 }
9639
9640 hourglass_shown_p = 1;
9641 UNBLOCK_INPUT;
9642 }
9643 }
9644
9645
9646 /* Hide the hourglass pointer on all frames, if it is currently
9647 shown. */
9648
9649 static void
9650 hide_hourglass ()
9651 {
9652 if (hourglass_shown_p)
9653 {
9654 Lisp_Object rest, frame;
9655
9656 BLOCK_INPUT;
9657 FOR_EACH_FRAME (rest, frame)
9658 {
9659 struct frame *f = XFRAME (frame);
9660
9661 if (FRAME_X_P (f)
9662 /* Watch out for newly created frames. */
9663 && f->output_data.x->hourglass_window)
9664 {
9665 XUnmapWindow (FRAME_X_DISPLAY (f),
9666 f->output_data.x->hourglass_window);
9667 /* Sync here because XTread_socket looks at the
9668 hourglass_p flag that is reset to zero below. */
9669 XSync (FRAME_X_DISPLAY (f), False);
9670 f->output_data.x->hourglass_p = 0;
9671 }
9672 }
9673
9674 hourglass_shown_p = 0;
9675 UNBLOCK_INPUT;
9676 }
9677 }
9678
9679
9680 \f
9681 /***********************************************************************
9682 Tool tips
9683 ***********************************************************************/
9684
9685 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
9686 Lisp_Object, Lisp_Object));
9687 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
9688 Lisp_Object, int, int, int *, int *));
9689
9690 /* The frame of a currently visible tooltip. */
9691
9692 Lisp_Object tip_frame;
9693
9694 /* If non-nil, a timer started that hides the last tooltip when it
9695 fires. */
9696
9697 Lisp_Object tip_timer;
9698 Window tip_window;
9699
9700 /* If non-nil, a vector of 3 elements containing the last args
9701 with which x-show-tip was called. See there. */
9702
9703 Lisp_Object last_show_tip_args;
9704
9705 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
9706
9707 Lisp_Object Vx_max_tooltip_size;
9708
9709
9710 static Lisp_Object
9711 unwind_create_tip_frame (frame)
9712 Lisp_Object frame;
9713 {
9714 Lisp_Object deleted;
9715
9716 deleted = unwind_create_frame (frame);
9717 if (EQ (deleted, Qt))
9718 {
9719 tip_window = None;
9720 tip_frame = Qnil;
9721 }
9722
9723 return deleted;
9724 }
9725
9726
9727 /* Create a frame for a tooltip on the display described by DPYINFO.
9728 PARMS is a list of frame parameters. TEXT is the string to
9729 display in the tip frame. Value is the frame.
9730
9731 Note that functions called here, esp. x_default_parameter can
9732 signal errors, for instance when a specified color name is
9733 undefined. We have to make sure that we're in a consistent state
9734 when this happens. */
9735
9736 static Lisp_Object
9737 x_create_tip_frame (dpyinfo, parms, text)
9738 struct x_display_info *dpyinfo;
9739 Lisp_Object parms, text;
9740 {
9741 struct frame *f;
9742 Lisp_Object frame, tem;
9743 Lisp_Object name;
9744 long window_prompting = 0;
9745 int width, height;
9746 int count = SPECPDL_INDEX ();
9747 struct gcpro gcpro1, gcpro2, gcpro3;
9748 struct kboard *kb;
9749 int face_change_count_before = face_change_count;
9750 Lisp_Object buffer;
9751 struct buffer *old_buffer;
9752
9753 check_x ();
9754
9755 /* Use this general default value to start with until we know if
9756 this frame has a specified name. */
9757 Vx_resource_name = Vinvocation_name;
9758
9759 #ifdef MULTI_KBOARD
9760 kb = dpyinfo->kboard;
9761 #else
9762 kb = &the_only_kboard;
9763 #endif
9764
9765 /* Get the name of the frame to use for resource lookup. */
9766 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
9767 if (!STRINGP (name)
9768 && !EQ (name, Qunbound)
9769 && !NILP (name))
9770 error ("Invalid frame name--not a string or nil");
9771 Vx_resource_name = name;
9772
9773 frame = Qnil;
9774 GCPRO3 (parms, name, frame);
9775 f = make_frame (1);
9776 XSETFRAME (frame, f);
9777
9778 buffer = Fget_buffer_create (build_string (" *tip*"));
9779 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
9780 old_buffer = current_buffer;
9781 set_buffer_internal_1 (XBUFFER (buffer));
9782 current_buffer->truncate_lines = Qnil;
9783 Ferase_buffer ();
9784 Finsert (1, &text);
9785 set_buffer_internal_1 (old_buffer);
9786
9787 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9788 record_unwind_protect (unwind_create_tip_frame, frame);
9789
9790 /* By setting the output method, we're essentially saying that
9791 the frame is live, as per FRAME_LIVE_P. If we get a signal
9792 from this point on, x_destroy_window might screw up reference
9793 counts etc. */
9794 f->output_method = output_x_window;
9795 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
9796 bzero (f->output_data.x, sizeof (struct x_output));
9797 f->output_data.x->icon_bitmap = -1;
9798 FRAME_FONTSET (f) = -1;
9799 f->output_data.x->scroll_bar_foreground_pixel = -1;
9800 f->output_data.x->scroll_bar_background_pixel = -1;
9801 #ifdef USE_TOOLKIT_SCROLL_BARS
9802 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
9803 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
9804 #endif /* USE_TOOLKIT_SCROLL_BARS */
9805 f->icon_name = Qnil;
9806 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
9807 #if GLYPH_DEBUG
9808 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
9809 dpyinfo_refcount = dpyinfo->reference_count;
9810 #endif /* GLYPH_DEBUG */
9811 #ifdef MULTI_KBOARD
9812 FRAME_KBOARD (f) = kb;
9813 #endif
9814 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9815 f->output_data.x->explicit_parent = 0;
9816
9817 /* These colors will be set anyway later, but it's important
9818 to get the color reference counts right, so initialize them! */
9819 {
9820 Lisp_Object black;
9821 struct gcpro gcpro1;
9822
9823 black = build_string ("black");
9824 GCPRO1 (black);
9825 f->output_data.x->foreground_pixel
9826 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9827 f->output_data.x->background_pixel
9828 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9829 f->output_data.x->cursor_pixel
9830 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9831 f->output_data.x->cursor_foreground_pixel
9832 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9833 f->output_data.x->border_pixel
9834 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9835 f->output_data.x->mouse_pixel
9836 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9837 UNGCPRO;
9838 }
9839
9840 /* Set the name; the functions to which we pass f expect the name to
9841 be set. */
9842 if (EQ (name, Qunbound) || NILP (name))
9843 {
9844 f->name = build_string (dpyinfo->x_id_name);
9845 f->explicit_name = 0;
9846 }
9847 else
9848 {
9849 f->name = name;
9850 f->explicit_name = 1;
9851 /* use the frame's title when getting resources for this frame. */
9852 specbind (Qx_resource_name, name);
9853 }
9854
9855 /* Extract the window parameters from the supplied values that are
9856 needed to determine window geometry. */
9857 {
9858 Lisp_Object font;
9859
9860 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
9861
9862 BLOCK_INPUT;
9863 /* First, try whatever font the caller has specified. */
9864 if (STRINGP (font))
9865 {
9866 tem = Fquery_fontset (font, Qnil);
9867 if (STRINGP (tem))
9868 font = x_new_fontset (f, SDATA (tem));
9869 else
9870 font = x_new_font (f, SDATA (font));
9871 }
9872
9873 /* Try out a font which we hope has bold and italic variations. */
9874 if (!STRINGP (font))
9875 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9876 if (!STRINGP (font))
9877 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9878 if (! STRINGP (font))
9879 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9880 if (! STRINGP (font))
9881 /* This was formerly the first thing tried, but it finds too many fonts
9882 and takes too long. */
9883 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9884 /* If those didn't work, look for something which will at least work. */
9885 if (! STRINGP (font))
9886 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9887 UNBLOCK_INPUT;
9888 if (! STRINGP (font))
9889 font = build_string ("fixed");
9890
9891 x_default_parameter (f, parms, Qfont, font,
9892 "font", "Font", RES_TYPE_STRING);
9893 }
9894
9895 x_default_parameter (f, parms, Qborder_width, make_number (2),
9896 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9897
9898 /* This defaults to 2 in order to match xterm. We recognize either
9899 internalBorderWidth or internalBorder (which is what xterm calls
9900 it). */
9901 if (NILP (Fassq (Qinternal_border_width, parms)))
9902 {
9903 Lisp_Object value;
9904
9905 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
9906 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9907 if (! EQ (value, Qunbound))
9908 parms = Fcons (Fcons (Qinternal_border_width, value),
9909 parms);
9910 }
9911
9912 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9913 "internalBorderWidth", "internalBorderWidth",
9914 RES_TYPE_NUMBER);
9915
9916 /* Also do the stuff which must be set before the window exists. */
9917 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9918 "foreground", "Foreground", RES_TYPE_STRING);
9919 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9920 "background", "Background", RES_TYPE_STRING);
9921 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9922 "pointerColor", "Foreground", RES_TYPE_STRING);
9923 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9924 "cursorColor", "Foreground", RES_TYPE_STRING);
9925 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9926 "borderColor", "BorderColor", RES_TYPE_STRING);
9927
9928 /* Init faces before x_default_parameter is called for scroll-bar
9929 parameters because that function calls x_set_scroll_bar_width,
9930 which calls change_frame_size, which calls Fset_window_buffer,
9931 which runs hooks, which call Fvertical_motion. At the end, we
9932 end up in init_iterator with a null face cache, which should not
9933 happen. */
9934 init_frame_faces (f);
9935
9936 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9937
9938 window_prompting = x_figure_window_size (f, parms, 0);
9939
9940 {
9941 XSetWindowAttributes attrs;
9942 unsigned long mask;
9943
9944 BLOCK_INPUT;
9945 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
9946 if (DoesSaveUnders (dpyinfo->screen))
9947 mask |= CWSaveUnder;
9948
9949 /* Window managers look at the override-redirect flag to determine
9950 whether or net to give windows a decoration (Xlib spec, chapter
9951 3.2.8). */
9952 attrs.override_redirect = True;
9953 attrs.save_under = True;
9954 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9955 /* Arrange for getting MapNotify and UnmapNotify events. */
9956 attrs.event_mask = StructureNotifyMask;
9957 tip_window
9958 = FRAME_X_WINDOW (f)
9959 = XCreateWindow (FRAME_X_DISPLAY (f),
9960 FRAME_X_DISPLAY_INFO (f)->root_window,
9961 /* x, y, width, height */
9962 0, 0, 1, 1,
9963 /* Border. */
9964 1,
9965 CopyFromParent, InputOutput, CopyFromParent,
9966 mask, &attrs);
9967 UNBLOCK_INPUT;
9968 }
9969
9970 x_make_gc (f);
9971
9972 x_default_parameter (f, parms, Qauto_raise, Qnil,
9973 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9974 x_default_parameter (f, parms, Qauto_lower, Qnil,
9975 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9976 x_default_parameter (f, parms, Qcursor_type, Qbox,
9977 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9978
9979 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
9980 Change will not be effected unless different from the current
9981 FRAME_LINES (f). */
9982 width = FRAME_COLS (f);
9983 height = FRAME_LINES (f);
9984 SET_FRAME_COLS (f, 0);
9985 FRAME_LINES (f) = 0;
9986 change_frame_size (f, height, width, 1, 0, 0);
9987
9988 /* Add `tooltip' frame parameter's default value. */
9989 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
9990 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
9991 Qnil));
9992
9993 /* Set up faces after all frame parameters are known. This call
9994 also merges in face attributes specified for new frames.
9995
9996 Frame parameters may be changed if .Xdefaults contains
9997 specifications for the default font. For example, if there is an
9998 `Emacs.default.attributeBackground: pink', the `background-color'
9999 attribute of the frame get's set, which let's the internal border
10000 of the tooltip frame appear in pink. Prevent this. */
10001 {
10002 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
10003
10004 /* Set tip_frame here, so that */
10005 tip_frame = frame;
10006 call1 (Qface_set_after_frame_default, frame);
10007
10008 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
10009 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
10010 Qnil));
10011 }
10012
10013 f->no_split = 1;
10014
10015 UNGCPRO;
10016
10017 /* It is now ok to make the frame official even if we get an error
10018 below. And the frame needs to be on Vframe_list or making it
10019 visible won't work. */
10020 Vframe_list = Fcons (frame, Vframe_list);
10021
10022 /* Now that the frame is official, it counts as a reference to
10023 its display. */
10024 FRAME_X_DISPLAY_INFO (f)->reference_count++;
10025
10026 /* Setting attributes of faces of the tooltip frame from resources
10027 and similar will increment face_change_count, which leads to the
10028 clearing of all current matrices. Since this isn't necessary
10029 here, avoid it by resetting face_change_count to the value it
10030 had before we created the tip frame. */
10031 face_change_count = face_change_count_before;
10032
10033 /* Discard the unwind_protect. */
10034 return unbind_to (count, frame);
10035 }
10036
10037
10038 /* Compute where to display tip frame F. PARMS is the list of frame
10039 parameters for F. DX and DY are specified offsets from the current
10040 location of the mouse. WIDTH and HEIGHT are the width and height
10041 of the tooltip. Return coordinates relative to the root window of
10042 the display in *ROOT_X, and *ROOT_Y. */
10043
10044 static void
10045 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
10046 struct frame *f;
10047 Lisp_Object parms, dx, dy;
10048 int width, height;
10049 int *root_x, *root_y;
10050 {
10051 Lisp_Object left, top;
10052 int win_x, win_y;
10053 Window root, child;
10054 unsigned pmask;
10055
10056 /* User-specified position? */
10057 left = Fcdr (Fassq (Qleft, parms));
10058 top = Fcdr (Fassq (Qtop, parms));
10059
10060 /* Move the tooltip window where the mouse pointer is. Resize and
10061 show it. */
10062 if (!INTEGERP (left) || !INTEGERP (top))
10063 {
10064 BLOCK_INPUT;
10065 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10066 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
10067 UNBLOCK_INPUT;
10068 }
10069
10070 if (INTEGERP (top))
10071 *root_y = XINT (top);
10072 else if (*root_y + XINT (dy) - height < 0)
10073 *root_y -= XINT (dy);
10074 else
10075 {
10076 *root_y -= height;
10077 *root_y += XINT (dy);
10078 }
10079
10080 if (INTEGERP (left))
10081 *root_x = XINT (left);
10082 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
10083 /* It fits to the right of the pointer. */
10084 *root_x += XINT (dx);
10085 else if (width + XINT (dx) <= *root_x)
10086 /* It fits to the left of the pointer. */
10087 *root_x -= width + XINT (dx);
10088 else
10089 /* Put it left-justified on the screen--it ought to fit that way. */
10090 *root_x = 0;
10091 }
10092
10093
10094 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
10095 doc: /* Show STRING in a "tooltip" window on frame FRAME.
10096 A tooltip window is a small X window displaying a string.
10097
10098 FRAME nil or omitted means use the selected frame.
10099
10100 PARMS is an optional list of frame parameters which can be used to
10101 change the tooltip's appearance.
10102
10103 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
10104 means use the default timeout of 5 seconds.
10105
10106 If the list of frame parameters PARAMS contains a `left' parameters,
10107 the tooltip is displayed at that x-position. Otherwise it is
10108 displayed at the mouse position, with offset DX added (default is 5 if
10109 DX isn't specified). Likewise for the y-position; if a `top' frame
10110 parameter is specified, it determines the y-position of the tooltip
10111 window, otherwise it is displayed at the mouse position, with offset
10112 DY added (default is -10).
10113
10114 A tooltip's maximum size is specified by `x-max-tooltip-size'.
10115 Text larger than the specified size is clipped. */)
10116 (string, frame, parms, timeout, dx, dy)
10117 Lisp_Object string, frame, parms, timeout, dx, dy;
10118 {
10119 struct frame *f;
10120 struct window *w;
10121 int root_x, root_y;
10122 struct buffer *old_buffer;
10123 struct text_pos pos;
10124 int i, width, height;
10125 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10126 int old_windows_or_buffers_changed = windows_or_buffers_changed;
10127 int count = SPECPDL_INDEX ();
10128
10129 specbind (Qinhibit_redisplay, Qt);
10130
10131 GCPRO4 (string, parms, frame, timeout);
10132
10133 CHECK_STRING (string);
10134 f = check_x_frame (frame);
10135 if (NILP (timeout))
10136 timeout = make_number (5);
10137 else
10138 CHECK_NATNUM (timeout);
10139
10140 if (NILP (dx))
10141 dx = make_number (5);
10142 else
10143 CHECK_NUMBER (dx);
10144
10145 if (NILP (dy))
10146 dy = make_number (-10);
10147 else
10148 CHECK_NUMBER (dy);
10149
10150 if (NILP (last_show_tip_args))
10151 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
10152
10153 if (!NILP (tip_frame))
10154 {
10155 Lisp_Object last_string = AREF (last_show_tip_args, 0);
10156 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
10157 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
10158
10159 if (EQ (frame, last_frame)
10160 && !NILP (Fequal (last_string, string))
10161 && !NILP (Fequal (last_parms, parms)))
10162 {
10163 struct frame *f = XFRAME (tip_frame);
10164
10165 /* Only DX and DY have changed. */
10166 if (!NILP (tip_timer))
10167 {
10168 Lisp_Object timer = tip_timer;
10169 tip_timer = Qnil;
10170 call1 (Qcancel_timer, timer);
10171 }
10172
10173 BLOCK_INPUT;
10174 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
10175 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
10176 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10177 root_x, root_y);
10178 UNBLOCK_INPUT;
10179 goto start_timer;
10180 }
10181 }
10182
10183 /* Hide a previous tip, if any. */
10184 Fx_hide_tip ();
10185
10186 ASET (last_show_tip_args, 0, string);
10187 ASET (last_show_tip_args, 1, frame);
10188 ASET (last_show_tip_args, 2, parms);
10189
10190 /* Add default values to frame parameters. */
10191 if (NILP (Fassq (Qname, parms)))
10192 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10193 if (NILP (Fassq (Qinternal_border_width, parms)))
10194 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10195 if (NILP (Fassq (Qborder_width, parms)))
10196 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10197 if (NILP (Fassq (Qborder_color, parms)))
10198 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
10199 if (NILP (Fassq (Qbackground_color, parms)))
10200 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
10201 parms);
10202
10203 /* Create a frame for the tooltip, and record it in the global
10204 variable tip_frame. */
10205 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
10206 f = XFRAME (frame);
10207
10208 /* Set up the frame's root window. */
10209 w = XWINDOW (FRAME_ROOT_WINDOW (f));
10210 w->left_col = w->top_line = make_number (0);
10211
10212 if (CONSP (Vx_max_tooltip_size)
10213 && INTEGERP (XCAR (Vx_max_tooltip_size))
10214 && XINT (XCAR (Vx_max_tooltip_size)) > 0
10215 && INTEGERP (XCDR (Vx_max_tooltip_size))
10216 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
10217 {
10218 w->total_cols = XCAR (Vx_max_tooltip_size);
10219 w->total_lines = XCDR (Vx_max_tooltip_size);
10220 }
10221 else
10222 {
10223 w->total_cols = make_number (80);
10224 w->total_lines = make_number (40);
10225 }
10226
10227 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
10228 adjust_glyphs (f);
10229 w->pseudo_window_p = 1;
10230
10231 /* Display the tooltip text in a temporary buffer. */
10232 old_buffer = current_buffer;
10233 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
10234 current_buffer->truncate_lines = Qnil;
10235 clear_glyph_matrix (w->desired_matrix);
10236 clear_glyph_matrix (w->current_matrix);
10237 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
10238 try_window (FRAME_ROOT_WINDOW (f), pos);
10239
10240 /* Compute width and height of the tooltip. */
10241 width = height = 0;
10242 for (i = 0; i < w->desired_matrix->nrows; ++i)
10243 {
10244 struct glyph_row *row = &w->desired_matrix->rows[i];
10245 struct glyph *last;
10246 int row_width;
10247
10248 /* Stop at the first empty row at the end. */
10249 if (!row->enabled_p || !row->displays_text_p)
10250 break;
10251
10252 /* Let the row go over the full width of the frame. */
10253 row->full_width_p = 1;
10254
10255 /* There's a glyph at the end of rows that is used to place
10256 the cursor there. Don't include the width of this glyph. */
10257 if (row->used[TEXT_AREA])
10258 {
10259 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
10260 row_width = row->pixel_width - last->pixel_width;
10261 }
10262 else
10263 row_width = row->pixel_width;
10264
10265 height += row->height;
10266 width = max (width, row_width);
10267 }
10268
10269 /* Add the frame's internal border to the width and height the X
10270 window should have. */
10271 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10272 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10273
10274 /* Move the tooltip window where the mouse pointer is. Resize and
10275 show it. */
10276 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
10277
10278 BLOCK_INPUT;
10279 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10280 root_x, root_y, width, height);
10281 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10282 UNBLOCK_INPUT;
10283
10284 /* Draw into the window. */
10285 w->must_be_updated_p = 1;
10286 update_single_window (w, 1);
10287
10288 /* Restore original current buffer. */
10289 set_buffer_internal_1 (old_buffer);
10290 windows_or_buffers_changed = old_windows_or_buffers_changed;
10291
10292 start_timer:
10293 /* Let the tip disappear after timeout seconds. */
10294 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
10295 intern ("x-hide-tip"));
10296
10297 UNGCPRO;
10298 return unbind_to (count, Qnil);
10299 }
10300
10301
10302 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
10303 doc: /* Hide the current tooltip window, if there is any.
10304 Value is t if tooltip was open, nil otherwise. */)
10305 ()
10306 {
10307 int count;
10308 Lisp_Object deleted, frame, timer;
10309 struct gcpro gcpro1, gcpro2;
10310
10311 /* Return quickly if nothing to do. */
10312 if (NILP (tip_timer) && NILP (tip_frame))
10313 return Qnil;
10314
10315 frame = tip_frame;
10316 timer = tip_timer;
10317 GCPRO2 (frame, timer);
10318 tip_frame = tip_timer = deleted = Qnil;
10319
10320 count = SPECPDL_INDEX ();
10321 specbind (Qinhibit_redisplay, Qt);
10322 specbind (Qinhibit_quit, Qt);
10323
10324 if (!NILP (timer))
10325 call1 (Qcancel_timer, timer);
10326
10327 if (FRAMEP (frame))
10328 {
10329 Fdelete_frame (frame, Qnil);
10330 deleted = Qt;
10331
10332 #ifdef USE_LUCID
10333 /* Bloodcurdling hack alert: The Lucid menu bar widget's
10334 redisplay procedure is not called when a tip frame over menu
10335 items is unmapped. Redisplay the menu manually... */
10336 {
10337 struct frame *f = SELECTED_FRAME ();
10338 Widget w = f->output_data.x->menubar_widget;
10339 extern void xlwmenu_redisplay P_ ((Widget));
10340
10341 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
10342 && w != NULL)
10343 {
10344 BLOCK_INPUT;
10345 xlwmenu_redisplay (w);
10346 UNBLOCK_INPUT;
10347 }
10348 }
10349 #endif /* USE_LUCID */
10350 }
10351
10352 UNGCPRO;
10353 return unbind_to (count, deleted);
10354 }
10355
10356
10357 \f
10358 /***********************************************************************
10359 File selection dialog
10360 ***********************************************************************/
10361
10362 #ifdef USE_MOTIF
10363
10364 /* Callback for "OK" and "Cancel" on file selection dialog. */
10365
10366 static void
10367 file_dialog_cb (widget, client_data, call_data)
10368 Widget widget;
10369 XtPointer call_data, client_data;
10370 {
10371 int *result = (int *) client_data;
10372 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
10373 *result = cb->reason;
10374 }
10375
10376
10377 /* Callback for unmapping a file selection dialog. This is used to
10378 capture the case where a dialog is closed via a window manager's
10379 closer button, for example. Using a XmNdestroyCallback didn't work
10380 in this case. */
10381
10382 static void
10383 file_dialog_unmap_cb (widget, client_data, call_data)
10384 Widget widget;
10385 XtPointer call_data, client_data;
10386 {
10387 int *result = (int *) client_data;
10388 *result = XmCR_CANCEL;
10389 }
10390
10391
10392 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10393 doc: /* Read file name, prompting with PROMPT in directory DIR.
10394 Use a file selection dialog.
10395 Select DEFAULT-FILENAME in the dialog's file selection box, if
10396 specified. Don't let the user enter a file name in the file
10397 selection dialog's entry field, if MUSTMATCH is non-nil. */)
10398 (prompt, dir, default_filename, mustmatch)
10399 Lisp_Object prompt, dir, default_filename, mustmatch;
10400 {
10401 int result;
10402 struct frame *f = SELECTED_FRAME ();
10403 Lisp_Object file = Qnil;
10404 Widget dialog, text, list, help;
10405 Arg al[10];
10406 int ac = 0;
10407 extern XtAppContext Xt_app_con;
10408 XmString dir_xmstring, pattern_xmstring;
10409 int count = SPECPDL_INDEX ();
10410 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10411
10412 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10413 CHECK_STRING (prompt);
10414 CHECK_STRING (dir);
10415
10416 /* Prevent redisplay. */
10417 specbind (Qinhibit_redisplay, Qt);
10418
10419 BLOCK_INPUT;
10420
10421 /* Create the dialog with PROMPT as title, using DIR as initial
10422 directory and using "*" as pattern. */
10423 dir = Fexpand_file_name (dir, Qnil);
10424 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
10425 pattern_xmstring = XmStringCreateLocalized ("*");
10426
10427 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
10428 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
10429 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
10430 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
10431 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
10432 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
10433 "fsb", al, ac);
10434 XmStringFree (dir_xmstring);
10435 XmStringFree (pattern_xmstring);
10436
10437 /* Add callbacks for OK and Cancel. */
10438 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
10439 (XtPointer) &result);
10440 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
10441 (XtPointer) &result);
10442 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
10443 (XtPointer) &result);
10444
10445 /* Disable the help button since we can't display help. */
10446 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
10447 XtSetSensitive (help, False);
10448
10449 /* Mark OK button as default. */
10450 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
10451 XmNshowAsDefault, True, NULL);
10452
10453 /* If MUSTMATCH is non-nil, disable the file entry field of the
10454 dialog, so that the user must select a file from the files list
10455 box. We can't remove it because we wouldn't have a way to get at
10456 the result file name, then. */
10457 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
10458 if (!NILP (mustmatch))
10459 {
10460 Widget label;
10461 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
10462 XtSetSensitive (text, False);
10463 XtSetSensitive (label, False);
10464 }
10465
10466 /* Manage the dialog, so that list boxes get filled. */
10467 XtManageChild (dialog);
10468
10469 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10470 must include the path for this to work. */
10471 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
10472 if (STRINGP (default_filename))
10473 {
10474 XmString default_xmstring;
10475 int item_pos;
10476
10477 default_xmstring
10478 = XmStringCreateLocalized (SDATA (default_filename));
10479
10480 if (!XmListItemExists (list, default_xmstring))
10481 {
10482 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10483 XmListAddItem (list, default_xmstring, 0);
10484 item_pos = 0;
10485 }
10486 else
10487 item_pos = XmListItemPos (list, default_xmstring);
10488 XmStringFree (default_xmstring);
10489
10490 /* Select the item and scroll it into view. */
10491 XmListSelectPos (list, item_pos, True);
10492 XmListSetPos (list, item_pos);
10493 }
10494
10495 /* Process events until the user presses Cancel or OK. */
10496 result = 0;
10497 while (result == 0)
10498 {
10499 XEvent event;
10500 XtAppNextEvent (Xt_app_con, &event);
10501 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f) );
10502 }
10503
10504 /* Get the result. */
10505 if (result == XmCR_OK)
10506 {
10507 XmString text;
10508 String data;
10509
10510 XtVaGetValues (dialog, XmNtextString, &text, NULL);
10511 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
10512 XmStringFree (text);
10513 file = build_string (data);
10514 XtFree (data);
10515 }
10516 else
10517 file = Qnil;
10518
10519 /* Clean up. */
10520 XtUnmanageChild (dialog);
10521 XtDestroyWidget (dialog);
10522 UNBLOCK_INPUT;
10523 UNGCPRO;
10524
10525 /* Make "Cancel" equivalent to C-g. */
10526 if (NILP (file))
10527 Fsignal (Qquit, Qnil);
10528
10529 return unbind_to (count, file);
10530 }
10531
10532 #endif /* USE_MOTIF */
10533
10534 #ifdef USE_GTK
10535
10536 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10537 "Read file name, prompting with PROMPT in directory DIR.\n\
10538 Use a file selection dialog.\n\
10539 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10540 specified. Don't let the user enter a file name in the file\n\
10541 selection dialog's entry field, if MUSTMATCH is non-nil.")
10542 (prompt, dir, default_filename, mustmatch)
10543 Lisp_Object prompt, dir, default_filename, mustmatch;
10544 {
10545 FRAME_PTR f = SELECTED_FRAME ();
10546 char *fn;
10547 Lisp_Object file = Qnil;
10548 int count = specpdl_ptr - specpdl;
10549 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10550 char *cdef_file;
10551 char *cprompt;
10552
10553 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10554 CHECK_STRING (prompt);
10555 CHECK_STRING (dir);
10556
10557 /* Prevent redisplay. */
10558 specbind (Qinhibit_redisplay, Qt);
10559
10560 BLOCK_INPUT;
10561
10562 if (STRINGP (default_filename))
10563 cdef_file = SDATA (default_filename);
10564 else
10565 cdef_file = SDATA (dir);
10566
10567 fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch));
10568
10569 if (fn)
10570 {
10571 file = build_string (fn);
10572 xfree (fn);
10573 }
10574
10575 UNBLOCK_INPUT;
10576 UNGCPRO;
10577
10578 /* Make "Cancel" equivalent to C-g. */
10579 if (NILP (file))
10580 Fsignal (Qquit, Qnil);
10581
10582 return unbind_to (count, file);
10583 }
10584
10585 #endif /* USE_GTK */
10586
10587 \f
10588 /***********************************************************************
10589 Keyboard
10590 ***********************************************************************/
10591
10592 #ifdef HAVE_XKBGETKEYBOARD
10593 #include <X11/XKBlib.h>
10594 #include <X11/keysym.h>
10595 #endif
10596
10597 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
10598 Sx_backspace_delete_keys_p, 0, 1, 0,
10599 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
10600 FRAME nil means use the selected frame.
10601 Value is t if we know that both keys are present, and are mapped to the
10602 usual X keysyms. */)
10603 (frame)
10604 Lisp_Object frame;
10605 {
10606 #ifdef HAVE_XKBGETKEYBOARD
10607 XkbDescPtr kb;
10608 struct frame *f = check_x_frame (frame);
10609 Display *dpy = FRAME_X_DISPLAY (f);
10610 Lisp_Object have_keys;
10611 int major, minor, op, event, error;
10612
10613 BLOCK_INPUT;
10614
10615 /* Check library version in case we're dynamically linked. */
10616 major = XkbMajorVersion;
10617 minor = XkbMinorVersion;
10618 if (!XkbLibraryVersion (&major, &minor))
10619 {
10620 UNBLOCK_INPUT;
10621 return Qnil;
10622 }
10623
10624 /* Check that the server supports XKB. */
10625 major = XkbMajorVersion;
10626 minor = XkbMinorVersion;
10627 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
10628 {
10629 UNBLOCK_INPUT;
10630 return Qnil;
10631 }
10632
10633 have_keys = Qnil;
10634 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
10635 if (kb)
10636 {
10637 int delete_keycode = 0, backspace_keycode = 0, i;
10638
10639 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
10640 {
10641 for (i = kb->min_key_code;
10642 (i < kb->max_key_code
10643 && (delete_keycode == 0 || backspace_keycode == 0));
10644 ++i)
10645 {
10646 /* The XKB symbolic key names can be seen most easily in
10647 the PS file generated by `xkbprint -label name
10648 $DISPLAY'. */
10649 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
10650 delete_keycode = i;
10651 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
10652 backspace_keycode = i;
10653 }
10654
10655 XkbFreeNames (kb, 0, True);
10656 }
10657
10658 XkbFreeClientMap (kb, 0, True);
10659
10660 if (delete_keycode
10661 && backspace_keycode
10662 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
10663 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
10664 have_keys = Qt;
10665 }
10666 UNBLOCK_INPUT;
10667 return have_keys;
10668 #else /* not HAVE_XKBGETKEYBOARD */
10669 return Qnil;
10670 #endif /* not HAVE_XKBGETKEYBOARD */
10671 }
10672
10673
10674 \f
10675 /***********************************************************************
10676 Initialization
10677 ***********************************************************************/
10678
10679 /* Keep this list in the same order as frame_parms in frame.c.
10680 Use 0 for unsupported frame parameters. */
10681
10682 frame_parm_handler x_frame_parm_handlers[] =
10683 {
10684 x_set_autoraise,
10685 x_set_autolower,
10686 x_set_background_color,
10687 x_set_border_color,
10688 x_set_border_width,
10689 x_set_cursor_color,
10690 x_set_cursor_type,
10691 x_set_font,
10692 x_set_foreground_color,
10693 x_set_icon_name,
10694 x_set_icon_type,
10695 x_set_internal_border_width,
10696 x_set_menu_bar_lines,
10697 x_set_mouse_color,
10698 x_explicitly_set_name,
10699 x_set_scroll_bar_width,
10700 x_set_title,
10701 x_set_unsplittable,
10702 x_set_vertical_scroll_bars,
10703 x_set_visibility,
10704 x_set_tool_bar_lines,
10705 x_set_scroll_bar_foreground,
10706 x_set_scroll_bar_background,
10707 x_set_screen_gamma,
10708 x_set_line_spacing,
10709 x_set_fringe_width,
10710 x_set_fringe_width,
10711 x_set_wait_for_wm,
10712 x_set_fullscreen,
10713 };
10714
10715 void
10716 syms_of_xfns ()
10717 {
10718 /* This is zero if not using X windows. */
10719 x_in_use = 0;
10720
10721 /* The section below is built by the lisp expression at the top of the file,
10722 just above where these variables are declared. */
10723 /*&&& init symbols here &&&*/
10724 Qnone = intern ("none");
10725 staticpro (&Qnone);
10726 Qsuppress_icon = intern ("suppress-icon");
10727 staticpro (&Qsuppress_icon);
10728 Qundefined_color = intern ("undefined-color");
10729 staticpro (&Qundefined_color);
10730 Qcenter = intern ("center");
10731 staticpro (&Qcenter);
10732 Qcompound_text = intern ("compound-text");
10733 staticpro (&Qcompound_text);
10734 Qcancel_timer = intern ("cancel-timer");
10735 staticpro (&Qcancel_timer);
10736 /* This is the end of symbol initialization. */
10737
10738 /* Text property `display' should be nonsticky by default. */
10739 Vtext_property_default_nonsticky
10740 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10741
10742
10743 Qlaplace = intern ("laplace");
10744 staticpro (&Qlaplace);
10745 Qemboss = intern ("emboss");
10746 staticpro (&Qemboss);
10747 Qedge_detection = intern ("edge-detection");
10748 staticpro (&Qedge_detection);
10749 Qheuristic = intern ("heuristic");
10750 staticpro (&Qheuristic);
10751 QCmatrix = intern (":matrix");
10752 staticpro (&QCmatrix);
10753 QCcolor_adjustment = intern (":color-adjustment");
10754 staticpro (&QCcolor_adjustment);
10755 QCmask = intern (":mask");
10756 staticpro (&QCmask);
10757
10758 Fput (Qundefined_color, Qerror_conditions,
10759 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10760 Fput (Qundefined_color, Qerror_message,
10761 build_string ("Undefined color"));
10762
10763 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
10764 doc: /* Non-nil means always draw a cross over disabled images.
10765 Disabled images are those having an `:conversion disabled' property.
10766 A cross is always drawn on black & white displays. */);
10767 cross_disabled_images = 0;
10768
10769 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10770 doc: /* List of directories to search for window system bitmap files. */);
10771 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
10772
10773 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10774 doc: /* The shape of the pointer when over text.
10775 Changing the value does not affect existing frames
10776 unless you set the mouse color. */);
10777 Vx_pointer_shape = Qnil;
10778
10779 #if 0 /* This doesn't really do anything. */
10780 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
10781 doc: /* The shape of the pointer when not over text.
10782 This variable takes effect when you create a new frame
10783 or when you set the mouse color. */);
10784 #endif
10785 Vx_nontext_pointer_shape = Qnil;
10786
10787 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
10788 doc: /* The shape of the pointer when Emacs is busy.
10789 This variable takes effect when you create a new frame
10790 or when you set the mouse color. */);
10791 Vx_hourglass_pointer_shape = Qnil;
10792
10793 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
10794 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
10795 display_hourglass_p = 1;
10796
10797 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
10798 doc: /* *Seconds to wait before displaying an hourglass pointer.
10799 Value must be an integer or float. */);
10800 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
10801
10802 #if 0 /* This doesn't really do anything. */
10803 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
10804 doc: /* The shape of the pointer when over the mode line.
10805 This variable takes effect when you create a new frame
10806 or when you set the mouse color. */);
10807 #endif
10808 Vx_mode_pointer_shape = Qnil;
10809
10810 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10811 &Vx_sensitive_text_pointer_shape,
10812 doc: /* The shape of the pointer when over mouse-sensitive text.
10813 This variable takes effect when you create a new frame
10814 or when you set the mouse color. */);
10815 Vx_sensitive_text_pointer_shape = Qnil;
10816
10817 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
10818 &Vx_window_horizontal_drag_shape,
10819 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
10820 This variable takes effect when you create a new frame
10821 or when you set the mouse color. */);
10822 Vx_window_horizontal_drag_shape = Qnil;
10823
10824 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10825 doc: /* A string indicating the foreground color of the cursor box. */);
10826 Vx_cursor_fore_pixel = Qnil;
10827
10828 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
10829 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
10830 Text larger than this is clipped. */);
10831 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
10832
10833 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10834 doc: /* Non-nil if no X window manager is in use.
10835 Emacs doesn't try to figure this out; this is always nil
10836 unless you set it to something else. */);
10837 /* We don't have any way to find this out, so set it to nil
10838 and maybe the user would like to set it to t. */
10839 Vx_no_window_manager = Qnil;
10840
10841 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10842 &Vx_pixel_size_width_font_regexp,
10843 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
10844
10845 Since Emacs gets width of a font matching with this regexp from
10846 PIXEL_SIZE field of the name, font finding mechanism gets faster for
10847 such a font. This is especially effective for such large fonts as
10848 Chinese, Japanese, and Korean. */);
10849 Vx_pixel_size_width_font_regexp = Qnil;
10850
10851 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10852 doc: /* Time after which cached images are removed from the cache.
10853 When an image has not been displayed this many seconds, remove it
10854 from the image cache. Value must be an integer or nil with nil
10855 meaning don't clear the cache. */);
10856 Vimage_cache_eviction_delay = make_number (30 * 60);
10857
10858 #ifdef USE_X_TOOLKIT
10859 Fprovide (intern ("x-toolkit"), Qnil);
10860 #ifdef USE_MOTIF
10861 Fprovide (intern ("motif"), Qnil);
10862
10863 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
10864 doc: /* Version info for LessTif/Motif. */);
10865 Vmotif_version_string = build_string (XmVERSION_STRING);
10866 #endif /* USE_MOTIF */
10867 #endif /* USE_X_TOOLKIT */
10868
10869 /* X window properties. */
10870 defsubr (&Sx_change_window_property);
10871 defsubr (&Sx_delete_window_property);
10872 defsubr (&Sx_window_property);
10873
10874 defsubr (&Sxw_display_color_p);
10875 defsubr (&Sx_display_grayscale_p);
10876 defsubr (&Sxw_color_defined_p);
10877 defsubr (&Sxw_color_values);
10878 defsubr (&Sx_server_max_request_size);
10879 defsubr (&Sx_server_vendor);
10880 defsubr (&Sx_server_version);
10881 defsubr (&Sx_display_pixel_width);
10882 defsubr (&Sx_display_pixel_height);
10883 defsubr (&Sx_display_mm_width);
10884 defsubr (&Sx_display_mm_height);
10885 defsubr (&Sx_display_screens);
10886 defsubr (&Sx_display_planes);
10887 defsubr (&Sx_display_color_cells);
10888 defsubr (&Sx_display_visual_class);
10889 defsubr (&Sx_display_backing_store);
10890 defsubr (&Sx_display_save_under);
10891 defsubr (&Sx_create_frame);
10892 defsubr (&Sx_open_connection);
10893 defsubr (&Sx_close_connection);
10894 defsubr (&Sx_display_list);
10895 defsubr (&Sx_synchronize);
10896 defsubr (&Sx_focus_frame);
10897 defsubr (&Sx_backspace_delete_keys_p);
10898
10899 /* Setting callback functions for fontset handler. */
10900 get_font_info_func = x_get_font_info;
10901
10902 #if 0 /* This function pointer doesn't seem to be used anywhere.
10903 And the pointer assigned has the wrong type, anyway. */
10904 list_fonts_func = x_list_fonts;
10905 #endif
10906
10907 load_font_func = x_load_font;
10908 find_ccl_program_func = x_find_ccl_program;
10909 query_font_func = x_query_font;
10910 set_frame_fontset_func = x_set_font;
10911 check_window_system_func = check_x;
10912
10913 /* Images. */
10914 Qxbm = intern ("xbm");
10915 staticpro (&Qxbm);
10916 QCconversion = intern (":conversion");
10917 staticpro (&QCconversion);
10918 QCheuristic_mask = intern (":heuristic-mask");
10919 staticpro (&QCheuristic_mask);
10920 QCcolor_symbols = intern (":color-symbols");
10921 staticpro (&QCcolor_symbols);
10922 QCascent = intern (":ascent");
10923 staticpro (&QCascent);
10924 QCmargin = intern (":margin");
10925 staticpro (&QCmargin);
10926 QCrelief = intern (":relief");
10927 staticpro (&QCrelief);
10928 Qpostscript = intern ("postscript");
10929 staticpro (&Qpostscript);
10930 QCloader = intern (":loader");
10931 staticpro (&QCloader);
10932 QCbounding_box = intern (":bounding-box");
10933 staticpro (&QCbounding_box);
10934 QCpt_width = intern (":pt-width");
10935 staticpro (&QCpt_width);
10936 QCpt_height = intern (":pt-height");
10937 staticpro (&QCpt_height);
10938 QCindex = intern (":index");
10939 staticpro (&QCindex);
10940 Qpbm = intern ("pbm");
10941 staticpro (&Qpbm);
10942
10943 #if HAVE_XPM
10944 Qxpm = intern ("xpm");
10945 staticpro (&Qxpm);
10946 #endif
10947
10948 #if HAVE_JPEG
10949 Qjpeg = intern ("jpeg");
10950 staticpro (&Qjpeg);
10951 #endif
10952
10953 #if HAVE_TIFF
10954 Qtiff = intern ("tiff");
10955 staticpro (&Qtiff);
10956 #endif
10957
10958 #if HAVE_GIF
10959 Qgif = intern ("gif");
10960 staticpro (&Qgif);
10961 #endif
10962
10963 #if HAVE_PNG
10964 Qpng = intern ("png");
10965 staticpro (&Qpng);
10966 #endif
10967
10968 defsubr (&Sclear_image_cache);
10969 defsubr (&Simage_size);
10970 defsubr (&Simage_mask_p);
10971
10972 hourglass_atimer = NULL;
10973 hourglass_shown_p = 0;
10974
10975 defsubr (&Sx_show_tip);
10976 defsubr (&Sx_hide_tip);
10977 tip_timer = Qnil;
10978 staticpro (&tip_timer);
10979 tip_frame = Qnil;
10980 staticpro (&tip_frame);
10981
10982 last_show_tip_args = Qnil;
10983 staticpro (&last_show_tip_args);
10984
10985 #ifdef USE_MOTIF
10986 defsubr (&Sx_file_dialog);
10987 #endif
10988 }
10989
10990
10991 void
10992 init_xfns ()
10993 {
10994 image_types = NULL;
10995 Vimage_types = Qnil;
10996
10997 define_image_type (&xbm_type);
10998 define_image_type (&gs_type);
10999 define_image_type (&pbm_type);
11000
11001 #if HAVE_XPM
11002 define_image_type (&xpm_type);
11003 #endif
11004
11005 #if HAVE_JPEG
11006 define_image_type (&jpeg_type);
11007 #endif
11008
11009 #if HAVE_TIFF
11010 define_image_type (&tiff_type);
11011 #endif
11012
11013 #if HAVE_GIF
11014 define_image_type (&gif_type);
11015 #endif
11016
11017 #if HAVE_PNG
11018 define_image_type (&png_type);
11019 #endif
11020 }
11021
11022 #endif /* HAVE_X_WINDOWS */