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