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