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