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