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