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