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