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