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