comparison src/xfns.c @ 88155:d7ddb3e565de

sync with trunk
author Henrik Enberg <henrik.enberg@telia.com>
date Mon, 16 Jan 2006 00:03:54 +0000
parents 834df49192b0
children
comparison
equal deleted inserted replaced
88154:8ce476d3ba36 88155:d7ddb3e565de
1 /* Functions for the X window system. 1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 Free Software Foundation. 3 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 4
5 This file is part of GNU Emacs. 5 This file is part of GNU Emacs.
6 6
7 GNU Emacs is free software; you can redistribute it and/or modify 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 8 it under the terms of the GNU General Public License as published by
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details. 15 GNU General Public License for more details.
16 16
17 You should have received a copy of the GNU General Public License 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 18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02110-1301, USA. */
21 21
22 #include <config.h> 22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h> 23 #include <stdio.h>
25 #include <math.h> 24 #include <math.h>
26 25
27 #ifdef HAVE_UNISTD_H 26 #ifdef HAVE_UNISTD_H
28 #include <unistd.h> 27 #include <unistd.h>
123 122
124 #endif /* USE_MOTIF */ 123 #endif /* USE_MOTIF */
125 124
126 #endif /* USE_X_TOOLKIT */ 125 #endif /* USE_X_TOOLKIT */
127 126
127 #ifdef USE_GTK
128
129 /* GTK+ version info */
130
131 static Lisp_Object Vgtk_version_string;
132
133 #endif /* USE_GTK */
134
128 #ifdef HAVE_X11R4 135 #ifdef HAVE_X11R4
129 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy)) 136 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
130 #else 137 #else
131 #define MAXREQUEST(dpy) ((dpy)->max_request_size) 138 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
132 #endif 139 #endif
137 144
138 int gray_bitmap_width = gray_width; 145 int gray_bitmap_width = gray_width;
139 int gray_bitmap_height = gray_height; 146 int gray_bitmap_height = gray_height;
140 char *gray_bitmap_bits = gray_bits; 147 char *gray_bitmap_bits = gray_bits;
141 148
142 /* The name we're using in resource queries. Most often "emacs". */
143
144 Lisp_Object Vx_resource_name;
145
146 /* The application class we're using in resource queries.
147 Normally "Emacs". */
148
149 Lisp_Object Vx_resource_class;
150
151 /* Non-zero means we're allowed to display an hourglass cursor. */ 149 /* Non-zero means we're allowed to display an hourglass cursor. */
152 150
153 int display_hourglass_p; 151 int display_hourglass_p;
152
153 /* Non-zero means prompt with the old GTK file selection dialog. */
154
155 int x_use_old_gtk_file_dialog;
156
157 /* If non-zero, by default show hidden files in the GTK file chooser. */
158
159 int x_gtk_show_hidden_files;
154 160
155 /* The background and shape of the mouse pointer, and shape when not 161 /* The background and shape of the mouse pointer, and shape when not
156 over text or in the modeline. */ 162 over text or in the modeline. */
157 163
158 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape; 164 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
177 183
178 /* Non nil if no window manager is in use. */ 184 /* Non nil if no window manager is in use. */
179 185
180 Lisp_Object Vx_no_window_manager; 186 Lisp_Object Vx_no_window_manager;
181 187
182 /* Search path for bitmap files. */
183
184 Lisp_Object Vx_bitmap_file_path;
185
186 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */ 188 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
187 189
188 Lisp_Object Vx_pixel_size_width_font_regexp; 190 Lisp_Object Vx_pixel_size_width_font_regexp;
189 191
190 Lisp_Object Qauto_raise;
191 Lisp_Object Qauto_lower;
192 Lisp_Object Qborder_color;
193 Lisp_Object Qborder_width;
194 extern Lisp_Object Qbox;
195 Lisp_Object Qcursor_color;
196 Lisp_Object Qcursor_type;
197 Lisp_Object Qgeometry;
198 Lisp_Object Qicon_left;
199 Lisp_Object Qicon_top;
200 Lisp_Object Qicon_type;
201 Lisp_Object Qicon_name;
202 Lisp_Object Qinternal_border_width;
203 Lisp_Object Qleft;
204 Lisp_Object Qright;
205 Lisp_Object Qmouse_color;
206 Lisp_Object Qnone; 192 Lisp_Object Qnone;
207 Lisp_Object Qouter_window_id;
208 Lisp_Object Qparent_id;
209 Lisp_Object Qscroll_bar_width;
210 Lisp_Object Qsuppress_icon; 193 Lisp_Object Qsuppress_icon;
211 extern Lisp_Object Qtop;
212 Lisp_Object Qundefined_color; 194 Lisp_Object Qundefined_color;
213 Lisp_Object Qvertical_scroll_bars;
214 Lisp_Object Qvisibility;
215 Lisp_Object Qwindow_id;
216 Lisp_Object Qx_frame_parameter;
217 Lisp_Object Qx_resource_name;
218 Lisp_Object Quser_position;
219 Lisp_Object Quser_size;
220 extern Lisp_Object Qdisplay;
221 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
222 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
223 Lisp_Object Qcompound_text, Qcancel_timer; 195 Lisp_Object Qcompound_text, Qcancel_timer;
224 Lisp_Object Qwait_for_wm; 196
225 Lisp_Object Qfullscreen; 197 /* In dispnew.c */
226 Lisp_Object Qfullwidth; 198
227 Lisp_Object Qfullheight; 199 extern Lisp_Object Vwindow_system_version;
228 Lisp_Object Qfullboth;
229 200
230 /* The below are defined in frame.c. */ 201 /* The below are defined in frame.c. */
231
232 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
233 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
234 extern Lisp_Object Qtool_bar_lines;
235
236 extern Lisp_Object Vwindow_system_version;
237
238 Lisp_Object Qface_set_after_frame_default;
239 202
240 #if GLYPH_DEBUG 203 #if GLYPH_DEBUG
241 int image_cache_refcount, dpyinfo_refcount; 204 int image_cache_refcount, dpyinfo_refcount;
242 #endif 205 #endif
243 206
281 244
282 /* Let the user specify an X display with a frame. 245 /* Let the user specify an X display with a frame.
283 nil stands for the selected frame--or, if that is not an X frame, 246 nil stands for the selected frame--or, if that is not an X frame,
284 the first X display on the list. */ 247 the first X display on the list. */
285 248
286 static struct x_display_info * 249 struct x_display_info *
287 check_x_display_info (frame) 250 check_x_display_info (frame)
288 Lisp_Object frame; 251 Lisp_Object frame;
289 { 252 {
290 struct x_display_info *dpyinfo = NULL; 253 struct x_display_info *dpyinfo = NULL;
291 254
322 struct x_display_info *dpyinfo; 285 struct x_display_info *dpyinfo;
323 int wdesc; 286 int wdesc;
324 { 287 {
325 Lisp_Object tail, frame; 288 Lisp_Object tail, frame;
326 struct frame *f; 289 struct frame *f;
290
291 if (wdesc == None) return 0;
327 292
328 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail)) 293 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
329 { 294 {
330 frame = XCAR (tail); 295 frame = XCAR (tail);
331 if (!GC_FRAMEP (frame)) 296 if (!GC_FRAMEP (frame))
345 return f; 310 return f;
346 #else /* not USE_X_TOOLKIT */ 311 #else /* not USE_X_TOOLKIT */
347 #ifdef USE_GTK 312 #ifdef USE_GTK
348 if (f->output_data.x->edit_widget) 313 if (f->output_data.x->edit_widget)
349 { 314 {
350 GtkWidget *gwdesc = xg_win_to_widget (wdesc); 315 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
351 struct x_output *x = f->output_data.x; 316 struct x_output *x = f->output_data.x;
352 if (gwdesc != 0 && gwdesc == x->edit_widget) 317 if (gwdesc != 0 && gwdesc == x->edit_widget)
353 return f; 318 return f;
354 } 319 }
355 #endif /* USE_GTK */ 320 #endif /* USE_GTK */
371 int wdesc; 336 int wdesc;
372 { 337 {
373 Lisp_Object tail, frame; 338 Lisp_Object tail, frame;
374 struct frame *f, *found; 339 struct frame *f, *found;
375 struct x_output *x; 340 struct x_output *x;
341
342 if (wdesc == None) return NULL;
376 343
377 found = NULL; 344 found = NULL;
378 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail)) 345 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
379 { 346 {
380 frame = XCAR (tail); 347 frame = XCAR (tail);
389 if (x->hourglass_window == wdesc) 356 if (x->hourglass_window == wdesc)
390 found = f; 357 found = f;
391 else if (x->widget) 358 else if (x->widget)
392 { 359 {
393 #ifdef USE_GTK 360 #ifdef USE_GTK
394 GtkWidget *gwdesc = xg_win_to_widget (wdesc); 361 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
395 if (gwdesc != 0 362 if (gwdesc != 0
396 && (gwdesc == x->widget 363 && (gwdesc == x->widget
397 || gwdesc == x->edit_widget 364 || gwdesc == x->edit_widget
398 || gwdesc == x->vbox_widget 365 || gwdesc == x->vbox_widget
399 || gwdesc == x->menubar_widget)) 366 || gwdesc == x->menubar_widget))
426 { 393 {
427 Lisp_Object tail, frame; 394 Lisp_Object tail, frame;
428 struct frame *f; 395 struct frame *f;
429 struct x_output *x; 396 struct x_output *x;
430 397
398 if (wdesc == None) return 0;
399
431 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail)) 400 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
432 { 401 {
433 frame = XCAR (tail); 402 frame = XCAR (tail);
434 if (!GC_FRAMEP (frame)) 403 if (!GC_FRAMEP (frame))
435 continue; 404 continue;
441 if (x->hourglass_window == wdesc) 410 if (x->hourglass_window == wdesc)
442 return f; 411 return f;
443 else if (x->widget) 412 else if (x->widget)
444 { 413 {
445 #ifdef USE_GTK 414 #ifdef USE_GTK
446 GtkWidget *gwdesc = xg_win_to_widget (wdesc); 415 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
447 if (gwdesc != 0 416 if (gwdesc != 0
448 && (gwdesc == x->widget 417 && (gwdesc == x->widget
449 || gwdesc == x->edit_widget 418 || gwdesc == x->edit_widget
450 || gwdesc == x->vbox_widget)) 419 || gwdesc == x->vbox_widget))
451 return f; 420 return f;
472 { 441 {
473 Lisp_Object tail, frame; 442 Lisp_Object tail, frame;
474 struct frame *f; 443 struct frame *f;
475 struct x_output *x; 444 struct x_output *x;
476 445
446 if (wdesc == None) return 0;
447
477 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail)) 448 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
478 { 449 {
479 frame = XCAR (tail); 450 frame = XCAR (tail);
480 if (!GC_FRAMEP (frame)) 451 if (!GC_FRAMEP (frame))
481 continue; 452 continue;
485 x = f->output_data.x; 456 x = f->output_data.x;
486 /* Match if the window is this frame's menubar. */ 457 /* Match if the window is this frame's menubar. */
487 #ifdef USE_GTK 458 #ifdef USE_GTK
488 if (x->menubar_widget) 459 if (x->menubar_widget)
489 { 460 {
490 GtkWidget *gwdesc = xg_win_to_widget (wdesc); 461 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
491 int found = 0; 462 int found = 0;
492 463
493 BLOCK_INPUT; 464 BLOCK_INPUT;
494 if (gwdesc != 0 465 if (gwdesc != 0
495 && (gwdesc == x->menubar_widget 466 && (gwdesc == x->menubar_widget
517 { 488 {
518 Lisp_Object tail, frame; 489 Lisp_Object tail, frame;
519 struct frame *f; 490 struct frame *f;
520 struct x_output *x; 491 struct x_output *x;
521 492
493 if (wdesc == None) return 0;
494
522 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail)) 495 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
523 { 496 {
524 frame = XCAR (tail); 497 frame = XCAR (tail);
525 if (!GC_FRAMEP (frame)) 498 if (!GC_FRAMEP (frame))
526 continue; 499 continue;
531 504
532 if (x->widget) 505 if (x->widget)
533 { 506 {
534 /* This frame matches if the window is its topmost widget. */ 507 /* This frame matches if the window is its topmost widget. */
535 #ifdef USE_GTK 508 #ifdef USE_GTK
536 GtkWidget *gwdesc = xg_win_to_widget (wdesc); 509 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
537 if (gwdesc == x->widget) 510 if (gwdesc == x->widget)
538 return f; 511 return f;
539 #else 512 #else
540 if (wdesc == XtWindow (x->widget)) 513 if (wdesc == XtWindow (x->widget))
541 return f; 514 return f;
557 } 530 }
558 #endif /* USE_X_TOOLKIT || USE_GTK */ 531 #endif /* USE_X_TOOLKIT || USE_GTK */
559 532
560 533
561 534
562 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
563 id, which is just an int that this section returns. Bitmaps are
564 reference counted so they can be shared among frames.
565
566 Bitmap indices are guaranteed to be > 0, so a negative number can
567 be used to indicate no bitmap.
568
569 If you use x_create_bitmap_from_data, then you must keep track of
570 the bitmaps yourself. That is, creating a bitmap from the same
571 data more than once will not be caught. */
572
573
574 /* Functions to access the contents of a bitmap, given an id. */
575
576 int
577 x_bitmap_height (f, id)
578 FRAME_PTR f;
579 int id;
580 {
581 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
582 }
583
584 int
585 x_bitmap_width (f, id)
586 FRAME_PTR f;
587 int id;
588 {
589 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
590 }
591
592 int
593 x_bitmap_pixmap (f, id)
594 FRAME_PTR f;
595 int id;
596 {
597 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
598 }
599
600
601 /* Allocate a new bitmap record. Returns index of new record. */
602
603 static int
604 x_allocate_bitmap_record (f)
605 FRAME_PTR f;
606 {
607 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
608 int i;
609
610 if (dpyinfo->bitmaps == NULL)
611 {
612 dpyinfo->bitmaps_size = 10;
613 dpyinfo->bitmaps
614 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
615 dpyinfo->bitmaps_last = 1;
616 return 1;
617 }
618
619 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
620 return ++dpyinfo->bitmaps_last;
621
622 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
623 if (dpyinfo->bitmaps[i].refcount == 0)
624 return i + 1;
625
626 dpyinfo->bitmaps_size *= 2;
627 dpyinfo->bitmaps
628 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
629 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
630 return ++dpyinfo->bitmaps_last;
631 }
632
633 /* Add one reference to the reference count of the bitmap with id ID. */
634
635 void
636 x_reference_bitmap (f, id)
637 FRAME_PTR f;
638 int id;
639 {
640 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
641 }
642
643 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
644
645 int
646 x_create_bitmap_from_data (f, bits, width, height)
647 struct frame *f;
648 char *bits;
649 unsigned int width, height;
650 {
651 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
652 Pixmap bitmap;
653 int id;
654
655 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
656 bits, width, height);
657
658 if (! bitmap)
659 return -1;
660
661 id = x_allocate_bitmap_record (f);
662 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
663 dpyinfo->bitmaps[id - 1].file = NULL;
664 dpyinfo->bitmaps[id - 1].refcount = 1;
665 dpyinfo->bitmaps[id - 1].depth = 1;
666 dpyinfo->bitmaps[id - 1].height = height;
667 dpyinfo->bitmaps[id - 1].width = width;
668
669 return id;
670 }
671
672 /* Create bitmap from file FILE for frame F. */
673
674 int
675 x_create_bitmap_from_file (f, file)
676 struct frame *f;
677 Lisp_Object file;
678 {
679 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
680 unsigned int width, height;
681 Pixmap bitmap;
682 int xhot, yhot, result, id;
683 Lisp_Object found;
684 int fd;
685 char *filename;
686
687 /* Look for an existing bitmap with the same name. */
688 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
689 {
690 if (dpyinfo->bitmaps[id].refcount
691 && dpyinfo->bitmaps[id].file
692 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
693 {
694 ++dpyinfo->bitmaps[id].refcount;
695 return id + 1;
696 }
697 }
698
699 /* Search bitmap-file-path for the file, if appropriate. */
700 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
701 if (fd < 0)
702 return -1;
703 emacs_close (fd);
704
705 filename = (char *) SDATA (found);
706
707 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
708 filename, &width, &height, &bitmap, &xhot, &yhot);
709 if (result != BitmapSuccess)
710 return -1;
711
712 id = x_allocate_bitmap_record (f);
713 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
714 dpyinfo->bitmaps[id - 1].refcount = 1;
715 dpyinfo->bitmaps[id - 1].file
716 = (char *) xmalloc (SBYTES (file) + 1);
717 dpyinfo->bitmaps[id - 1].depth = 1;
718 dpyinfo->bitmaps[id - 1].height = height;
719 dpyinfo->bitmaps[id - 1].width = width;
720 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
721
722 return id;
723 }
724
725 /* Remove reference to bitmap with id number ID. */
726
727 void
728 x_destroy_bitmap (f, id)
729 FRAME_PTR f;
730 int id;
731 {
732 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
733
734 if (id > 0)
735 {
736 --dpyinfo->bitmaps[id - 1].refcount;
737 if (dpyinfo->bitmaps[id - 1].refcount == 0)
738 {
739 BLOCK_INPUT;
740 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
741 if (dpyinfo->bitmaps[id - 1].file)
742 {
743 xfree (dpyinfo->bitmaps[id - 1].file);
744 dpyinfo->bitmaps[id - 1].file = NULL;
745 }
746 UNBLOCK_INPUT;
747 }
748 }
749 }
750
751 /* Free all the bitmaps for the display specified by DPYINFO. */
752
753 static void
754 x_destroy_all_bitmaps (dpyinfo)
755 struct x_display_info *dpyinfo;
756 {
757 int i;
758 for (i = 0; i < dpyinfo->bitmaps_last; i++)
759 if (dpyinfo->bitmaps[i].refcount > 0)
760 {
761 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
762 if (dpyinfo->bitmaps[i].file)
763 xfree (dpyinfo->bitmaps[i].file);
764 }
765 dpyinfo->bitmaps_last = 0;
766 }
767
768 /* Connect the frame-parameter names for X frames
769 to the ways of passing the parameter values to the window system.
770
771 The name of a parameter, as a Lisp symbol,
772 has an `x-frame-parameter' property which is an integer in Lisp
773 that is an index in this table. */
774
775 struct x_frame_parm_table
776 {
777 char *name;
778 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
779 };
780
781 static Lisp_Object unwind_create_frame P_ ((Lisp_Object)); 535 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
782 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object)); 536 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
783 static void x_change_window_heights P_ ((Lisp_Object, int)); 537
784 static void x_disable_image P_ ((struct frame *, struct image *));
785 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 538 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
786 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
787 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object)); 539 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
788 static void x_set_fullscreen P_ ((struct frame *, Lisp_Object, Lisp_Object));
789 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 540 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
790 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 541 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
791 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 542 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
792 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 543 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
793 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object)); 544 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
794 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object)); 545 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
795 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object)); 546 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
796 static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
797 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
798 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
799 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
800 Lisp_Object));
801 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object)); 547 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
802 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
803 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
804 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
805 Lisp_Object));
806 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
807 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object)); 548 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
808 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
809 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object)); 549 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
810 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
811 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object)); 550 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
812 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object, 551 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
813 Lisp_Object)); 552 Lisp_Object));
814 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object, 553 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
815 Lisp_Object)); 554 Lisp_Object));
816 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *, 555 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
817 Lisp_Object, 556 Lisp_Object,
818 Lisp_Object, 557 Lisp_Object,
819 char *, char *, 558 char *, char *,
820 int)); 559 int));
821 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
822 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
823 Lisp_Object));
824 static void init_color_table P_ ((void));
825 static void free_color_table P_ ((void));
826 static unsigned long *colors_in_color_table P_ ((int *n));
827 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
828 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
829
830
831
832 static struct x_frame_parm_table x_frame_parms[] =
833 {
834 {"auto-raise", x_set_autoraise},
835 {"auto-lower", x_set_autolower},
836 {"background-color", x_set_background_color},
837 {"border-color", x_set_border_color},
838 {"border-width", x_set_border_width},
839 {"cursor-color", x_set_cursor_color},
840 {"cursor-type", x_set_cursor_type},
841 {"font", x_set_font},
842 {"foreground-color", x_set_foreground_color},
843 {"icon-name", x_set_icon_name},
844 {"icon-type", x_set_icon_type},
845 {"internal-border-width", x_set_internal_border_width},
846 {"menu-bar-lines", x_set_menu_bar_lines},
847 {"mouse-color", x_set_mouse_color},
848 {"name", x_explicitly_set_name},
849 {"scroll-bar-width", x_set_scroll_bar_width},
850 {"title", x_set_title},
851 {"unsplittable", x_set_unsplittable},
852 {"vertical-scroll-bars", x_set_vertical_scroll_bars},
853 {"visibility", x_set_visibility},
854 {"tool-bar-lines", x_set_tool_bar_lines},
855 {"scroll-bar-foreground", x_set_scroll_bar_foreground},
856 {"scroll-bar-background", x_set_scroll_bar_background},
857 {"screen-gamma", x_set_screen_gamma},
858 {"line-spacing", x_set_line_spacing},
859 {"left-fringe", x_set_fringe_width},
860 {"right-fringe", x_set_fringe_width},
861 {"wait-for-wm", x_set_wait_for_wm},
862 {"fullscreen", x_set_fullscreen},
863
864 };
865
866 /* Attach the `x-frame-parameter' properties to
867 the Lisp symbol names of parameters relevant to X. */
868
869 void
870 init_x_parm_symbols ()
871 {
872 int i;
873
874 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
875 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
876 make_number (i));
877 }
878 560
879
880 /* Really try to move where we want to be in case of fullscreen. Some WMs
881 moves the window where we tell them. Some (mwm, twm) moves the outer
882 window manager window there instead.
883 Try to compensate for those WM here. */
884 static void
885 x_fullscreen_move (f, new_top, new_left)
886 struct frame *f;
887 int new_top;
888 int new_left;
889 {
890 if (new_top != f->output_data.x->top_pos
891 || new_left != f->output_data.x->left_pos)
892 {
893 int move_x = new_left + f->output_data.x->x_pixels_outer_diff;
894 int move_y = new_top + f->output_data.x->y_pixels_outer_diff;
895
896 f->output_data.x->want_fullscreen |= FULLSCREEN_MOVE_WAIT;
897 x_set_offset (f, move_x, move_y, 1);
898 }
899 }
900
901 /* Change the parameters of frame F as specified by ALIST.
902 If a parameter is not specially recognized, do nothing special;
903 otherwise call the `x_set_...' function for that parameter.
904 Except for certain geometry properties, always call store_frame_param
905 to store the new value in the parameter alist. */
906
907 void
908 x_set_frame_parameters (f, alist)
909 FRAME_PTR f;
910 Lisp_Object alist;
911 {
912 Lisp_Object tail;
913
914 /* If both of these parameters are present, it's more efficient to
915 set them both at once. So we wait until we've looked at the
916 entire list before we set them. */
917 int width, height;
918
919 /* Same here. */
920 Lisp_Object left, top;
921
922 /* Same with these. */
923 Lisp_Object icon_left, icon_top;
924
925 /* Record in these vectors all the parms specified. */
926 Lisp_Object *parms;
927 Lisp_Object *values;
928 int i, p;
929 int left_no_change = 0, top_no_change = 0;
930 int icon_left_no_change = 0, icon_top_no_change = 0;
931 int fullscreen_is_being_set = 0;
932
933 struct gcpro gcpro1, gcpro2;
934
935 i = 0;
936 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
937 i++;
938
939 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
940 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
941
942 /* Extract parm names and values into those vectors. */
943
944 i = 0;
945 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
946 {
947 Lisp_Object elt;
948
949 elt = Fcar (tail);
950 parms[i] = Fcar (elt);
951 values[i] = Fcdr (elt);
952 i++;
953 }
954 /* TAIL and ALIST are not used again below here. */
955 alist = tail = Qnil;
956
957 GCPRO2 (*parms, *values);
958 gcpro1.nvars = i;
959 gcpro2.nvars = i;
960
961 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
962 because their values appear in VALUES and strings are not valid. */
963 top = left = Qunbound;
964 icon_left = icon_top = Qunbound;
965
966 /* Provide default values for HEIGHT and WIDTH. */
967 if (FRAME_NEW_WIDTH (f))
968 width = FRAME_NEW_WIDTH (f);
969 else
970 width = FRAME_WIDTH (f);
971
972 if (FRAME_NEW_HEIGHT (f))
973 height = FRAME_NEW_HEIGHT (f);
974 else
975 height = FRAME_HEIGHT (f);
976
977 /* Process foreground_color and background_color before anything else.
978 They are independent of other properties, but other properties (e.g.,
979 cursor_color) are dependent upon them. */
980 /* Process default font as well, since fringe widths depends on it. */
981 /* Also, process fullscreen, width and height depend upon that */
982 for (p = 0; p < i; p++)
983 {
984 Lisp_Object prop, val;
985
986 prop = parms[p];
987 val = values[p];
988 if (EQ (prop, Qforeground_color)
989 || EQ (prop, Qbackground_color)
990 || EQ (prop, Qfont)
991 || EQ (prop, Qfullscreen))
992 {
993 register Lisp_Object param_index, old_value;
994
995 old_value = get_frame_param (f, prop);
996 fullscreen_is_being_set |= EQ (prop, Qfullscreen);
997
998 if (NILP (Fequal (val, old_value)))
999 {
1000 store_frame_param (f, prop, val);
1001
1002 param_index = Fget (prop, Qx_frame_parameter);
1003 if (NATNUMP (param_index)
1004 && (XFASTINT (param_index)
1005 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
1006 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
1007 }
1008 }
1009 }
1010
1011 /* Now process them in reverse of specified order. */
1012 for (i--; i >= 0; i--)
1013 {
1014 Lisp_Object prop, val;
1015
1016 prop = parms[i];
1017 val = values[i];
1018
1019 if (EQ (prop, Qwidth) && NUMBERP (val))
1020 width = XFASTINT (val);
1021 else if (EQ (prop, Qheight) && NUMBERP (val))
1022 height = XFASTINT (val);
1023 else if (EQ (prop, Qtop))
1024 top = val;
1025 else if (EQ (prop, Qleft))
1026 left = val;
1027 else if (EQ (prop, Qicon_top))
1028 icon_top = val;
1029 else if (EQ (prop, Qicon_left))
1030 icon_left = val;
1031 else if (EQ (prop, Qforeground_color)
1032 || EQ (prop, Qbackground_color)
1033 || EQ (prop, Qfont)
1034 || EQ (prop, Qfullscreen))
1035 /* Processed above. */
1036 continue;
1037 else
1038 {
1039 register Lisp_Object param_index, old_value;
1040
1041 old_value = get_frame_param (f, prop);
1042
1043 store_frame_param (f, prop, val);
1044
1045 param_index = Fget (prop, Qx_frame_parameter);
1046 if (NATNUMP (param_index)
1047 && (XFASTINT (param_index)
1048 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
1049 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
1050 }
1051 }
1052
1053 /* Don't die if just one of these was set. */
1054 if (EQ (left, Qunbound))
1055 {
1056 left_no_change = 1;
1057 if (f->output_data.x->left_pos < 0)
1058 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
1059 else
1060 XSETINT (left, f->output_data.x->left_pos);
1061 }
1062 if (EQ (top, Qunbound))
1063 {
1064 top_no_change = 1;
1065 if (f->output_data.x->top_pos < 0)
1066 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
1067 else
1068 XSETINT (top, f->output_data.x->top_pos);
1069 }
1070
1071 /* If one of the icon positions was not set, preserve or default it. */
1072 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
1073 {
1074 icon_left_no_change = 1;
1075 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
1076 if (NILP (icon_left))
1077 XSETINT (icon_left, 0);
1078 }
1079 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
1080 {
1081 icon_top_no_change = 1;
1082 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
1083 if (NILP (icon_top))
1084 XSETINT (icon_top, 0);
1085 }
1086
1087 if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
1088 {
1089 /* If the frame is visible already and the fullscreen parameter is
1090 being set, it is too late to set WM manager hints to specify
1091 size and position.
1092 Here we first get the width, height and position that applies to
1093 fullscreen. We then move the frame to the appropriate
1094 position. Resize of the frame is taken care of in the code after
1095 this if-statement. */
1096 int new_left, new_top;
1097
1098 x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
1099 x_fullscreen_move (f, new_top, new_left);
1100 }
1101
1102 /* Don't set these parameters unless they've been explicitly
1103 specified. The window might be mapped or resized while we're in
1104 this function, and we don't want to override that unless the lisp
1105 code has asked for it.
1106
1107 Don't set these parameters unless they actually differ from the
1108 window's current parameters; the window may not actually exist
1109 yet. */
1110 {
1111 Lisp_Object frame;
1112
1113 check_frame_size (f, &height, &width);
1114
1115 XSETFRAME (frame, f);
1116
1117 if (width != FRAME_WIDTH (f)
1118 || height != FRAME_HEIGHT (f)
1119 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1120 Fset_frame_size (frame, make_number (width), make_number (height));
1121
1122 if ((!NILP (left) || !NILP (top))
1123 && ! (left_no_change && top_no_change)
1124 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1125 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1126 {
1127 int leftpos = 0;
1128 int toppos = 0;
1129
1130 /* Record the signs. */
1131 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1132 if (EQ (left, Qminus))
1133 f->output_data.x->size_hint_flags |= XNegative;
1134 else if (INTEGERP (left))
1135 {
1136 leftpos = XINT (left);
1137 if (leftpos < 0)
1138 f->output_data.x->size_hint_flags |= XNegative;
1139 }
1140 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1141 && CONSP (XCDR (left))
1142 && INTEGERP (XCAR (XCDR (left))))
1143 {
1144 leftpos = - XINT (XCAR (XCDR (left)));
1145 f->output_data.x->size_hint_flags |= XNegative;
1146 }
1147 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1148 && CONSP (XCDR (left))
1149 && INTEGERP (XCAR (XCDR (left))))
1150 {
1151 leftpos = XINT (XCAR (XCDR (left)));
1152 }
1153
1154 if (EQ (top, Qminus))
1155 f->output_data.x->size_hint_flags |= YNegative;
1156 else if (INTEGERP (top))
1157 {
1158 toppos = XINT (top);
1159 if (toppos < 0)
1160 f->output_data.x->size_hint_flags |= YNegative;
1161 }
1162 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1163 && CONSP (XCDR (top))
1164 && INTEGERP (XCAR (XCDR (top))))
1165 {
1166 toppos = - XINT (XCAR (XCDR (top)));
1167 f->output_data.x->size_hint_flags |= YNegative;
1168 }
1169 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1170 && CONSP (XCDR (top))
1171 && INTEGERP (XCAR (XCDR (top))))
1172 {
1173 toppos = XINT (XCAR (XCDR (top)));
1174 }
1175
1176
1177 /* Store the numeric value of the position. */
1178 f->output_data.x->top_pos = toppos;
1179 f->output_data.x->left_pos = leftpos;
1180
1181 f->output_data.x->win_gravity = NorthWestGravity;
1182
1183 /* Actually set that position, and convert to absolute. */
1184 x_set_offset (f, leftpos, toppos, -1);
1185 }
1186
1187 if ((!NILP (icon_left) || !NILP (icon_top))
1188 && ! (icon_left_no_change && icon_top_no_change))
1189 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1190 }
1191
1192 UNGCPRO;
1193 }
1194 561
1195 /* Store the screen positions of frame F into XPTR and YPTR. 562 /* Store the screen positions of frame F into XPTR and YPTR.
1196 These are the positions of the containing window manager window, 563 These are the positions of the containing window manager window,
1197 not Emacs's own window. */ 564 not Emacs's own window. */
1198 565
1243 win = wm_window; 610 win = wm_window;
1244 } 611 }
1245 612
1246 if (! had_errors) 613 if (! had_errors)
1247 { 614 {
1248 int ign; 615 unsigned int ign;
1249 Window child, rootw; 616 Window child, rootw;
1250 617
1251 /* Get the real coordinates for the WM window upper left corner */ 618 /* Get the real coordinates for the WM window upper left corner */
1252 XGetGeometry (FRAME_X_DISPLAY (f), win, 619 XGetGeometry (FRAME_X_DISPLAY (f), win,
1253 &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign); 620 &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
1290 /* From-position, to-position. */ 657 /* From-position, to-position. */
1291 real_x, real_y, &outer_x, &outer_y, 658 real_x, real_y, &outer_x, &outer_y,
1292 659
1293 /* Child of win. */ 660 /* Child of win. */
1294 &child); 661 &child);
1295 } 662 }
1296 663
1297 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f)); 664 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
1298 } 665 }
1299 666
1300 x_uncatch_errors (FRAME_X_DISPLAY (f), count); 667 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1301 668
1302 UNBLOCK_INPUT; 669 UNBLOCK_INPUT;
1303 670
1304 if (had_errors) return; 671 if (had_errors) return;
1305 672
1306 f->output_data.x->x_pixels_diff = -win_x; 673 f->x_pixels_diff = -win_x;
1307 f->output_data.x->y_pixels_diff = -win_y; 674 f->y_pixels_diff = -win_y;
1308 f->output_data.x->x_pixels_outer_diff = -outer_x; 675
1309 f->output_data.x->y_pixels_outer_diff = -outer_y; 676 FRAME_X_OUTPUT (f)->x_pixels_outer_diff = -outer_x;
677 FRAME_X_OUTPUT (f)->y_pixels_outer_diff = -outer_y;
1310 678
1311 *xptr = real_x; 679 *xptr = real_x;
1312 *yptr = real_y; 680 *yptr = real_y;
1313 } 681 }
1314 682
1315 /* Insert a description of internally-recorded parameters of frame X
1316 into the parameter alist *ALISTPTR that is to be given to the user.
1317 Only parameters that are specific to the X window system
1318 and whose values are not correctly recorded in the frame's
1319 param_alist need to be considered here. */
1320
1321 void
1322 x_report_frame_params (f, alistptr)
1323 struct frame *f;
1324 Lisp_Object *alistptr;
1325 {
1326 char buf[16];
1327 Lisp_Object tem;
1328
1329 /* Represent negative positions (off the top or left screen edge)
1330 in a way that Fmodify_frame_parameters will understand correctly. */
1331 XSETINT (tem, f->output_data.x->left_pos);
1332 if (f->output_data.x->left_pos >= 0)
1333 store_in_alist (alistptr, Qleft, tem);
1334 else
1335 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1336
1337 XSETINT (tem, f->output_data.x->top_pos);
1338 if (f->output_data.x->top_pos >= 0)
1339 store_in_alist (alistptr, Qtop, tem);
1340 else
1341 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1342
1343 store_in_alist (alistptr, Qborder_width,
1344 make_number (f->output_data.x->border_width));
1345 store_in_alist (alistptr, Qinternal_border_width,
1346 make_number (f->output_data.x->internal_border_width));
1347 store_in_alist (alistptr, Qleft_fringe,
1348 make_number (f->output_data.x->left_fringe_width));
1349 store_in_alist (alistptr, Qright_fringe,
1350 make_number (f->output_data.x->right_fringe_width));
1351 store_in_alist (alistptr, Qscroll_bar_width,
1352 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
1353 ? make_number (0)
1354 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
1355 ? make_number (FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
1356 /* nil means "use default width"
1357 for non-toolkit scroll bar.
1358 ruler-mode.el depends on this. */
1359 : Qnil));
1360 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1361 store_in_alist (alistptr, Qwindow_id,
1362 build_string (buf));
1363 #ifdef USE_X_TOOLKIT
1364 /* Tooltip frame may not have this widget. */
1365 if (f->output_data.x->widget)
1366 #endif
1367 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1368 store_in_alist (alistptr, Qouter_window_id,
1369 build_string (buf));
1370 store_in_alist (alistptr, Qicon_name, f->icon_name);
1371 FRAME_SAMPLE_VISIBILITY (f);
1372 store_in_alist (alistptr, Qvisibility,
1373 (FRAME_VISIBLE_P (f) ? Qt
1374 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1375 store_in_alist (alistptr, Qdisplay,
1376 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1377
1378 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1379 tem = Qnil;
1380 else
1381 XSETFASTINT (tem, f->output_data.x->parent_desc);
1382 store_in_alist (alistptr, Qparent_id, tem);
1383 }
1384 683
1385 684
1386 685
1387 /* Gamma-correct COLOR on frame F. */ 686 /* Gamma-correct COLOR on frame F. */
1388 687
1463 return 0; 762 return 0;
1464 } 763 }
1465 764
1466 765
1467 766
1468 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1469 the previous value of that parameter, NEW_VALUE is the new value. */
1470
1471 static void
1472 x_set_line_spacing (f, new_value, old_value)
1473 struct frame *f;
1474 Lisp_Object new_value, old_value;
1475 {
1476 if (NILP (new_value))
1477 f->extra_line_spacing = 0;
1478 else if (NATNUMP (new_value))
1479 f->extra_line_spacing = XFASTINT (new_value);
1480 else
1481 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1482 Fcons (new_value, Qnil)));
1483 if (FRAME_VISIBLE_P (f))
1484 redraw_frame (f);
1485 }
1486
1487
1488 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is 767 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1489 the previous value of that parameter, NEW_VALUE is the new value. 768 the previous value of that parameter, NEW_VALUE is the new value.
1490 See also the comment of wait_for_wm in struct x_output. */ 769 See also the comment of wait_for_wm in struct x_output. */
1491 770
1492 static void 771 static void
1495 Lisp_Object new_value, old_value; 774 Lisp_Object new_value, old_value;
1496 { 775 {
1497 f->output_data.x->wait_for_wm = !NILP (new_value); 776 f->output_data.x->wait_for_wm = !NILP (new_value);
1498 } 777 }
1499 778
1500 779 #ifdef USE_GTK
1501 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is 780
1502 the previous value of that parameter, NEW_VALUE is the new value. */ 781 /* Set icon from FILE for frame F. By using GTK functions the icon
1503 782 may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */
1504 static void 783
1505 x_set_fullscreen (f, new_value, old_value) 784 int
1506 struct frame *f; 785 xg_set_icon (f, file)
1507 Lisp_Object new_value, old_value; 786 FRAME_PTR f;
1508 { 787 Lisp_Object file;
1509 if (NILP (new_value)) 788 {
1510 f->output_data.x->want_fullscreen = FULLSCREEN_NONE; 789 struct gcpro gcpro1;
1511 else if (EQ (new_value, Qfullboth)) 790 int result = 0;
1512 f->output_data.x->want_fullscreen = FULLSCREEN_BOTH; 791 Lisp_Object found;
1513 else if (EQ (new_value, Qfullwidth)) 792
1514 f->output_data.x->want_fullscreen = FULLSCREEN_WIDTH; 793 GCPRO1 (found);
1515 else if (EQ (new_value, Qfullheight)) 794
1516 f->output_data.x->want_fullscreen = FULLSCREEN_HEIGHT; 795 found = x_find_image_file (file);
1517 } 796
1518 797 if (! NILP (found))
1519 798 {
1520 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is 799 GdkPixbuf *pixbuf;
1521 the previous value of that parameter, NEW_VALUE is the new 800 GError *err = NULL;
1522 value. */ 801 char *filename = (char *) SDATA (found);
1523 802 BLOCK_INPUT;
1524 static void 803
1525 x_set_screen_gamma (f, new_value, old_value) 804 pixbuf = gdk_pixbuf_new_from_file (filename, &err);
1526 struct frame *f; 805
1527 Lisp_Object new_value, old_value; 806 if (pixbuf)
1528 { 807 {
1529 if (NILP (new_value)) 808 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1530 f->gamma = 0; 809 pixbuf);
1531 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0) 810 g_object_unref (pixbuf);
1532 /* The value 0.4545 is the normal viewing gamma. */ 811
1533 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value)); 812 result = 1;
1534 else 813 }
1535 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"), 814 else
1536 Fcons (new_value, Qnil))); 815 g_error_free (err);
1537 816
1538 clear_face_cache (0); 817 UNBLOCK_INPUT;
1539 } 818 }
819
820 UNGCPRO;
821 return result;
822 }
823
824 int
825 xg_set_icon_from_xpm_data (f, data)
826 FRAME_PTR f;
827 char **data;
828 {
829 int result = 0;
830 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) data);
831
832 if (!pixbuf)
833 return 0;
834
835 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
836 g_object_unref (pixbuf);
837 return 1;
838 }
839 #endif /* USE_GTK */
1540 840
1541 841
1542 /* Functions called only from `x_set_frame_param' 842 /* Functions called only from `x_set_frame_param'
1543 to set individual parameters. 843 to set individual parameters.
1544 844
1638 struct frame *f; 938 struct frame *f;
1639 Lisp_Object arg, oldval; 939 Lisp_Object arg, oldval;
1640 { 940 {
1641 struct x_output *x = f->output_data.x; 941 struct x_output *x = f->output_data.x;
1642 Display *dpy = FRAME_X_DISPLAY (f); 942 Display *dpy = FRAME_X_DISPLAY (f);
1643 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor; 943 Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
1644 Cursor hourglass_cursor, horizontal_drag_cursor; 944 Cursor hourglass_cursor, horizontal_drag_cursor;
1645 int count; 945 int count;
1646 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); 946 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1647 unsigned long mask_color = x->background_pixel; 947 unsigned long mask_color = x->background_pixel;
1648 948
1688 } 988 }
1689 else 989 else
1690 hourglass_cursor = XCreateFontCursor (dpy, XC_watch); 990 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1691 x_check_errors (dpy, "bad hourglass pointer cursor: %s"); 991 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1692 992
1693 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1694 if (!NILP (Vx_mode_pointer_shape)) 993 if (!NILP (Vx_mode_pointer_shape))
1695 { 994 {
1696 CHECK_NUMBER (Vx_mode_pointer_shape); 995 CHECK_NUMBER (Vx_mode_pointer_shape);
1697 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape)); 996 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1698 } 997 }
1701 x_check_errors (dpy, "bad modeline pointer cursor: %s"); 1000 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1702 1001
1703 if (!NILP (Vx_sensitive_text_pointer_shape)) 1002 if (!NILP (Vx_sensitive_text_pointer_shape))
1704 { 1003 {
1705 CHECK_NUMBER (Vx_sensitive_text_pointer_shape); 1004 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1706 cross_cursor 1005 hand_cursor
1707 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape)); 1006 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1708 } 1007 }
1709 else 1008 else
1710 cross_cursor = XCreateFontCursor (dpy, XC_hand2); 1009 hand_cursor = XCreateFontCursor (dpy, XC_hand2);
1711 1010
1712 if (!NILP (Vx_window_horizontal_drag_shape)) 1011 if (!NILP (Vx_window_horizontal_drag_shape))
1713 { 1012 {
1714 CHECK_NUMBER (Vx_window_horizontal_drag_shape); 1013 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1715 horizontal_drag_cursor 1014 horizontal_drag_cursor
1732 x_query_color (f, &back_color); 1031 x_query_color (f, &back_color);
1733 1032
1734 XRecolorCursor (dpy, cursor, &fore_color, &back_color); 1033 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1735 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color); 1034 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1736 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color); 1035 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1737 XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color); 1036 XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
1738 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color); 1037 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1739 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color); 1038 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1740 } 1039 }
1741 1040
1742 if (FRAME_X_WINDOW (f) != 0) 1041 if (FRAME_X_WINDOW (f) != 0)
1760 if (mode_cursor != x->modeline_cursor 1059 if (mode_cursor != x->modeline_cursor
1761 && x->modeline_cursor != 0) 1060 && x->modeline_cursor != 0)
1762 XFreeCursor (dpy, f->output_data.x->modeline_cursor); 1061 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1763 x->modeline_cursor = mode_cursor; 1062 x->modeline_cursor = mode_cursor;
1764 1063
1765 if (cross_cursor != x->cross_cursor 1064 if (hand_cursor != x->hand_cursor
1766 && x->cross_cursor != 0) 1065 && x->hand_cursor != 0)
1767 XFreeCursor (dpy, x->cross_cursor); 1066 XFreeCursor (dpy, x->hand_cursor);
1768 x->cross_cursor = cross_cursor; 1067 x->hand_cursor = hand_cursor;
1769 1068
1770 if (horizontal_drag_cursor != x->horizontal_drag_cursor 1069 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1771 && x->horizontal_drag_cursor != 0) 1070 && x->horizontal_drag_cursor != 0)
1772 XFreeCursor (dpy, x->horizontal_drag_cursor); 1071 XFreeCursor (dpy, x->horizontal_drag_cursor);
1773 x->horizontal_drag_cursor = horizontal_drag_cursor; 1072 x->horizontal_drag_cursor = horizontal_drag_cursor;
1845 } 1144 }
1846 1145
1847 update_face_from_frame_parameter (f, Qcursor_color, arg); 1146 update_face_from_frame_parameter (f, Qcursor_color, arg);
1848 } 1147 }
1849 1148
1149 /* Set the border-color of frame F to pixel value PIX.
1150 Note that this does not fully take effect if done before
1151 F has an x-window. */
1152
1153 void
1154 x_set_border_pixel (f, pix)
1155 struct frame *f;
1156 int pix;
1157 {
1158 unload_color (f, f->output_data.x->border_pixel);
1159 f->output_data.x->border_pixel = pix;
1160
1161 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1162 {
1163 BLOCK_INPUT;
1164 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1165 (unsigned long)pix);
1166 UNBLOCK_INPUT;
1167
1168 if (FRAME_VISIBLE_P (f))
1169 redraw_frame (f);
1170 }
1171 }
1172
1850 /* Set the border-color of frame F to value described by ARG. 1173 /* Set the border-color of frame F to value described by ARG.
1851 ARG can be a string naming a color. 1174 ARG can be a string naming a color.
1852 The border-color is used for the border that is drawn by the X server. 1175 The border-color is used for the border that is drawn by the X server.
1853 Note that this does not fully take effect if done before 1176 Note that this does not fully take effect if done before
1854 F has an x-window; it must be redone when the window is created. 1177 F has an x-window; it must be redone when the window is created.
1868 CHECK_STRING (arg); 1191 CHECK_STRING (arg);
1869 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); 1192 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1870 x_set_border_pixel (f, pix); 1193 x_set_border_pixel (f, pix);
1871 update_face_from_frame_parameter (f, Qborder_color, arg); 1194 update_face_from_frame_parameter (f, Qborder_color, arg);
1872 } 1195 }
1873
1874 /* Set the border-color of frame F to pixel value PIX.
1875 Note that this does not fully take effect if done before
1876 F has an x-window. */
1877
1878 void
1879 x_set_border_pixel (f, pix)
1880 struct frame *f;
1881 int pix;
1882 {
1883 unload_color (f, f->output_data.x->border_pixel);
1884 f->output_data.x->border_pixel = pix;
1885
1886 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1887 {
1888 BLOCK_INPUT;
1889 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1890 (unsigned long)pix);
1891 UNBLOCK_INPUT;
1892
1893 if (FRAME_VISIBLE_P (f))
1894 redraw_frame (f);
1895 }
1896 }
1897
1898 1196
1899 1197
1900 void 1198 void
1901 x_set_cursor_type (f, arg, oldval) 1199 x_set_cursor_type (f, arg, oldval)
1902 FRAME_PTR f; 1200 FRAME_PTR f;
1940 1238
1941 XFlush (FRAME_X_DISPLAY (f)); 1239 XFlush (FRAME_X_DISPLAY (f));
1942 UNBLOCK_INPUT; 1240 UNBLOCK_INPUT;
1943 } 1241 }
1944 1242
1945 /* Return non-nil if frame F wants a bitmap icon. */
1946
1947 Lisp_Object
1948 x_icon_type (f)
1949 FRAME_PTR f;
1950 {
1951 Lisp_Object tem;
1952
1953 tem = assq_no_quit (Qicon_type, f->param_alist);
1954 if (CONSP (tem))
1955 return XCDR (tem);
1956 else
1957 return Qnil;
1958 }
1959
1960 void 1243 void
1961 x_set_icon_name (f, arg, oldval) 1244 x_set_icon_name (f, arg, oldval)
1962 struct frame *f; 1245 struct frame *f;
1963 Lisp_Object arg, oldval; 1246 Lisp_Object arg, oldval;
1964 { 1247 {
1993 } 1276 }
1994 1277
1995 XFlush (FRAME_X_DISPLAY (f)); 1278 XFlush (FRAME_X_DISPLAY (f));
1996 UNBLOCK_INPUT; 1279 UNBLOCK_INPUT;
1997 } 1280 }
1281
1998 1282
1999 void
2000 x_set_font (f, arg, oldval)
2001 struct frame *f;
2002 Lisp_Object arg, oldval;
2003 {
2004 Lisp_Object result;
2005 Lisp_Object fontset_name;
2006 Lisp_Object frame;
2007 int old_fontset = f->output_data.x->fontset;
2008
2009 CHECK_STRING (arg);
2010
2011 fontset_name = Fquery_fontset (arg, Qnil);
2012
2013 BLOCK_INPUT;
2014 result = (STRINGP (fontset_name)
2015 ? x_new_fontset (f, SDATA (fontset_name))
2016 : x_new_font (f, SDATA (arg)));
2017 UNBLOCK_INPUT;
2018
2019 if (EQ (result, Qnil))
2020 error ("Font `%s' is not defined", SDATA (arg));
2021 else if (EQ (result, Qt))
2022 error ("The characters of the given font have varying widths");
2023 else if (STRINGP (result))
2024 {
2025 if (STRINGP (fontset_name))
2026 {
2027 /* Fontset names are built from ASCII font names, so the
2028 names may be equal despite there was a change. */
2029 if (old_fontset == f->output_data.x->fontset)
2030 return;
2031 }
2032 else if (!NILP (Fequal (result, oldval)))
2033 return;
2034
2035 store_frame_param (f, Qfont, result);
2036 recompute_basic_faces (f);
2037 }
2038 else
2039 abort ();
2040
2041 do_pending_window_change (0);
2042
2043 /* Don't call `face-set-after-frame-default' when faces haven't been
2044 initialized yet. This is the case when called from
2045 Fx_create_frame. In that case, the X widget or window doesn't
2046 exist either, and we can end up in x_report_frame_params with a
2047 null widget which gives a segfault. */
2048 if (FRAME_FACE_CACHE (f))
2049 {
2050 XSETFRAME (frame, f);
2051 call1 (Qface_set_after_frame_default, frame);
2052 }
2053 }
2054
2055 static void
2056 x_set_fringe_width (f, new_value, old_value)
2057 struct frame *f;
2058 Lisp_Object new_value, old_value;
2059 {
2060 x_compute_fringe_widths (f, 1);
2061 }
2062
2063 void
2064 x_set_border_width (f, arg, oldval)
2065 struct frame *f;
2066 Lisp_Object arg, oldval;
2067 {
2068 CHECK_NUMBER (arg);
2069
2070 if (XINT (arg) == f->output_data.x->border_width)
2071 return;
2072
2073 if (FRAME_X_WINDOW (f) != 0)
2074 error ("Cannot change the border width of a window");
2075
2076 f->output_data.x->border_width = XINT (arg);
2077 }
2078
2079 void
2080 x_set_internal_border_width (f, arg, oldval)
2081 struct frame *f;
2082 Lisp_Object arg, oldval;
2083 {
2084 int old = f->output_data.x->internal_border_width;
2085
2086 CHECK_NUMBER (arg);
2087 f->output_data.x->internal_border_width = XINT (arg);
2088 if (f->output_data.x->internal_border_width < 0)
2089 f->output_data.x->internal_border_width = 0;
2090
2091 #ifdef USE_X_TOOLKIT
2092 if (f->output_data.x->edit_widget)
2093 widget_store_internal_border (f->output_data.x->edit_widget);
2094 #endif
2095
2096 if (f->output_data.x->internal_border_width == old)
2097 return;
2098
2099 if (FRAME_X_WINDOW (f) != 0)
2100 {
2101 x_set_window_size (f, 0, f->width, f->height);
2102 SET_FRAME_GARBAGED (f);
2103 do_pending_window_change (0);
2104 }
2105 else
2106 SET_FRAME_GARBAGED (f);
2107 }
2108
2109 void
2110 x_set_visibility (f, value, oldval)
2111 struct frame *f;
2112 Lisp_Object value, oldval;
2113 {
2114 Lisp_Object frame;
2115 XSETFRAME (frame, f);
2116
2117 if (NILP (value))
2118 Fmake_frame_invisible (frame, Qt);
2119 else if (EQ (value, Qicon))
2120 Ficonify_frame (frame);
2121 else
2122 Fmake_frame_visible (frame);
2123 }
2124
2125
2126 /* Change window heights in windows rooted in WINDOW by N lines. */
2127
2128 static void
2129 x_change_window_heights (window, n)
2130 Lisp_Object window;
2131 int n;
2132 {
2133 struct window *w = XWINDOW (window);
2134
2135 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2136 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2137
2138 if (INTEGERP (w->orig_top))
2139 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2140 if (INTEGERP (w->orig_height))
2141 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2142
2143 /* Handle just the top child in a vertical split. */
2144 if (!NILP (w->vchild))
2145 x_change_window_heights (w->vchild, n);
2146
2147 /* Adjust all children in a horizontal split. */
2148 for (window = w->hchild; !NILP (window); window = w->next)
2149 {
2150 w = XWINDOW (window);
2151 x_change_window_heights (window, n);
2152 }
2153 }
2154
2155 void 1283 void
2156 x_set_menu_bar_lines (f, value, oldval) 1284 x_set_menu_bar_lines (f, value, oldval)
2157 struct frame *f; 1285 struct frame *f;
2158 Lisp_Object value, oldval; 1286 Lisp_Object value, oldval;
2159 { 1287 {
2160 int nlines; 1288 int nlines;
2161 #ifndef USE_X_TOOLKIT 1289 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
2162 int olines = FRAME_MENU_BAR_LINES (f); 1290 int olines = FRAME_MENU_BAR_LINES (f);
2163 #endif 1291 #endif
2164 1292
2165 /* Right now, menu bars don't work properly in minibuf-only frames; 1293 /* Right now, menu bars don't work properly in minibuf-only frames;
2166 most of the commands try to apply themselves to the minibuffer 1294 most of the commands try to apply themselves to the minibuffer
2194 if (FRAME_X_P (f)) 1322 if (FRAME_X_P (f))
2195 f->output_data.x->menubar_widget = 0; 1323 f->output_data.x->menubar_widget = 0;
2196 } 1324 }
2197 #else /* not USE_X_TOOLKIT && not USE_GTK */ 1325 #else /* not USE_X_TOOLKIT && not USE_GTK */
2198 FRAME_MENU_BAR_LINES (f) = nlines; 1326 FRAME_MENU_BAR_LINES (f) = nlines;
2199 x_change_window_heights (f->root_window, nlines - olines); 1327 change_window_heights (f->root_window, nlines - olines);
2200 #endif /* not USE_X_TOOLKIT */ 1328 #endif /* not USE_X_TOOLKIT */
2201 adjust_glyphs (f); 1329 adjust_glyphs (f);
2202 } 1330 }
2203 1331
2204 1332
2251 1379
2252 delta = nlines - FRAME_TOOL_BAR_LINES (f); 1380 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2253 1381
2254 /* Don't resize the tool-bar to more than we have room for. */ 1382 /* Don't resize the tool-bar to more than we have room for. */
2255 root_window = FRAME_ROOT_WINDOW (f); 1383 root_window = FRAME_ROOT_WINDOW (f);
2256 root_height = XINT (XWINDOW (root_window)->height); 1384 root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
2257 if (root_height - delta < 1) 1385 if (root_height - delta < 1)
2258 { 1386 {
2259 delta = root_height - 1; 1387 delta = root_height - 1;
2260 nlines = FRAME_TOOL_BAR_LINES (f) + delta; 1388 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2261 } 1389 }
2262 1390
2263 FRAME_TOOL_BAR_LINES (f) = nlines; 1391 FRAME_TOOL_BAR_LINES (f) = nlines;
2264 x_change_window_heights (root_window, delta); 1392 change_window_heights (root_window, delta);
2265 adjust_glyphs (f); 1393 adjust_glyphs (f);
2266 1394
2267 /* We also have to make sure that the internal border at the top of 1395 /* We also have to make sure that the internal border at the top of
2268 the frame, below the menu bar or tool bar, is redrawn when the 1396 the frame, below the menu bar or tool bar, is redrawn when the
2269 tool bar disappears. This is so because the internal border is 1397 tool bar disappears. This is so because the internal border is
2282 has to be cleared. It was formerly part of the display 1410 has to be cleared. It was formerly part of the display
2283 of the larger tool bar, and updating windows won't clear it. */ 1411 of the larger tool bar, and updating windows won't clear it. */
2284 if (delta < 0) 1412 if (delta < 0)
2285 { 1413 {
2286 int height = FRAME_INTERNAL_BORDER_WIDTH (f); 1414 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2287 int width = PIXEL_WIDTH (f); 1415 int width = FRAME_PIXEL_WIDTH (f);
2288 int y = nlines * CANON_Y_UNIT (f); 1416 int y = nlines * FRAME_LINE_HEIGHT (f);
2289 1417
2290 BLOCK_INPUT; 1418 /* height can be zero here. */
2291 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 1419 if (height > 0 && width > 0)
2292 0, y, width, height, False); 1420 {
2293 UNBLOCK_INPUT; 1421 BLOCK_INPUT;
1422 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1423 0, y, width, height, False);
1424 UNBLOCK_INPUT;
1425 }
2294 1426
2295 if (WINDOWP (f->tool_bar_window)) 1427 if (WINDOWP (f->tool_bar_window))
2296 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); 1428 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2297 } 1429 }
2298 } 1430 }
2399 If the text contains only ASCII and Latin-1, store 1 in *STRING_P, 1531 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2400 which means that the `encoding' of the result can be `STRING'. 1532 which means that the `encoding' of the result can be `STRING'.
2401 Otherwise store 0 in *STRINGP, which means that the `encoding' of 1533 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2402 the result should be `COMPOUND_TEXT'. */ 1534 the result should be `COMPOUND_TEXT'. */
2403 1535
2404 unsigned char * 1536 static unsigned char *
2405 x_encode_text (string, coding_system, selectionp, text_bytes, stringp) 1537 x_encode_text (string, coding_system, selectionp, text_bytes, stringp, freep)
2406 Lisp_Object string, coding_system; 1538 Lisp_Object string, coding_system;
2407 int *text_bytes, *stringp; 1539 int *text_bytes, *stringp;
2408 int selectionp; 1540 int selectionp;
1541 int *freep;
2409 { 1542 {
2410 unsigned char *str = SDATA (string); 1543 unsigned char *str = SDATA (string);
2411 int chars = SCHARS (string); 1544 int chars = SCHARS (string);
2412 int bytes = SBYTES (string); 1545 int bytes = SBYTES (string);
2413 int charset_info; 1546 int charset_info;
2420 if (charset_info == 0) 1553 if (charset_info == 0)
2421 { 1554 {
2422 /* No multibyte character in OBJ. We need not encode it. */ 1555 /* No multibyte character in OBJ. We need not encode it. */
2423 *text_bytes = bytes; 1556 *text_bytes = bytes;
2424 *stringp = 1; 1557 *stringp = 1;
1558 *freep = 0;
2425 return str; 1559 return str;
2426 } 1560 }
2427 1561
2428 setup_coding_system (coding_system, &coding); 1562 setup_coding_system (coding_system, &coding);
2429 if (selectionp 1563 if (selectionp
2447 encode_coding (&coding, str, buf, bytes, bufsize); 1581 encode_coding (&coding, str, buf, bytes, bufsize);
2448 *text_bytes = coding.produced; 1582 *text_bytes = coding.produced;
2449 *stringp = (charset_info == 1 1583 *stringp = (charset_info == 1
2450 || (!EQ (coding_system, Qcompound_text) 1584 || (!EQ (coding_system, Qcompound_text)
2451 && !EQ (coding_system, Qcompound_text_with_extensions))); 1585 && !EQ (coding_system, Qcompound_text_with_extensions)));
1586 *freep = 1;
2452 return buf; 1587 return buf;
2453 } 1588 }
2454 1589
2455 1590
2456 /* Change the name of frame F to NAME. If NAME is nil, set F's name to 1591 /* Set the WM name to NAME for frame F. Also set the icon name.
2457 x_id_name. 1592 If the frame already has an icon name, use that, otherwise set the
2458 1593 icon name to NAME. */
2459 If EXPLICIT is non-zero, that indicates that lisp code is setting the 1594
2460 name; if NAME is a string, set F's name to NAME and set 1595 static void
2461 F->explicit_name; if NAME is Qnil, then clear F->explicit_name. 1596 x_set_name_internal (f, name)
2462 1597 FRAME_PTR f;
2463 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2464 suggesting a new name, which lisp code should override; if
2465 F->explicit_name is set, ignore the new name; otherwise, set it. */
2466
2467 void
2468 x_set_name (f, name, explicit)
2469 struct frame *f;
2470 Lisp_Object name; 1598 Lisp_Object name;
2471 int explicit; 1599 {
2472 {
2473 /* Make sure that requests from lisp code override requests from
2474 Emacs redisplay code. */
2475 if (explicit)
2476 {
2477 /* If we're switching from explicit to implicit, we had better
2478 update the mode lines and thereby update the title. */
2479 if (f->explicit_name && NILP (name))
2480 update_mode_lines = 1;
2481
2482 f->explicit_name = ! NILP (name);
2483 }
2484 else if (f->explicit_name)
2485 return;
2486
2487 /* If NAME is nil, set the name to the x_id_name. */
2488 if (NILP (name))
2489 {
2490 /* Check for no change needed in this very common case
2491 before we do any consing. */
2492 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2493 SDATA (f->name)))
2494 return;
2495 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2496 }
2497 else
2498 CHECK_STRING (name);
2499
2500 /* Don't change the name if it's already NAME. */
2501 if (! NILP (Fstring_equal (name, f->name)))
2502 return;
2503
2504 f->name = name;
2505
2506 /* For setting the frame title, the title parameter should override
2507 the name parameter. */
2508 if (! NILP (f->title))
2509 name = f->title;
2510
2511 if (FRAME_X_WINDOW (f)) 1600 if (FRAME_X_WINDOW (f))
2512 { 1601 {
2513 BLOCK_INPUT; 1602 BLOCK_INPUT;
2514 #ifdef HAVE_X11R4 1603 #ifdef HAVE_X11R4
2515 { 1604 {
2516 XTextProperty text, icon; 1605 XTextProperty text, icon;
2517 int bytes, stringp; 1606 int bytes, stringp;
1607 int do_free_icon_value = 0, do_free_text_value = 0;
2518 Lisp_Object coding_system; 1608 Lisp_Object coding_system;
2519 1609
1610 coding_system = Qcompound_text;
2520 /* Note: Encoding strategy 1611 /* Note: Encoding strategy
2521 1612
2522 We encode NAME by compound-text and use "COMPOUND-TEXT" in 1613 We encode NAME by compound-text and use "COMPOUND-TEXT" in
2523 text.encoding. But, there are non-internationalized window 1614 text.encoding. But, there are non-internationalized window
2524 managers which don't support that encoding. So, if NAME 1615 managers which don't support that encoding. So, if NAME
2525 contains only ASCII and 8859-1 characters, encode it by 1616 contains only ASCII and 8859-1 characters, encode it by
2526 iso-latin-1, and use "STRING" in text.encoding hoping that 1617 iso-latin-1, and use "STRING" in text.encoding hoping that
2527 such window manager at least analize this format correctly, 1618 such window managers at least analyze this format correctly,
2528 i.e. treat 8-bit bytes as 8859-1 characters. 1619 i.e. treat 8-bit bytes as 8859-1 characters.
2529 1620
2530 We may also be able to use "UTF8_STRING" in text.encoding 1621 We may also be able to use "UTF8_STRING" in text.encoding
2531 in the feature which can encode all Unicode characters. 1622 in the future which can encode all Unicode characters.
2532 But, for the moment, there's no way to know that the 1623 But, for the moment, there's no way to know that the
2533 current window manager supports it or not. */ 1624 current window manager supports it or not. */
2534 coding_system = Qcompound_text; 1625 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp,
2535 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp); 1626 &do_free_text_value);
2536 text.encoding = (stringp ? XA_STRING 1627 text.encoding = (stringp ? XA_STRING
2537 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); 1628 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2538 text.format = 8; 1629 text.format = 8;
2539 text.nitems = bytes; 1630 text.nitems = bytes;
2540 1631
2544 } 1635 }
2545 else 1636 else
2546 { 1637 {
2547 /* See the above comment "Note: Encoding strategy". */ 1638 /* See the above comment "Note: Encoding strategy". */
2548 icon.value = x_encode_text (f->icon_name, coding_system, 0, 1639 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2549 &bytes, &stringp); 1640 &bytes, &stringp, &do_free_icon_value);
2550 icon.encoding = (stringp ? XA_STRING 1641 icon.encoding = (stringp ? XA_STRING
2551 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); 1642 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2552 icon.format = 8; 1643 icon.format = 8;
2553 icon.nitems = bytes; 1644 icon.nitems = bytes;
2554 } 1645 }
1646
2555 #ifdef USE_GTK 1647 #ifdef USE_GTK
2556 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), 1648 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
2557 SDATA (name)); 1649 (char *) SDATA (ENCODE_UTF_8 (name)));
2558 #else /* not USE_GTK */ 1650 #else /* not USE_GTK */
2559 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text); 1651 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
2560 #endif /* not USE_GTK */ 1652 #endif /* not USE_GTK */
2561 1653
2562 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon); 1654 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
2563 1655
2564 if (!NILP (f->icon_name) 1656 if (do_free_icon_value)
2565 && icon.value != (unsigned char *) SDATA (f->icon_name))
2566 xfree (icon.value); 1657 xfree (icon.value);
2567 if (text.value != (unsigned char *) SDATA (name)) 1658 if (do_free_text_value)
2568 xfree (text.value); 1659 xfree (text.value);
2569 } 1660 }
2570 #else /* not HAVE_X11R4 */ 1661 #else /* not HAVE_X11R4 */
2571 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 1662 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2572 SDATA (name)); 1663 SDATA (name));
2575 #endif /* not HAVE_X11R4 */ 1666 #endif /* not HAVE_X11R4 */
2576 UNBLOCK_INPUT; 1667 UNBLOCK_INPUT;
2577 } 1668 }
2578 } 1669 }
2579 1670
1671 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1672 x_id_name.
1673
1674 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1675 name; if NAME is a string, set F's name to NAME and set
1676 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1677
1678 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1679 suggesting a new name, which lisp code should override; if
1680 F->explicit_name is set, ignore the new name; otherwise, set it. */
1681
1682 void
1683 x_set_name (f, name, explicit)
1684 struct frame *f;
1685 Lisp_Object name;
1686 int explicit;
1687 {
1688 /* Make sure that requests from lisp code override requests from
1689 Emacs redisplay code. */
1690 if (explicit)
1691 {
1692 /* If we're switching from explicit to implicit, we had better
1693 update the mode lines and thereby update the title. */
1694 if (f->explicit_name && NILP (name))
1695 update_mode_lines = 1;
1696
1697 f->explicit_name = ! NILP (name);
1698 }
1699 else if (f->explicit_name)
1700 return;
1701
1702 /* If NAME is nil, set the name to the x_id_name. */
1703 if (NILP (name))
1704 {
1705 /* Check for no change needed in this very common case
1706 before we do any consing. */
1707 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1708 SDATA (f->name)))
1709 return;
1710 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
1711 }
1712 else
1713 CHECK_STRING (name);
1714
1715 /* Don't change the name if it's already NAME. */
1716 if (! NILP (Fstring_equal (name, f->name)))
1717 return;
1718
1719 f->name = name;
1720
1721 /* For setting the frame title, the title parameter should override
1722 the name parameter. */
1723 if (! NILP (f->title))
1724 name = f->title;
1725
1726 x_set_name_internal (f, name);
1727 }
1728
2580 /* This function should be called when the user's lisp code has 1729 /* This function should be called when the user's lisp code has
2581 specified a name for the frame; the name will override any set by the 1730 specified a name for the frame; the name will override any set by the
2582 redisplay code. */ 1731 redisplay code. */
2583 void 1732 void
2584 x_explicitly_set_name (f, arg, oldval) 1733 x_explicitly_set_name (f, arg, oldval)
2626 if (NILP (name)) 1775 if (NILP (name))
2627 name = f->name; 1776 name = f->name;
2628 else 1777 else
2629 CHECK_STRING (name); 1778 CHECK_STRING (name);
2630 1779
2631 if (FRAME_X_WINDOW (f)) 1780 x_set_name_internal (f, name);
2632 { 1781 }
2633 BLOCK_INPUT; 1782
2634 #ifdef HAVE_X11R4 1783 void
2635 { 1784 x_set_scroll_bar_default_width (f)
2636 XTextProperty text, icon; 1785 struct frame *f;
2637 int bytes, stringp; 1786 {
2638 Lisp_Object coding_system; 1787 int wid = FRAME_COLUMN_WIDTH (f);
2639 1788
2640 coding_system = Qcompound_text; 1789 #ifdef USE_TOOLKIT_SCROLL_BARS
2641 /* See the comment "Note: Encoding strategy" in x_set_name. */ 1790 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2642 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp); 1791 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2643 text.encoding = (stringp ? XA_STRING 1792 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2644 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); 1793 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = width;
2645 text.format = 8; 1794 #else
2646 text.nitems = bytes; 1795 /* Make the actual width at least 14 pixels and a multiple of a
2647 1796 character width. */
2648 if (NILP (f->icon_name)) 1797 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2649 { 1798
2650 icon = text; 1799 /* Use all of that space (aside from required margins) for the
2651 } 1800 scroll bar. */
2652 else 1801 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
2653 { 1802 #endif
2654 /* See the comment "Note: Encoding strategy" in x_set_name. */ 1803 }
2655 icon.value = x_encode_text (f->icon_name, coding_system, 0, 1804
2656 &bytes, &stringp);
2657 icon.encoding = (stringp ? XA_STRING
2658 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2659 icon.format = 8;
2660 icon.nitems = bytes;
2661 }
2662
2663 #ifdef USE_GTK
2664 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
2665 SDATA (name));
2666 #else /* not USE_GTK */
2667 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
2668 #endif /* not USE_GTK */
2669
2670 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
2671 &icon);
2672
2673 if (!NILP (f->icon_name)
2674 && icon.value != (unsigned char *) SDATA (f->icon_name))
2675 xfree (icon.value);
2676 if (text.value != (unsigned char *) SDATA (name))
2677 xfree (text.value);
2678 }
2679 #else /* not HAVE_X11R4 */
2680 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2681 SDATA (name));
2682 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2683 SDATA (name));
2684 #endif /* not HAVE_X11R4 */
2685 UNBLOCK_INPUT;
2686 }
2687 }
2688 1805
2689 void
2690 x_set_autoraise (f, arg, oldval)
2691 struct frame *f;
2692 Lisp_Object arg, oldval;
2693 {
2694 f->auto_raise = !EQ (Qnil, arg);
2695 }
2696
2697 void
2698 x_set_autolower (f, arg, oldval)
2699 struct frame *f;
2700 Lisp_Object arg, oldval;
2701 {
2702 f->auto_lower = !EQ (Qnil, arg);
2703 }
2704
2705 void
2706 x_set_unsplittable (f, arg, oldval)
2707 struct frame *f;
2708 Lisp_Object arg, oldval;
2709 {
2710 f->no_split = !NILP (arg);
2711 }
2712
2713 void
2714 x_set_vertical_scroll_bars (f, arg, oldval)
2715 struct frame *f;
2716 Lisp_Object arg, oldval;
2717 {
2718 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2719 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2720 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2721 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2722 {
2723 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2724 = (NILP (arg)
2725 ? vertical_scroll_bar_none
2726 : EQ (Qright, arg)
2727 ? vertical_scroll_bar_right
2728 : vertical_scroll_bar_left);
2729
2730 /* We set this parameter before creating the X window for the
2731 frame, so we can get the geometry right from the start.
2732 However, if the window hasn't been created yet, we shouldn't
2733 call x_set_window_size. */
2734 if (FRAME_X_WINDOW (f))
2735 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2736 do_pending_window_change (0);
2737 }
2738 }
2739
2740 void
2741 x_set_scroll_bar_width (f, arg, oldval)
2742 struct frame *f;
2743 Lisp_Object arg, oldval;
2744 {
2745 int wid = FONT_WIDTH (f->output_data.x->font);
2746
2747 if (NILP (arg))
2748 {
2749 #ifdef USE_TOOLKIT_SCROLL_BARS
2750 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2751 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2752 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2753 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2754 #else
2755 /* Make the actual width at least 14 pixels and a multiple of a
2756 character width. */
2757 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2758
2759 /* Use all of that space (aside from required margins) for the
2760 scroll bar. */
2761 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2762 #endif
2763
2764 if (FRAME_X_WINDOW (f))
2765 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2766 do_pending_window_change (0);
2767 }
2768 else if (INTEGERP (arg) && XINT (arg) > 0
2769 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2770 {
2771 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2772 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2773
2774 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2775 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2776 if (FRAME_X_WINDOW (f))
2777 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2778 }
2779
2780 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2781 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2782 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2783 }
2784
2785
2786
2787 /* Subroutines of creating an X frame. */
2788
2789 /* Make sure that Vx_resource_name is set to a reasonable value.
2790 Fix it up, or set it to `emacs' if it is too hopeless. */
2791
2792 static void
2793 validate_x_resource_name ()
2794 {
2795 int len = 0;
2796 /* Number of valid characters in the resource name. */
2797 int good_count = 0;
2798 /* Number of invalid characters in the resource name. */
2799 int bad_count = 0;
2800 Lisp_Object new;
2801 int i;
2802
2803 if (!STRINGP (Vx_resource_class))
2804 Vx_resource_class = build_string (EMACS_CLASS);
2805
2806 if (STRINGP (Vx_resource_name))
2807 {
2808 unsigned char *p = SDATA (Vx_resource_name);
2809 int i;
2810
2811 len = SBYTES (Vx_resource_name);
2812
2813 /* Only letters, digits, - and _ are valid in resource names.
2814 Count the valid characters and count the invalid ones. */
2815 for (i = 0; i < len; i++)
2816 {
2817 int c = p[i];
2818 if (! ((c >= 'a' && c <= 'z')
2819 || (c >= 'A' && c <= 'Z')
2820 || (c >= '0' && c <= '9')
2821 || c == '-' || c == '_'))
2822 bad_count++;
2823 else
2824 good_count++;
2825 }
2826 }
2827 else
2828 /* Not a string => completely invalid. */
2829 bad_count = 5, good_count = 0;
2830
2831 /* If name is valid already, return. */
2832 if (bad_count == 0)
2833 return;
2834
2835 /* If name is entirely invalid, or nearly so, use `emacs'. */
2836 if (good_count == 0
2837 || (good_count == 1 && bad_count > 0))
2838 {
2839 Vx_resource_name = build_string ("emacs");
2840 return;
2841 }
2842
2843 /* Name is partly valid. Copy it and replace the invalid characters
2844 with underscores. */
2845
2846 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2847
2848 for (i = 0; i < len; i++)
2849 {
2850 int c = SREF (new, i);
2851 if (! ((c >= 'a' && c <= 'z')
2852 || (c >= 'A' && c <= 'Z')
2853 || (c >= '0' && c <= '9')
2854 || c == '-' || c == '_'))
2855 SSET (new, i, '_');
2856 }
2857 }
2858
2859
2860 extern char *x_get_string_resource ();
2861
2862 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2863 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2864 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2865 class, where INSTANCE is the name under which Emacs was invoked, or
2866 the name specified by the `-name' or `-rn' command-line arguments.
2867
2868 The optional arguments COMPONENT and SUBCLASS add to the key and the
2869 class, respectively. You must specify both of them or neither.
2870 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2871 and the class is `Emacs.CLASS.SUBCLASS'. */)
2872 (attribute, class, component, subclass)
2873 Lisp_Object attribute, class, component, subclass;
2874 {
2875 register char *value;
2876 char *name_key;
2877 char *class_key;
2878
2879 check_x ();
2880
2881 CHECK_STRING (attribute);
2882 CHECK_STRING (class);
2883
2884 if (!NILP (component))
2885 CHECK_STRING (component);
2886 if (!NILP (subclass))
2887 CHECK_STRING (subclass);
2888 if (NILP (component) != NILP (subclass))
2889 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2890
2891 validate_x_resource_name ();
2892
2893 /* Allocate space for the components, the dots which separate them,
2894 and the final '\0'. Make them big enough for the worst case. */
2895 name_key = (char *) alloca (SBYTES (Vx_resource_name)
2896 + (STRINGP (component)
2897 ? SBYTES (component) : 0)
2898 + SBYTES (attribute)
2899 + 3);
2900
2901 class_key = (char *) alloca (SBYTES (Vx_resource_class)
2902 + SBYTES (class)
2903 + (STRINGP (subclass)
2904 ? SBYTES (subclass) : 0)
2905 + 3);
2906
2907 /* Start with emacs.FRAMENAME for the name (the specific one)
2908 and with `Emacs' for the class key (the general one). */
2909 strcpy (name_key, SDATA (Vx_resource_name));
2910 strcpy (class_key, SDATA (Vx_resource_class));
2911
2912 strcat (class_key, ".");
2913 strcat (class_key, SDATA (class));
2914
2915 if (!NILP (component))
2916 {
2917 strcat (class_key, ".");
2918 strcat (class_key, SDATA (subclass));
2919
2920 strcat (name_key, ".");
2921 strcat (name_key, SDATA (component));
2922 }
2923
2924 strcat (name_key, ".");
2925 strcat (name_key, SDATA (attribute));
2926
2927 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2928 name_key, class_key);
2929
2930 if (value != (char *) 0)
2931 return build_string (value);
2932 else
2933 return Qnil;
2934 }
2935
2936 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2937
2938 Lisp_Object
2939 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2940 struct x_display_info *dpyinfo;
2941 Lisp_Object attribute, class, component, subclass;
2942 {
2943 register char *value;
2944 char *name_key;
2945 char *class_key;
2946
2947 CHECK_STRING (attribute);
2948 CHECK_STRING (class);
2949
2950 if (!NILP (component))
2951 CHECK_STRING (component);
2952 if (!NILP (subclass))
2953 CHECK_STRING (subclass);
2954 if (NILP (component) != NILP (subclass))
2955 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2956
2957 validate_x_resource_name ();
2958
2959 /* Allocate space for the components, the dots which separate them,
2960 and the final '\0'. Make them big enough for the worst case. */
2961 name_key = (char *) alloca (SBYTES (Vx_resource_name)
2962 + (STRINGP (component)
2963 ? SBYTES (component) : 0)
2964 + SBYTES (attribute)
2965 + 3);
2966
2967 class_key = (char *) alloca (SBYTES (Vx_resource_class)
2968 + SBYTES (class)
2969 + (STRINGP (subclass)
2970 ? SBYTES (subclass) : 0)
2971 + 3);
2972
2973 /* Start with emacs.FRAMENAME for the name (the specific one)
2974 and with `Emacs' for the class key (the general one). */
2975 strcpy (name_key, SDATA (Vx_resource_name));
2976 strcpy (class_key, SDATA (Vx_resource_class));
2977
2978 strcat (class_key, ".");
2979 strcat (class_key, SDATA (class));
2980
2981 if (!NILP (component))
2982 {
2983 strcat (class_key, ".");
2984 strcat (class_key, SDATA (subclass));
2985
2986 strcat (name_key, ".");
2987 strcat (name_key, SDATA (component));
2988 }
2989
2990 strcat (name_key, ".");
2991 strcat (name_key, SDATA (attribute));
2992
2993 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2994
2995 if (value != (char *) 0)
2996 return build_string (value);
2997 else
2998 return Qnil;
2999 }
3000
3001 /* Used when C code wants a resource value. */
3002
3003 char *
3004 x_get_resource_string (attribute, class)
3005 char *attribute, *class;
3006 {
3007 char *name_key;
3008 char *class_key;
3009 struct frame *sf = SELECTED_FRAME ();
3010
3011 /* Allocate space for the components, the dots which separate them,
3012 and the final '\0'. */
3013 name_key = (char *) alloca (SBYTES (Vinvocation_name)
3014 + strlen (attribute) + 2);
3015 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3016 + strlen (class) + 2);
3017
3018 sprintf (name_key, "%s.%s",
3019 SDATA (Vinvocation_name),
3020 attribute);
3021 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3022
3023 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
3024 name_key, class_key);
3025 }
3026
3027 /* Types we might convert a resource string into. */
3028 enum resource_types
3029 {
3030 RES_TYPE_NUMBER,
3031 RES_TYPE_FLOAT,
3032 RES_TYPE_BOOLEAN,
3033 RES_TYPE_STRING,
3034 RES_TYPE_SYMBOL
3035 };
3036
3037 /* Return the value of parameter PARAM.
3038
3039 First search ALIST, then Vdefault_frame_alist, then the X defaults
3040 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3041
3042 Convert the resource to the type specified by desired_type.
3043
3044 If no default is specified, return Qunbound. If you call
3045 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3046 and don't let it get stored in any Lisp-visible variables! */
3047
3048 static Lisp_Object
3049 x_get_arg (dpyinfo, alist, param, attribute, class, type)
3050 struct x_display_info *dpyinfo;
3051 Lisp_Object alist, param;
3052 char *attribute;
3053 char *class;
3054 enum resource_types type;
3055 {
3056 register Lisp_Object tem;
3057
3058 tem = Fassq (param, alist);
3059 if (EQ (tem, Qnil))
3060 tem = Fassq (param, Vdefault_frame_alist);
3061 if (EQ (tem, Qnil))
3062 {
3063
3064 if (attribute)
3065 {
3066 tem = display_x_get_resource (dpyinfo,
3067 build_string (attribute),
3068 build_string (class),
3069 Qnil, Qnil);
3070
3071 if (NILP (tem))
3072 return Qunbound;
3073
3074 switch (type)
3075 {
3076 case RES_TYPE_NUMBER:
3077 return make_number (atoi (SDATA (tem)));
3078
3079 case RES_TYPE_FLOAT:
3080 return make_float (atof (SDATA (tem)));
3081
3082 case RES_TYPE_BOOLEAN:
3083 tem = Fdowncase (tem);
3084 if (!strcmp (SDATA (tem), "on")
3085 || !strcmp (SDATA (tem), "true"))
3086 return Qt;
3087 else
3088 return Qnil;
3089
3090 case RES_TYPE_STRING:
3091 return tem;
3092
3093 case RES_TYPE_SYMBOL:
3094 /* As a special case, we map the values `true' and `on'
3095 to Qt, and `false' and `off' to Qnil. */
3096 {
3097 Lisp_Object lower;
3098 lower = Fdowncase (tem);
3099 if (!strcmp (SDATA (lower), "on")
3100 || !strcmp (SDATA (lower), "true"))
3101 return Qt;
3102 else if (!strcmp (SDATA (lower), "off")
3103 || !strcmp (SDATA (lower), "false"))
3104 return Qnil;
3105 else
3106 return Fintern (tem, Qnil);
3107 }
3108
3109 default:
3110 abort ();
3111 }
3112 }
3113 else
3114 return Qunbound;
3115 }
3116 return Fcdr (tem);
3117 }
3118
3119 /* Like x_get_arg, but also record the value in f->param_alist. */
3120
3121 static Lisp_Object
3122 x_get_and_record_arg (f, alist, param, attribute, class, type)
3123 struct frame *f;
3124 Lisp_Object alist, param;
3125 char *attribute;
3126 char *class;
3127 enum resource_types type;
3128 {
3129 Lisp_Object value;
3130
3131 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
3132 attribute, class, type);
3133 if (! NILP (value))
3134 store_frame_param (f, param, value);
3135
3136 return value;
3137 }
3138
3139 /* Record in frame F the specified or default value according to ALIST
3140 of the parameter named PROP (a Lisp symbol).
3141 If no value is specified for PROP, look for an X default for XPROP
3142 on the frame named NAME.
3143 If that is not found either, use the value DEFLT. */
3144
3145 static Lisp_Object
3146 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3147 struct frame *f;
3148 Lisp_Object alist;
3149 Lisp_Object prop;
3150 Lisp_Object deflt;
3151 char *xprop;
3152 char *xclass;
3153 enum resource_types type;
3154 {
3155 Lisp_Object tem;
3156
3157 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
3158 if (EQ (tem, Qunbound))
3159 tem = deflt;
3160 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3161 return tem;
3162 }
3163
3164
3165 /* Record in frame F the specified or default value according to ALIST 1806 /* Record in frame F the specified or default value according to ALIST
3166 of the parameter named PROP (a Lisp symbol). If no value is 1807 of the parameter named PROP (a Lisp symbol). If no value is
3167 specified for PROP, look for an X default for XPROP on the frame 1808 specified for PROP, look for an X default for XPROP on the frame
3168 named NAME. If that is not found either, use the value DEFLT. */ 1809 named NAME. If that is not found either, use the value DEFLT. */
3169 1810
3214 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil)); 1855 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3215 return tem; 1856 return tem;
3216 } 1857 }
3217 1858
3218 1859
3219
3220 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3221 doc: /* Parse an X-style geometry string STRING.
3222 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3223 The properties returned may include `top', `left', `height', and `width'.
3224 The value of `left' or `top' may be an integer,
3225 or a list (+ N) meaning N pixels relative to top/left corner,
3226 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3227 (string)
3228 Lisp_Object string;
3229 {
3230 int geometry, x, y;
3231 unsigned int width, height;
3232 Lisp_Object result;
3233
3234 CHECK_STRING (string);
3235
3236 geometry = XParseGeometry ((char *) SDATA (string),
3237 &x, &y, &width, &height);
3238
3239 #if 0
3240 if (!!(geometry & XValue) != !!(geometry & YValue))
3241 error ("Must specify both x and y position, or neither");
3242 #endif
3243
3244 result = Qnil;
3245 if (geometry & XValue)
3246 {
3247 Lisp_Object element;
3248
3249 if (x >= 0 && (geometry & XNegative))
3250 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3251 else if (x < 0 && ! (geometry & XNegative))
3252 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3253 else
3254 element = Fcons (Qleft, make_number (x));
3255 result = Fcons (element, result);
3256 }
3257
3258 if (geometry & YValue)
3259 {
3260 Lisp_Object element;
3261
3262 if (y >= 0 && (geometry & YNegative))
3263 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3264 else if (y < 0 && ! (geometry & YNegative))
3265 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3266 else
3267 element = Fcons (Qtop, make_number (y));
3268 result = Fcons (element, result);
3269 }
3270
3271 if (geometry & WidthValue)
3272 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3273 if (geometry & HeightValue)
3274 result = Fcons (Fcons (Qheight, make_number (height)), result);
3275
3276 return result;
3277 }
3278
3279 /* Calculate the desired size and position of this window,
3280 and return the flags saying which aspects were specified.
3281
3282 This function does not make the coordinates positive. */
3283
3284 #define DEFAULT_ROWS 40
3285 #define DEFAULT_COLS 80
3286
3287 static int
3288 x_figure_window_size (f, parms)
3289 struct frame *f;
3290 Lisp_Object parms;
3291 {
3292 register Lisp_Object tem0, tem1, tem2;
3293 long window_prompting = 0;
3294 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3295
3296 /* Default values if we fall through.
3297 Actually, if that happens we should get
3298 window manager prompting. */
3299 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3300 f->height = DEFAULT_ROWS;
3301 /* Window managers expect that if program-specified
3302 positions are not (0,0), they're intentional, not defaults. */
3303 f->output_data.x->top_pos = 0;
3304 f->output_data.x->left_pos = 0;
3305
3306 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3307 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3308 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3309 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3310 {
3311 if (!EQ (tem0, Qunbound))
3312 {
3313 CHECK_NUMBER (tem0);
3314 f->height = XINT (tem0);
3315 }
3316 if (!EQ (tem1, Qunbound))
3317 {
3318 CHECK_NUMBER (tem1);
3319 SET_FRAME_WIDTH (f, XINT (tem1));
3320 }
3321 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3322 window_prompting |= USSize;
3323 else
3324 window_prompting |= PSize;
3325 }
3326
3327 f->output_data.x->vertical_scroll_bar_extra
3328 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3329 ? 0
3330 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3331
3332 x_compute_fringe_widths (f, 0);
3333
3334 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3335 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3336
3337 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3338 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3339 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3340 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3341 {
3342 if (EQ (tem0, Qminus))
3343 {
3344 f->output_data.x->top_pos = 0;
3345 window_prompting |= YNegative;
3346 }
3347 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3348 && CONSP (XCDR (tem0))
3349 && INTEGERP (XCAR (XCDR (tem0))))
3350 {
3351 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3352 window_prompting |= YNegative;
3353 }
3354 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3355 && CONSP (XCDR (tem0))
3356 && INTEGERP (XCAR (XCDR (tem0))))
3357 {
3358 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3359 }
3360 else if (EQ (tem0, Qunbound))
3361 f->output_data.x->top_pos = 0;
3362 else
3363 {
3364 CHECK_NUMBER (tem0);
3365 f->output_data.x->top_pos = XINT (tem0);
3366 if (f->output_data.x->top_pos < 0)
3367 window_prompting |= YNegative;
3368 }
3369
3370 if (EQ (tem1, Qminus))
3371 {
3372 f->output_data.x->left_pos = 0;
3373 window_prompting |= XNegative;
3374 }
3375 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3376 && CONSP (XCDR (tem1))
3377 && INTEGERP (XCAR (XCDR (tem1))))
3378 {
3379 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3380 window_prompting |= XNegative;
3381 }
3382 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3383 && CONSP (XCDR (tem1))
3384 && INTEGERP (XCAR (XCDR (tem1))))
3385 {
3386 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3387 }
3388 else if (EQ (tem1, Qunbound))
3389 f->output_data.x->left_pos = 0;
3390 else
3391 {
3392 CHECK_NUMBER (tem1);
3393 f->output_data.x->left_pos = XINT (tem1);
3394 if (f->output_data.x->left_pos < 0)
3395 window_prompting |= XNegative;
3396 }
3397
3398 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3399 window_prompting |= USPosition;
3400 else
3401 window_prompting |= PPosition;
3402 }
3403
3404 if (f->output_data.x->want_fullscreen != FULLSCREEN_NONE)
3405 {
3406 int left, top;
3407 int width, height;
3408
3409 /* It takes both for some WM:s to place it where we want */
3410 window_prompting = USPosition | PPosition;
3411 x_fullscreen_adjust (f, &width, &height, &top, &left);
3412 f->width = width;
3413 f->height = height;
3414 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3415 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3416 f->output_data.x->left_pos = left;
3417 f->output_data.x->top_pos = top;
3418 }
3419
3420 return window_prompting;
3421 }
3422 1860
3423 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS) 1861 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3424 1862
3425 Status 1863 Status
3426 XSetWMProtocols (dpy, w, protocols, count) 1864 XSetWMProtocols (dpy, w, protocols, count)
3456 int need_focus = 1; 1894 int need_focus = 1;
3457 int need_save = 1; 1895 int need_save = 1;
3458 1896
3459 BLOCK_INPUT; 1897 BLOCK_INPUT;
3460 { 1898 {
3461 Atom type, *atoms = 0; 1899 Atom type;
1900 unsigned char *catoms;
3462 int format = 0; 1901 int format = 0;
3463 unsigned long nitems = 0; 1902 unsigned long nitems = 0;
3464 unsigned long bytes_after; 1903 unsigned long bytes_after;
3465 1904
3466 if ((XGetWindowProperty (dpy, w, 1905 if ((XGetWindowProperty (dpy, w,
3467 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols, 1906 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3468 (long)0, (long)100, False, XA_ATOM, 1907 (long)0, (long)100, False, XA_ATOM,
3469 &type, &format, &nitems, &bytes_after, 1908 &type, &format, &nitems, &bytes_after,
3470 (unsigned char **) &atoms) 1909 &catoms)
3471 == Success) 1910 == Success)
3472 && format == 32 && type == XA_ATOM) 1911 && format == 32 && type == XA_ATOM)
3473 while (nitems > 0) 1912 {
3474 { 1913 Atom *atoms = (Atom *) catoms;
3475 nitems--; 1914 while (nitems > 0)
3476 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window) 1915 {
3477 need_delete = 0; 1916 nitems--;
3478 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus) 1917 if (atoms[nitems]
3479 need_focus = 0; 1918 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3480 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself) 1919 need_delete = 0;
3481 need_save = 0; 1920 else if (atoms[nitems]
3482 } 1921 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3483 if (atoms) XFree ((char *) atoms); 1922 need_focus = 0;
1923 else if (atoms[nitems]
1924 == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
1925 need_save = 0;
1926 }
1927 }
1928 if (catoms)
1929 XFree (catoms);
3484 } 1930 }
3485 { 1931 {
3486 Atom props [10]; 1932 Atom props [10];
3487 int count = 0; 1933 int count = 0;
3488 if (need_delete) 1934 if (need_delete)
3508 1954
3509 static XFontSet xic_create_xfontset P_ ((struct frame *, char *)); 1955 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3510 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *)); 1956 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3511 1957
3512 1958
3513 /* Supported XIM styles, ordered by preferenc. */ 1959 /* Supported XIM styles, ordered by preference. */
3514 1960
3515 static XIMStyle supported_xim_styles[] = 1961 static XIMStyle supported_xim_styles[] =
3516 { 1962 {
3517 XIMPreeditPosition | XIMStatusArea, 1963 XIMPreeditPosition | XIMStatusArea,
3518 XIMPreeditPosition | XIMStatusNothing, 1964 XIMPreeditPosition | XIMStatusNothing,
3525 XIMPreeditNone | XIMStatusNone, 1971 XIMPreeditNone | XIMStatusNone,
3526 0, 1972 0,
3527 }; 1973 };
3528 1974
3529 1975
3530 /* Create an X fontset on frame F with base font name 1976 /* Create an X fontset on frame F with base font name BASE_FONTNAME. */
3531 BASE_FONTNAME.. */ 1977
1978 char xic_defaut_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
1979
1980 /* Create an Xt fontset spec from the name of a base font.
1981 If `motif' is True use the Motif syntax. */
1982 char *
1983 xic_create_fontsetname (base_fontname, motif)
1984 char *base_fontname;
1985 Bool motif;
1986 {
1987 const char *sep = motif ? ";" : ",";
1988 char *fontsetname;
1989
1990 /* Make a fontset name from the base font name. */
1991 if (xic_defaut_fontset == base_fontname)
1992 { /* There is no base font name, use the default. */
1993 int len = strlen (base_fontname) + 2;
1994 fontsetname = xmalloc (len);
1995 bzero (fontsetname, len);
1996 strcpy (fontsetname, base_fontname);
1997 }
1998 else
1999 {
2000 /* Make a fontset name from the base font name.
2001 The font set will be made of the following elements:
2002 - the base font.
2003 - the base font where the charset spec is replaced by -*-*.
2004 - the same but with the family also replaced with -*-*-. */
2005 char *p = base_fontname;
2006 int i;
2007
2008 for (i = 0; *p; p++)
2009 if (*p == '-') i++;
2010 if (i != 14)
2011 { /* As the font name doesn't conform to XLFD, we can't
2012 modify it to generalize it to allcs and allfamilies.
2013 Use the specified font plus the default. */
2014 int len = strlen (base_fontname) + strlen (xic_defaut_fontset) + 3;
2015 fontsetname = xmalloc (len);
2016 bzero (fontsetname, len);
2017 strcpy (fontsetname, base_fontname);
2018 strcat (fontsetname, sep);
2019 strcat (fontsetname, xic_defaut_fontset);
2020 }
2021 else
2022 {
2023 int len;
2024 char *p1 = NULL, *p2 = NULL;
2025 char *font_allcs = NULL;
2026 char *font_allfamilies = NULL;
2027 char *font_all = NULL;
2028 char *allcs = "*-*-*-*-*-*-*";
2029 char *allfamilies = "-*-*-";
2030 char *all = "*-*-*-*-";
2031
2032 for (i = 0, p = base_fontname; i < 8; p++)
2033 {
2034 if (*p == '-')
2035 {
2036 i++;
2037 if (i == 3)
2038 p1 = p + 1;
2039 else if (i == 7)
2040 p2 = p + 1;
2041 }
2042 }
2043 /* Build the font spec that matches all charsets. */
2044 len = p - base_fontname + strlen (allcs) + 1;
2045 font_allcs = (char *) alloca (len);
2046 bzero (font_allcs, len);
2047 bcopy (base_fontname, font_allcs, p - base_fontname);
2048 strcat (font_allcs, allcs);
2049
2050 /* Build the font spec that matches all families. */
2051 len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2052 font_allfamilies = (char *) alloca (len);
2053 bzero (font_allfamilies, len);
2054 strcpy (font_allfamilies, allfamilies);
2055 bcopy (p1, font_allfamilies + strlen (allfamilies), p - p1);
2056 strcat (font_allfamilies, allcs);
2057
2058 /* Build the font spec that matches all. */
2059 len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2060 font_all = (char *) alloca (len);
2061 bzero (font_all, len);
2062 strcpy (font_all, allfamilies);
2063 strcat (font_all, all);
2064 bcopy (p2, font_all + strlen (all) + strlen (allfamilies), p - p2);
2065 strcat (font_all, allcs);
2066
2067 /* Build the actual font set name. */
2068 len = strlen (base_fontname) + strlen (font_allcs)
2069 + strlen (font_allfamilies) + strlen (font_all) + 5;
2070 fontsetname = xmalloc (len);
2071 bzero (fontsetname, len);
2072 strcpy (fontsetname, base_fontname);
2073 strcat (fontsetname, sep);
2074 strcat (fontsetname, font_allcs);
2075 strcat (fontsetname, sep);
2076 strcat (fontsetname, font_allfamilies);
2077 strcat (fontsetname, sep);
2078 strcat (fontsetname, font_all);
2079 }
2080 }
2081 if (motif)
2082 strcat (fontsetname, ":");
2083 return fontsetname;
2084 }
3532 2085
3533 static XFontSet 2086 static XFontSet
3534 xic_create_xfontset (f, base_fontname) 2087 xic_create_xfontset (f, base_fontname)
3535 struct frame *f; 2088 struct frame *f;
3536 char *base_fontname; 2089 char *base_fontname;
3537 { 2090 {
3538 XFontSet xfs; 2091 XFontSet xfs = NULL;
3539 char **missing_list; 2092 char **missing_list = NULL;
3540 int missing_count; 2093 int missing_count;
3541 char *def_string; 2094 char *def_string;
3542 2095 Lisp_Object rest, frame;
3543 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), 2096
3544 base_fontname, &missing_list, 2097 if (!base_fontname)
3545 &missing_count, &def_string); 2098 base_fontname = xic_defaut_fontset;
3546 if (missing_list) 2099
3547 XFreeStringList (missing_list); 2100 /* See if there is another frame already using same fontset. */
3548 2101 FOR_EACH_FRAME (rest, frame)
3549 /* No need to free def_string. */ 2102 {
2103 struct frame *cf = XFRAME (frame);
2104 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2105 && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
2106 && FRAME_XIC_BASE_FONTNAME (cf)
2107 && !strcmp (FRAME_XIC_BASE_FONTNAME (cf), base_fontname))
2108 {
2109 xfs = FRAME_XIC_FONTSET (cf);
2110 break;
2111 }
2112 }
2113
2114 if (!xfs)
2115 {
2116 char *fontsetname = xic_create_fontsetname (base_fontname, False);
2117
2118 /* New fontset. */
2119 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
2120 fontsetname, &missing_list,
2121 &missing_count, &def_string);
2122 if (missing_list)
2123 XFreeStringList (missing_list);
2124 xfree (fontsetname);
2125 }
2126
2127 if (FRAME_XIC_BASE_FONTNAME (f))
2128 xfree (FRAME_XIC_BASE_FONTNAME (f));
2129 FRAME_XIC_BASE_FONTNAME (f) = xstrdup (base_fontname);
2130
2131 /* No need to free def_string. */
3550 return xfs; 2132 return xfs;
2133 }
2134
2135 /* Free the X fontset of frame F if it is the last frame using it. */
2136
2137 void
2138 xic_free_xfontset (f)
2139 struct frame *f;
2140 {
2141 Lisp_Object rest, frame;
2142 int shared_p = 0;
2143
2144 if (!FRAME_XIC_FONTSET (f))
2145 return;
2146
2147 /* See if there is another frame sharing the same fontset. */
2148 FOR_EACH_FRAME (rest, frame)
2149 {
2150 struct frame *cf = XFRAME (frame);
2151 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2152 && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
2153 && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
2154 {
2155 shared_p = 1;
2156 break;
2157 }
2158 }
2159
2160 if (!shared_p)
2161 /* The fontset is not used anymore. It is safe to free it. */
2162 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2163
2164 if (FRAME_XIC_BASE_FONTNAME (f))
2165 xfree (FRAME_XIC_BASE_FONTNAME (f));
2166 FRAME_XIC_BASE_FONTNAME (f) = NULL;
2167 FRAME_XIC_FONTSET (f) = NULL;
3551 } 2168 }
3552 2169
3553 2170
3554 /* Value is the best input style, given user preferences USER (already 2171 /* Value is the best input style, given user preferences USER (already
3555 checked to be supported by Emacs), and styles supported by the 2172 checked to be supported by Emacs), and styles supported by the
3584 XFontSet xfs = NULL; 2201 XFontSet xfs = NULL;
3585 2202
3586 if (FRAME_XIC (f)) 2203 if (FRAME_XIC (f))
3587 return; 2204 return;
3588 2205
2206 /* Create X fontset. */
2207 xfs = xic_create_xfontset
2208 (f, (FRAME_FONTSET (f) < 0) ? NULL
2209 : (char *) SDATA (fontset_ascii (FRAME_FONTSET (f))));
2210
3589 xim = FRAME_X_XIM (f); 2211 xim = FRAME_X_XIM (f);
3590 if (xim) 2212 if (xim)
3591 { 2213 {
3592 XRectangle s_area; 2214 XRectangle s_area;
3593 XPoint spot; 2215 XPoint spot;
3594 XVaNestedList preedit_attr; 2216 XVaNestedList preedit_attr;
3595 XVaNestedList status_attr; 2217 XVaNestedList status_attr;
3596 char *base_fontname;
3597 int fontset;
3598 2218
3599 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1; 2219 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3600 spot.x = 0; spot.y = 1; 2220 spot.x = 0; spot.y = 1;
3601 /* Create X fontset. */
3602 fontset = FRAME_FONTSET (f);
3603 if (fontset < 0)
3604 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3605 else
3606 {
3607 /* Determine the base fontname from the ASCII font name of
3608 FONTSET. */
3609 char *ascii_font = (char *) SDATA (fontset_ascii (fontset));
3610 char *p = ascii_font;
3611 int i;
3612
3613 for (i = 0; *p; p++)
3614 if (*p == '-') i++;
3615 if (i != 14)
3616 /* As the font name doesn't conform to XLFD, we can't
3617 modify it to get a suitable base fontname for the
3618 frame. */
3619 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3620 else
3621 {
3622 int len = strlen (ascii_font) + 1;
3623 char *p1 = NULL;
3624
3625 for (i = 0, p = ascii_font; i < 8; p++)
3626 {
3627 if (*p == '-')
3628 {
3629 i++;
3630 if (i == 3)
3631 p1 = p + 1;
3632 }
3633 }
3634 base_fontname = (char *) alloca (len);
3635 bzero (base_fontname, len);
3636 strcpy (base_fontname, "-*-*-");
3637 bcopy (p1, base_fontname + 5, p - p1);
3638 strcat (base_fontname, "*-*-*-*-*-*-*");
3639 }
3640 }
3641 xfs = xic_create_xfontset (f, base_fontname);
3642 2221
3643 /* Determine XIC style. */ 2222 /* Determine XIC style. */
3644 if (xic_style == 0) 2223 if (xic_style == 0)
3645 { 2224 {
3646 XIMStyles supported_list; 2225 XIMStyles supported_list;
3673 FRAME_BACKGROUND_PIXEL (f), 2252 FRAME_BACKGROUND_PIXEL (f),
3674 NULL); 2253 NULL);
3675 2254
3676 xic = XCreateIC (xim, 2255 xic = XCreateIC (xim,
3677 XNInputStyle, xic_style, 2256 XNInputStyle, xic_style,
3678 XNClientWindow, FRAME_X_WINDOW(f), 2257 XNClientWindow, FRAME_X_WINDOW (f),
3679 XNFocusWindow, FRAME_X_WINDOW(f), 2258 XNFocusWindow, FRAME_X_WINDOW (f),
3680 XNStatusAttributes, status_attr, 2259 XNStatusAttributes, status_attr,
3681 XNPreeditAttributes, preedit_attr, 2260 XNPreeditAttributes, preedit_attr,
3682 NULL); 2261 NULL);
3683 XFree (preedit_attr); 2262 XFree (preedit_attr);
3684 XFree (status_attr); 2263 XFree (status_attr);
3698 { 2277 {
3699 if (FRAME_XIC (f) == NULL) 2278 if (FRAME_XIC (f) == NULL)
3700 return; 2279 return;
3701 2280
3702 XDestroyIC (FRAME_XIC (f)); 2281 XDestroyIC (FRAME_XIC (f));
3703 if (FRAME_XIC_FONTSET (f)) 2282 xic_free_xfontset (f);
3704 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3705 2283
3706 FRAME_XIC (f) = NULL; 2284 FRAME_XIC (f) = NULL;
3707 FRAME_XIC_FONTSET (f) = NULL;
3708 } 2285 }
3709 2286
3710 2287
3711 /* Place preedit area for XIC of window W's frame to specified 2288 /* Place preedit area for XIC of window W's frame to specified
3712 pixel position X/Y. X and Y are relative to window W. */ 2289 pixel position X/Y. X and Y are relative to window W. */
3718 { 2295 {
3719 struct frame *f = XFRAME (w->frame); 2296 struct frame *f = XFRAME (w->frame);
3720 XVaNestedList attr; 2297 XVaNestedList attr;
3721 XPoint spot; 2298 XPoint spot;
3722 2299
3723 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x); 2300 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
3724 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f)); 2301 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3725 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL); 2302 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3726 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL); 2303 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3727 XFree (attr); 2304 XFree (attr);
3728 } 2305 }
3757 XFree (attr); 2334 XFree (attr);
3758 } 2335 }
3759 2336
3760 area.width = needed->width; 2337 area.width = needed->width;
3761 area.height = needed->height; 2338 area.height = needed->height;
3762 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f); 2339 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3763 area.y = (PIXEL_HEIGHT (f) - area.height 2340 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
3764 - FRAME_MENUBAR_HEIGHT (f) 2341 - FRAME_MENUBAR_HEIGHT (f)
3765 - FRAME_TOOLBAR_HEIGHT (f) 2342 - FRAME_TOOLBAR_HEIGHT (f)
3766 - FRAME_INTERNAL_BORDER_WIDTH (f)); 2343 - FRAME_INTERNAL_BORDER_WIDTH (f));
3767 XFree (needed); 2344 XFree (needed);
3768 2345
3769 attr = XVaCreateNestedList (0, XNArea, &area, NULL); 2346 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3770 XSetICValues(xic, XNStatusAttributes, attr, NULL); 2347 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3771 XFree (attr); 2348 XFree (attr);
3772 } 2349 }
3773 2350
3774 2351
3775 /* Set X fontset for XIC of frame F, using base font name 2352 /* Set X fontset for XIC of frame F, using base font name
3780 struct frame *f; 2357 struct frame *f;
3781 char *base_fontname; 2358 char *base_fontname;
3782 { 2359 {
3783 XVaNestedList attr; 2360 XVaNestedList attr;
3784 XFontSet xfs; 2361 XFontSet xfs;
2362
2363 xic_free_xfontset (f);
3785 2364
3786 xfs = xic_create_xfontset (f, base_fontname); 2365 xfs = xic_create_xfontset (f, base_fontname);
3787 2366
3788 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL); 2367 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3789 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition) 2368 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3790 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL); 2369 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3791 if (FRAME_XIC_STYLE (f) & XIMStatusArea) 2370 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3792 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL); 2371 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3793 XFree (attr); 2372 XFree (attr);
3794 2373
3795 if (FRAME_XIC_FONTSET (f))
3796 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3797 FRAME_XIC_FONTSET (f) = xfs; 2374 FRAME_XIC_FONTSET (f) = xfs;
3798 } 2375 }
3799 2376
3800 #endif /* HAVE_X_I18N */ 2377 #endif /* HAVE_X_I18N */
3801 2378
3836 2413
3837 ac = 0; 2414 ac = 0;
3838 XtSetArg (al[ac], XtNallowShellResize, 1); ac++; 2415 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3839 XtSetArg (al[ac], XtNinput, 1); ac++; 2416 XtSetArg (al[ac], XtNinput, 1); ac++;
3840 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++; 2417 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3841 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++; 2418 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
3842 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++; 2419 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3843 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++; 2420 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3844 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; 2421 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3845 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS, 2422 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3846 applicationShellWidgetClass, 2423 applicationShellWidgetClass,
3885 2462
3886 /* Do some needed geometry management. */ 2463 /* Do some needed geometry management. */
3887 { 2464 {
3888 int len; 2465 int len;
3889 char *tem, shell_position[32]; 2466 char *tem, shell_position[32];
3890 Arg al[2]; 2467 Arg al[10];
3891 int ac = 0; 2468 int ac = 0;
3892 int extra_borders = 0; 2469 int extra_borders = 0;
3893 int menubar_size 2470 int menubar_size
3894 = (f->output_data.x->menubar_widget 2471 = (f->output_data.x->menubar_widget
3895 ? (f->output_data.x->menubar_widget->core.height 2472 ? (f->output_data.x->menubar_widget->core.height
3921 and specify it. 2498 and specify it.
3922 Note that we do not specify here whether the position 2499 Note that we do not specify here whether the position
3923 is a user-specified or program-specified one. 2500 is a user-specified or program-specified one.
3924 We pass that information later, in x_wm_set_size_hints. */ 2501 We pass that information later, in x_wm_set_size_hints. */
3925 { 2502 {
3926 int left = f->output_data.x->left_pos; 2503 int left = f->left_pos;
3927 int xneg = window_prompting & XNegative; 2504 int xneg = window_prompting & XNegative;
3928 int top = f->output_data.x->top_pos; 2505 int top = f->top_pos;
3929 int yneg = window_prompting & YNegative; 2506 int yneg = window_prompting & YNegative;
3930 if (xneg) 2507 if (xneg)
3931 left = -left; 2508 left = -left;
3932 if (yneg) 2509 if (yneg)
3933 top = -top; 2510 top = -top;
3934 2511
3935 if (window_prompting & USPosition) 2512 if (window_prompting & USPosition)
3936 sprintf (shell_position, "=%dx%d%c%d%c%d", 2513 sprintf (shell_position, "=%dx%d%c%d%c%d",
3937 PIXEL_WIDTH (f) + extra_borders, 2514 FRAME_PIXEL_WIDTH (f) + extra_borders,
3938 PIXEL_HEIGHT (f) + menubar_size + extra_borders, 2515 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3939 (xneg ? '-' : '+'), left, 2516 (xneg ? '-' : '+'), left,
3940 (yneg ? '-' : '+'), top); 2517 (yneg ? '-' : '+'), top);
3941 else 2518 else
3942 sprintf (shell_position, "=%dx%d", 2519 {
3943 PIXEL_WIDTH (f) + extra_borders, 2520 sprintf (shell_position, "=%dx%d",
3944 PIXEL_HEIGHT (f) + menubar_size + extra_borders); 2521 FRAME_PIXEL_WIDTH (f) + extra_borders,
2522 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2523
2524 /* Setting x and y when the position is not specified in
2525 the geometry string will set program position in the WM hints.
2526 If Emacs had just one program position, we could set it in
2527 fallback resources, but since each make-frame call can specify
2528 different program positions, this is easier. */
2529 XtSetArg (al[ac], XtNx, left); ac++;
2530 XtSetArg (al[ac], XtNy, top); ac++;
2531 }
3945 } 2532 }
3946 2533
3947 len = strlen (shell_position) + 1; 2534 len = strlen (shell_position) + 1;
3948 /* We don't free this because we don't know whether 2535 /* We don't free this because we don't know whether
3949 it is safe to free it while the frame exists. 2536 it is safe to free it while the frame exists.
3966 class_hints.res_class = (char *) SDATA (Vx_resource_class); 2553 class_hints.res_class = (char *) SDATA (Vx_resource_class);
3967 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints); 2554 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3968 2555
3969 #ifdef HAVE_X_I18N 2556 #ifdef HAVE_X_I18N
3970 FRAME_XIC (f) = NULL; 2557 FRAME_XIC (f) = NULL;
3971 #ifdef USE_XIM 2558 if (use_xim)
3972 create_frame_xic (f); 2559 create_frame_xic (f);
3973 #endif
3974 #endif 2560 #endif
3975 2561
3976 f->output_data.x->wm_hints.input = True; 2562 f->output_data.x->wm_hints.input = True;
3977 f->output_data.x->wm_hints.flags |= InputHint; 2563 f->output_data.x->wm_hints.flags |= InputHint;
3978 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 2564 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3999 #ifdef HAVE_X_I18N 2585 #ifdef HAVE_X_I18N
4000 if (FRAME_XIC (f)) 2586 if (FRAME_XIC (f))
4001 { 2587 {
4002 /* XIM server might require some X events. */ 2588 /* XIM server might require some X events. */
4003 unsigned long fevent = NoEventMask; 2589 unsigned long fevent = NoEventMask;
4004 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL); 2590 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
4005 attributes.event_mask |= fevent; 2591 attributes.event_mask |= fevent;
4006 } 2592 }
4007 #endif /* HAVE_X_I18N */ 2593 #endif /* HAVE_X_I18N */
4008 2594
4009 attribute_mask = CWEventMask; 2595 attribute_mask = CWEventMask;
4045 if (! xg_create_frame_widgets (f)) 2631 if (! xg_create_frame_widgets (f))
4046 error ("Unable to create window"); 2632 error ("Unable to create window");
4047 2633
4048 #ifdef HAVE_X_I18N 2634 #ifdef HAVE_X_I18N
4049 FRAME_XIC (f) = NULL; 2635 FRAME_XIC (f) = NULL;
4050 #ifdef USE_XIM 2636 if (use_xim)
4051 BLOCK_INPUT; 2637 {
4052 create_frame_xic (f); 2638 BLOCK_INPUT;
4053 if (FRAME_XIC (f)) 2639 create_frame_xic (f);
4054 { 2640 if (FRAME_XIC (f))
4055 /* XIM server might require some X events. */ 2641 {
4056 unsigned long fevent = NoEventMask; 2642 /* XIM server might require some X events. */
4057 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL); 2643 unsigned long fevent = NoEventMask;
4058 2644 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
4059 if (fevent != NoEventMask) 2645
4060 { 2646 if (fevent != NoEventMask)
4061 XSetWindowAttributes attributes; 2647 {
4062 XWindowAttributes wattr; 2648 XSetWindowAttributes attributes;
4063 unsigned long attribute_mask; 2649 XWindowAttributes wattr;
4064 2650 unsigned long attribute_mask;
4065 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 2651
4066 &wattr); 2652 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4067 attributes.event_mask = wattr.your_event_mask | fevent; 2653 &wattr);
4068 attribute_mask = CWEventMask; 2654 attributes.event_mask = wattr.your_event_mask | fevent;
4069 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 2655 attribute_mask = CWEventMask;
4070 attribute_mask, &attributes); 2656 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4071 } 2657 attribute_mask, &attributes);
4072 } 2658 }
4073 UNBLOCK_INPUT; 2659 }
4074 #endif 2660 UNBLOCK_INPUT;
2661 }
4075 #endif 2662 #endif
4076 } 2663 }
4077 2664
4078 #else /*! USE_GTK */ 2665 #else /*! USE_GTK */
4079 /* Create and set up the X window for frame F. */ 2666 /* Create and set up the X window for frame F. */
4099 2686
4100 BLOCK_INPUT; 2687 BLOCK_INPUT;
4101 FRAME_X_WINDOW (f) 2688 FRAME_X_WINDOW (f)
4102 = XCreateWindow (FRAME_X_DISPLAY (f), 2689 = XCreateWindow (FRAME_X_DISPLAY (f),
4103 f->output_data.x->parent_desc, 2690 f->output_data.x->parent_desc,
4104 f->output_data.x->left_pos, 2691 f->left_pos,
4105 f->output_data.x->top_pos, 2692 f->top_pos,
4106 PIXEL_WIDTH (f), PIXEL_HEIGHT (f), 2693 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
4107 f->output_data.x->border_width, 2694 f->border_width,
4108 CopyFromParent, /* depth */ 2695 CopyFromParent, /* depth */
4109 InputOutput, /* class */ 2696 InputOutput, /* class */
4110 FRAME_X_VISUAL (f), 2697 FRAME_X_VISUAL (f),
4111 attribute_mask, &attributes); 2698 attribute_mask, &attributes);
4112 2699
4113 #ifdef HAVE_X_I18N 2700 #ifdef HAVE_X_I18N
4114 #ifdef USE_XIM 2701 if (use_xim)
4115 create_frame_xic (f); 2702 {
4116 if (FRAME_XIC (f)) 2703 create_frame_xic (f);
4117 { 2704 if (FRAME_XIC (f))
4118 /* XIM server might require some X events. */ 2705 {
4119 unsigned long fevent = NoEventMask; 2706 /* XIM server might require some X events. */
4120 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL); 2707 unsigned long fevent = NoEventMask;
4121 attributes.event_mask |= fevent; 2708 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
4122 attribute_mask = CWEventMask; 2709 attributes.event_mask |= fevent;
4123 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 2710 attribute_mask = CWEventMask;
4124 attribute_mask, &attributes); 2711 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4125 } 2712 attribute_mask, &attributes);
4126 #endif 2713 }
2714 }
4127 #endif /* HAVE_X_I18N */ 2715 #endif /* HAVE_X_I18N */
4128 2716
4129 validate_x_resource_name (); 2717 validate_x_resource_name ();
4130 2718
4131 class_hints.res_name = (char *) SDATA (Vx_resource_name); 2719 class_hints.res_name = (char *) SDATA (Vx_resource_name);
4179 } 2767 }
4180 2768
4181 #endif /* not USE_GTK */ 2769 #endif /* not USE_GTK */
4182 #endif /* not USE_X_TOOLKIT */ 2770 #endif /* not USE_X_TOOLKIT */
4183 2771
2772 /* Verify that the icon position args for this window are valid. */
2773
2774 static void
2775 x_icon_verify (f, parms)
2776 struct frame *f;
2777 Lisp_Object parms;
2778 {
2779 Lisp_Object icon_x, icon_y;
2780
2781 /* Set the position of the icon. Note that twm groups all
2782 icons in an icon window. */
2783 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2784 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2785 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2786 {
2787 CHECK_NUMBER (icon_x);
2788 CHECK_NUMBER (icon_y);
2789 }
2790 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2791 error ("Both left and top icon corners of icon must be specified");
2792 }
2793
4184 /* Handle the icon stuff for this window. Perhaps later we might 2794 /* Handle the icon stuff for this window. Perhaps later we might
4185 want an x_set_icon_position which can be called interactively as 2795 want an x_set_icon_position which can be called interactively as
4186 well. */ 2796 well. */
4187 2797
4188 static void 2798 static void
4193 Lisp_Object icon_x, icon_y; 2803 Lisp_Object icon_x, icon_y;
4194 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 2804 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4195 2805
4196 /* Set the position of the icon. Note that twm groups all 2806 /* Set the position of the icon. Note that twm groups all
4197 icons in an icon window. */ 2807 icons in an icon window. */
4198 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); 2808 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
4199 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); 2809 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
4200 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) 2810 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
4201 { 2811 {
4202 CHECK_NUMBER (icon_x); 2812 CHECK_NUMBER (icon_x);
4203 CHECK_NUMBER (icon_y); 2813 CHECK_NUMBER (icon_y);
4204 } 2814 }
4246 2856
4247 /* Create the GCs of this frame. 2857 /* Create the GCs of this frame.
4248 Note that many default values are used. */ 2858 Note that many default values are used. */
4249 2859
4250 /* Normal video */ 2860 /* Normal video */
4251 gc_values.font = f->output_data.x->font->fid; 2861 gc_values.font = FRAME_FONT (f)->fid;
4252 gc_values.foreground = f->output_data.x->foreground_pixel; 2862 gc_values.foreground = f->output_data.x->foreground_pixel;
4253 gc_values.background = f->output_data.x->background_pixel; 2863 gc_values.background = f->output_data.x->background_pixel;
4254 gc_values.line_width = 0; /* Means 1 using fast algorithm. */ 2864 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
4255 f->output_data.x->normal_gc 2865 f->output_data.x->normal_gc
4256 = XCreateGC (FRAME_X_DISPLAY (f), 2866 = XCreateGC (FRAME_X_DISPLAY (f),
4355 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 2965 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4356 #endif 2966 #endif
4357 2967
4358 x_free_frame_resources (f); 2968 x_free_frame_resources (f);
4359 2969
2970 #if GLYPH_DEBUG
4360 /* Check that reference counts are indeed correct. */ 2971 /* Check that reference counts are indeed correct. */
4361 xassert (dpyinfo->reference_count == dpyinfo_refcount); 2972 xassert (dpyinfo->reference_count == dpyinfo_refcount);
4362 xassert (dpyinfo->image_cache->refcount == image_cache_refcount); 2973 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
2974 #endif
4363 return Qt; 2975 return Qt;
4364 } 2976 }
4365 2977
4366 return Qnil; 2978 return Qnil;
4367 } 2979 }
4452 3064
4453 f->output_method = output_x_window; 3065 f->output_method = output_x_window;
4454 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output)); 3066 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4455 bzero (f->output_data.x, sizeof (struct x_output)); 3067 bzero (f->output_data.x, sizeof (struct x_output));
4456 f->output_data.x->icon_bitmap = -1; 3068 f->output_data.x->icon_bitmap = -1;
4457 f->output_data.x->fontset = -1; 3069 FRAME_FONTSET (f) = -1;
4458 f->output_data.x->scroll_bar_foreground_pixel = -1; 3070 f->output_data.x->scroll_bar_foreground_pixel = -1;
4459 f->output_data.x->scroll_bar_background_pixel = -1; 3071 f->output_data.x->scroll_bar_background_pixel = -1;
4460 #ifdef USE_TOOLKIT_SCROLL_BARS 3072 #ifdef USE_TOOLKIT_SCROLL_BARS
4461 f->output_data.x->scroll_bar_top_shadow_pixel = -1; 3073 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4462 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; 3074 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4580 } 3192 }
4581 3193
4582 #ifdef USE_LUCID 3194 #ifdef USE_LUCID
4583 /* Prevent lwlib/xlwmenu.c from crashing because of a bug 3195 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4584 whereby it fails to get any font. */ 3196 whereby it fails to get any font. */
4585 xlwmenu_default_font = f->output_data.x->font; 3197 xlwmenu_default_font = FRAME_FONT (f);
4586 #endif 3198 #endif
4587 3199
4588 x_default_parameter (f, parms, Qborder_width, make_number (2), 3200 x_default_parameter (f, parms, Qborder_width, make_number (2),
4589 "borderWidth", "BorderWidth", RES_TYPE_NUMBER); 3201 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4590 3202
4657 x_default_parameter (f, parms, Qfullscreen, Qnil, 3269 x_default_parameter (f, parms, Qfullscreen, Qnil,
4658 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); 3270 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4659 3271
4660 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window; 3272 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4661 3273
4662 /* Add the tool-bar height to the initial frame height so that the
4663 user gets a text display area of the size he specified with -g or
4664 via .Xdefaults. Later changes of the tool-bar height don't
4665 change the frame size. This is done so that users can create
4666 tall Emacs frames without having to guess how tall the tool-bar
4667 will get. */
4668 if (FRAME_TOOL_BAR_LINES (f))
4669 {
4670 int margin, relief, bar_height;
4671
4672 relief = (tool_bar_button_relief >= 0
4673 ? tool_bar_button_relief
4674 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4675
4676 if (INTEGERP (Vtool_bar_button_margin)
4677 && XINT (Vtool_bar_button_margin) > 0)
4678 margin = XFASTINT (Vtool_bar_button_margin);
4679 else if (CONSP (Vtool_bar_button_margin)
4680 && INTEGERP (XCDR (Vtool_bar_button_margin))
4681 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4682 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4683 else
4684 margin = 0;
4685
4686 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4687 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4688 }
4689
4690 /* Compute the size of the X window. */ 3274 /* Compute the size of the X window. */
4691 window_prompting = x_figure_window_size (f, parms); 3275 window_prompting = x_figure_window_size (f, parms, 1);
4692
4693 if (window_prompting & XNegative)
4694 {
4695 if (window_prompting & YNegative)
4696 f->output_data.x->win_gravity = SouthEastGravity;
4697 else
4698 f->output_data.x->win_gravity = NorthEastGravity;
4699 }
4700 else
4701 {
4702 if (window_prompting & YNegative)
4703 f->output_data.x->win_gravity = SouthWestGravity;
4704 else
4705 f->output_data.x->win_gravity = NorthWestGravity;
4706 }
4707
4708 f->output_data.x->size_hint_flags = window_prompting;
4709 3276
4710 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); 3277 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4711 f->no_split = minibuffer_only || EQ (tem, Qt); 3278 f->no_split = minibuffer_only || EQ (tem, Qt);
3279
3280 x_icon_verify (f, parms);
4712 3281
4713 /* Create the X widget or window. */ 3282 /* Create the X widget or window. */
4714 #ifdef USE_X_TOOLKIT 3283 #ifdef USE_X_TOOLKIT
4715 x_window (f, window_prompting, minibuffer_only); 3284 x_window (f, window_prompting, minibuffer_only);
4716 #else 3285 #else
4724 FRAME_X_DISPLAY_INFO (f)->reference_count++; 3293 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4725 Vframe_list = Fcons (frame, Vframe_list); 3294 Vframe_list = Fcons (frame, Vframe_list);
4726 3295
4727 /* We need to do this after creating the X window, so that the 3296 /* We need to do this after creating the X window, so that the
4728 icon-creation functions can say whose icon they're describing. */ 3297 icon-creation functions can say whose icon they're describing. */
4729 x_default_parameter (f, parms, Qicon_type, Qnil, 3298 x_default_parameter (f, parms, Qicon_type, Qt,
4730 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL); 3299 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4731 3300
4732 x_default_parameter (f, parms, Qauto_raise, Qnil, 3301 x_default_parameter (f, parms, Qauto_raise, Qnil,
4733 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); 3302 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4734 x_default_parameter (f, parms, Qauto_lower, Qnil, 3303 x_default_parameter (f, parms, Qauto_lower, Qnil,
4737 "cursorType", "CursorType", RES_TYPE_SYMBOL); 3306 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4738 x_default_parameter (f, parms, Qscroll_bar_width, Qnil, 3307 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4739 "scrollBarWidth", "ScrollBarWidth", 3308 "scrollBarWidth", "ScrollBarWidth",
4740 RES_TYPE_NUMBER); 3309 RES_TYPE_NUMBER);
4741 3310
4742 /* Dimensions, especially f->height, must be done via change_frame_size. 3311 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4743 Change will not be effected unless different from the current 3312 Change will not be effected unless different from the current
4744 f->height. */ 3313 FRAME_LINES (f). */
4745 width = f->width; 3314 width = FRAME_COLS (f);
4746 height = f->height; 3315 height = FRAME_LINES (f);
4747 3316
4748 f->height = 0; 3317 SET_FRAME_COLS (f, 0);
4749 SET_FRAME_WIDTH (f, 0); 3318 FRAME_LINES (f) = 0;
4750 change_frame_size (f, height, width, 1, 0, 0); 3319 change_frame_size (f, height, width, 1, 0, 0);
4751
4752 /* Set up faces after all frame parameters are known. This call
4753 also merges in face attributes specified for new frames. If we
4754 don't do this, the `menu' face for instance won't have the right
4755 colors, and the menu bar won't appear in the specified colors for
4756 new frames. */
4757 call1 (Qface_set_after_frame_default, frame);
4758 3320
4759 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) 3321 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
4760 /* Create the menu bar. */ 3322 /* Create the menu bar. */
4761 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) 3323 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4762 { 3324 {
4799 x_make_frame_visible (f); 3361 x_make_frame_visible (f);
4800 else 3362 else
4801 /* Must have been Qnil. */ 3363 /* Must have been Qnil. */
4802 ; 3364 ;
4803 } 3365 }
3366
3367 /* Set the WM leader property. GTK does this itself, so this is not
3368 needed when using GTK. */
3369 if (dpyinfo->client_leader_window != 0)
3370 {
3371 BLOCK_INPUT;
3372 XChangeProperty (FRAME_X_DISPLAY (f),
3373 FRAME_OUTER_WINDOW (f),
3374 dpyinfo->Xatom_wm_client_leader,
3375 XA_WINDOW, 32, PropModeReplace,
3376 (unsigned char *) &dpyinfo->client_leader_window, 1);
3377 UNBLOCK_INPUT;
3378 }
3379
3380 /* Initialize `default-minibuffer-frame' in case this is the first
3381 frame on this display device. */
3382 if (FRAME_HAS_MINIBUF_P (f)
3383 && (!FRAMEP (kb->Vdefault_minibuffer_frame)
3384 || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
3385 kb->Vdefault_minibuffer_frame = frame;
4804 3386
4805 UNGCPRO; 3387 UNGCPRO;
4806 3388
4807 /* Make sure windows on this frame appear in calls to next-window 3389 /* Make sure windows on this frame appear in calls to next-window
4808 and similar functions. */ 3390 and similar functions. */
5003 (display) 3585 (display)
5004 Lisp_Object display; 3586 Lisp_Object display;
5005 { 3587 {
5006 struct x_display_info *dpyinfo = check_x_display_info (display); 3588 struct x_display_info *dpyinfo = check_x_display_info (display);
5007 3589
5008 return make_number (DisplayCells (dpyinfo->display, 3590 int nr_planes = DisplayPlanes (dpyinfo->display,
5009 XScreenNumberOfScreen (dpyinfo->screen))); 3591 XScreenNumberOfScreen (dpyinfo->screen));
3592
3593 /* Truncate nr_planes to 24 to avoid integer overflow.
3594 Some displays says 32, but only 24 bits are actually significant.
3595 There are only very few and rare video cards that have more than
3596 24 significant bits. Also 24 bits is more than 16 million colors,
3597 it "should be enough for everyone". */
3598 if (nr_planes > 24) nr_planes = 24;
3599
3600 return make_number (1 << nr_planes);
5010 } 3601 }
5011 3602
5012 DEFUN ("x-server-max-request-size", Fx_server_max_request_size, 3603 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
5013 Sx_server_max_request_size, 3604 Sx_server_max_request_size,
5014 0, 1, 0, 3605 0, 1, 0,
5023 3614
5024 return make_number (MAXREQUEST (dpyinfo->display)); 3615 return make_number (MAXREQUEST (dpyinfo->display));
5025 } 3616 }
5026 3617
5027 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0, 3618 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
5028 doc: /* Returns the vendor ID string of the X server of display DISPLAY. 3619 doc: /* Returns the "vendor ID" string of the X server of display DISPLAY.
3620 \(Labelling every distributor as a "vendor" embodies the false assumption
3621 that operating systems cannot be developed and distributed noncommercially.)
5029 The optional argument DISPLAY specifies which display to ask about. 3622 The optional argument DISPLAY specifies which display to ask about.
5030 DISPLAY should be either a frame or a display name (a string). 3623 DISPLAY should be either a frame or a display name (a string).
5031 If omitted or nil, that stands for the selected frame's display. */) 3624 If omitted or nil, that stands for the selected frame's display. */)
5032 (display) 3625 (display)
5033 Lisp_Object display; 3626 Lisp_Object display;
5040 } 3633 }
5041 3634
5042 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0, 3635 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
5043 doc: /* Returns the version numbers of the X server of display DISPLAY. 3636 doc: /* Returns the version numbers of the X server of display DISPLAY.
5044 The value is a list of three integers: the major and minor 3637 The value is a list of three integers: the major and minor
5045 version numbers of the X Protocol in use, and the vendor-specific release 3638 version numbers of the X Protocol in use, and the distributor-specific release
5046 number. See also the function `x-server-vendor'. 3639 number. See also the function `x-server-vendor'.
5047 3640
5048 The optional argument DISPLAY specifies which display to ask about. 3641 The optional argument DISPLAY specifies which display to ask about.
5049 DISPLAY should be either a frame or a display name (a string). 3642 DISPLAY should be either a frame or a display name (a string).
5050 If omitted or nil, that stands for the selected frame's display. */) 3643 If omitted or nil, that stands for the selected frame's display. */)
5195 3788
5196 int 3789 int
5197 x_pixel_width (f) 3790 x_pixel_width (f)
5198 register struct frame *f; 3791 register struct frame *f;
5199 { 3792 {
5200 return PIXEL_WIDTH (f); 3793 return FRAME_PIXEL_WIDTH (f);
5201 } 3794 }
5202 3795
5203 int 3796 int
5204 x_pixel_height (f) 3797 x_pixel_height (f)
5205 register struct frame *f; 3798 register struct frame *f;
5206 { 3799 {
5207 return PIXEL_HEIGHT (f); 3800 return FRAME_PIXEL_HEIGHT (f);
5208 } 3801 }
5209 3802
5210 int 3803 int
5211 x_char_width (f) 3804 x_char_width (f)
5212 register struct frame *f; 3805 register struct frame *f;
5213 { 3806 {
5214 return FONT_WIDTH (f->output_data.x->font); 3807 return FRAME_COLUMN_WIDTH (f);
5215 } 3808 }
5216 3809
5217 int 3810 int
5218 x_char_height (f) 3811 x_char_height (f)
5219 register struct frame *f; 3812 register struct frame *f;
5220 { 3813 {
5221 return f->output_data.x->line_height; 3814 return FRAME_LINE_HEIGHT (f);
5222 } 3815 }
5223 3816
5224 int 3817 int
5225 x_screen_planes (f) 3818 x_screen_planes (f)
5226 register struct frame *f; 3819 register struct frame *f;
5465 BLOCK_INPUT; 4058 BLOCK_INPUT;
5466 /* Free the fonts in the font table. */ 4059 /* Free the fonts in the font table. */
5467 for (i = 0; i < dpyinfo->n_fonts; i++) 4060 for (i = 0; i < dpyinfo->n_fonts; i++)
5468 if (dpyinfo->font_table[i].name) 4061 if (dpyinfo->font_table[i].name)
5469 { 4062 {
5470 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
5471 xfree (dpyinfo->font_table[i].full_name);
5472 xfree (dpyinfo->font_table[i].name);
5473 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font); 4063 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5474 } 4064 }
5475 4065
5476 x_destroy_all_bitmaps (dpyinfo); 4066 x_destroy_all_bitmaps (dpyinfo);
5477 XSetCloseDownMode (dpyinfo->display, DestroyAll); 4067 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5531 UNBLOCK_INPUT; 4121 UNBLOCK_INPUT;
5532 } 4122 }
5533 4123
5534 4124
5535 /*********************************************************************** 4125 /***********************************************************************
5536 Image types
5537 ***********************************************************************/
5538
5539 /* Value is the number of elements of vector VECTOR. */
5540
5541 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5542
5543 /* List of supported image types. Use define_image_type to add new
5544 types. Use lookup_image_type to find a type for a given symbol. */
5545
5546 static struct image_type *image_types;
5547
5548 /* The symbol `image' which is the car of the lists used to represent
5549 images in Lisp. */
5550
5551 extern Lisp_Object Qimage;
5552
5553 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5554
5555 Lisp_Object Qxbm;
5556
5557 /* Keywords. */
5558
5559 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5560 extern Lisp_Object QCdata, QCtype;
5561 Lisp_Object QCascent, QCmargin, QCrelief;
5562 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
5563 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5564
5565 /* Other symbols. */
5566
5567 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5568
5569 /* Time in seconds after which images should be removed from the cache
5570 if not displayed. */
5571
5572 Lisp_Object Vimage_cache_eviction_delay;
5573
5574 /* Function prototypes. */
5575
5576 static void define_image_type P_ ((struct image_type *type));
5577 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5578 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5579 static void x_laplace P_ ((struct frame *, struct image *));
5580 static void x_emboss P_ ((struct frame *, struct image *));
5581 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5582 Lisp_Object));
5583
5584
5585 /* Define a new image type from TYPE. This adds a copy of TYPE to
5586 image_types and adds the symbol *TYPE->type to Vimage_types. */
5587
5588 static void
5589 define_image_type (type)
5590 struct image_type *type;
5591 {
5592 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5593 The initialized data segment is read-only. */
5594 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5595 bcopy (type, p, sizeof *p);
5596 p->next = image_types;
5597 image_types = p;
5598 Vimage_types = Fcons (*p->type, Vimage_types);
5599 }
5600
5601
5602 /* Look up image type SYMBOL, and return a pointer to its image_type
5603 structure. Value is null if SYMBOL is not a known image type. */
5604
5605 static INLINE struct image_type *
5606 lookup_image_type (symbol)
5607 Lisp_Object symbol;
5608 {
5609 struct image_type *type;
5610
5611 for (type = image_types; type; type = type->next)
5612 if (EQ (symbol, *type->type))
5613 break;
5614
5615 return type;
5616 }
5617
5618
5619 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5620 valid image specification is a list whose car is the symbol
5621 `image', and whose rest is a property list. The property list must
5622 contain a value for key `:type'. That value must be the name of a
5623 supported image type. The rest of the property list depends on the
5624 image type. */
5625
5626 int
5627 valid_image_p (object)
5628 Lisp_Object object;
5629 {
5630 int valid_p = 0;
5631
5632 if (CONSP (object) && EQ (XCAR (object), Qimage))
5633 {
5634 Lisp_Object tem;
5635
5636 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
5637 if (EQ (XCAR (tem), QCtype))
5638 {
5639 tem = XCDR (tem);
5640 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
5641 {
5642 struct image_type *type;
5643 type = lookup_image_type (XCAR (tem));
5644 if (type)
5645 valid_p = type->valid_p (object);
5646 }
5647
5648 break;
5649 }
5650 }
5651
5652 return valid_p;
5653 }
5654
5655
5656 /* Log error message with format string FORMAT and argument ARG.
5657 Signaling an error, e.g. when an image cannot be loaded, is not a
5658 good idea because this would interrupt redisplay, and the error
5659 message display would lead to another redisplay. This function
5660 therefore simply displays a message. */
5661
5662 static void
5663 image_error (format, arg1, arg2)
5664 char *format;
5665 Lisp_Object arg1, arg2;
5666 {
5667 add_to_log (format, arg1, arg2);
5668 }
5669
5670
5671
5672 /***********************************************************************
5673 Image specifications
5674 ***********************************************************************/
5675
5676 enum image_value_type
5677 {
5678 IMAGE_DONT_CHECK_VALUE_TYPE,
5679 IMAGE_STRING_VALUE,
5680 IMAGE_STRING_OR_NIL_VALUE,
5681 IMAGE_SYMBOL_VALUE,
5682 IMAGE_POSITIVE_INTEGER_VALUE,
5683 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
5684 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5685 IMAGE_ASCENT_VALUE,
5686 IMAGE_INTEGER_VALUE,
5687 IMAGE_FUNCTION_VALUE,
5688 IMAGE_NUMBER_VALUE,
5689 IMAGE_BOOL_VALUE
5690 };
5691
5692 /* Structure used when parsing image specifications. */
5693
5694 struct image_keyword
5695 {
5696 /* Name of keyword. */
5697 char *name;
5698
5699 /* The type of value allowed. */
5700 enum image_value_type type;
5701
5702 /* Non-zero means key must be present. */
5703 int mandatory_p;
5704
5705 /* Used to recognize duplicate keywords in a property list. */
5706 int count;
5707
5708 /* The value that was found. */
5709 Lisp_Object value;
5710 };
5711
5712
5713 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5714 int, Lisp_Object));
5715 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5716
5717
5718 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5719 has the format (image KEYWORD VALUE ...). One of the keyword/
5720 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5721 image_keywords structures of size NKEYWORDS describing other
5722 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5723
5724 static int
5725 parse_image_spec (spec, keywords, nkeywords, type)
5726 Lisp_Object spec;
5727 struct image_keyword *keywords;
5728 int nkeywords;
5729 Lisp_Object type;
5730 {
5731 int i;
5732 Lisp_Object plist;
5733
5734 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5735 return 0;
5736
5737 plist = XCDR (spec);
5738 while (CONSP (plist))
5739 {
5740 Lisp_Object key, value;
5741
5742 /* First element of a pair must be a symbol. */
5743 key = XCAR (plist);
5744 plist = XCDR (plist);
5745 if (!SYMBOLP (key))
5746 return 0;
5747
5748 /* There must follow a value. */
5749 if (!CONSP (plist))
5750 return 0;
5751 value = XCAR (plist);
5752 plist = XCDR (plist);
5753
5754 /* Find key in KEYWORDS. Error if not found. */
5755 for (i = 0; i < nkeywords; ++i)
5756 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
5757 break;
5758
5759 if (i == nkeywords)
5760 continue;
5761
5762 /* Record that we recognized the keyword. If a keywords
5763 was found more than once, it's an error. */
5764 keywords[i].value = value;
5765 ++keywords[i].count;
5766
5767 if (keywords[i].count > 1)
5768 return 0;
5769
5770 /* Check type of value against allowed type. */
5771 switch (keywords[i].type)
5772 {
5773 case IMAGE_STRING_VALUE:
5774 if (!STRINGP (value))
5775 return 0;
5776 break;
5777
5778 case IMAGE_STRING_OR_NIL_VALUE:
5779 if (!STRINGP (value) && !NILP (value))
5780 return 0;
5781 break;
5782
5783 case IMAGE_SYMBOL_VALUE:
5784 if (!SYMBOLP (value))
5785 return 0;
5786 break;
5787
5788 case IMAGE_POSITIVE_INTEGER_VALUE:
5789 if (!INTEGERP (value) || XINT (value) <= 0)
5790 return 0;
5791 break;
5792
5793 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
5794 if (INTEGERP (value) && XINT (value) >= 0)
5795 break;
5796 if (CONSP (value)
5797 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
5798 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
5799 break;
5800 return 0;
5801
5802 case IMAGE_ASCENT_VALUE:
5803 if (SYMBOLP (value) && EQ (value, Qcenter))
5804 break;
5805 else if (INTEGERP (value)
5806 && XINT (value) >= 0
5807 && XINT (value) <= 100)
5808 break;
5809 return 0;
5810
5811 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5812 if (!INTEGERP (value) || XINT (value) < 0)
5813 return 0;
5814 break;
5815
5816 case IMAGE_DONT_CHECK_VALUE_TYPE:
5817 break;
5818
5819 case IMAGE_FUNCTION_VALUE:
5820 value = indirect_function (value);
5821 if (SUBRP (value)
5822 || COMPILEDP (value)
5823 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5824 break;
5825 return 0;
5826
5827 case IMAGE_NUMBER_VALUE:
5828 if (!INTEGERP (value) && !FLOATP (value))
5829 return 0;
5830 break;
5831
5832 case IMAGE_INTEGER_VALUE:
5833 if (!INTEGERP (value))
5834 return 0;
5835 break;
5836
5837 case IMAGE_BOOL_VALUE:
5838 if (!NILP (value) && !EQ (value, Qt))
5839 return 0;
5840 break;
5841
5842 default:
5843 abort ();
5844 break;
5845 }
5846
5847 if (EQ (key, QCtype) && !EQ (type, value))
5848 return 0;
5849 }
5850
5851 /* Check that all mandatory fields are present. */
5852 for (i = 0; i < nkeywords; ++i)
5853 if (keywords[i].mandatory_p && keywords[i].count == 0)
5854 return 0;
5855
5856 return NILP (plist);
5857 }
5858
5859
5860 /* Return the value of KEY in image specification SPEC. Value is nil
5861 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5862 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5863
5864 static Lisp_Object
5865 image_spec_value (spec, key, found)
5866 Lisp_Object spec, key;
5867 int *found;
5868 {
5869 Lisp_Object tail;
5870
5871 xassert (valid_image_p (spec));
5872
5873 for (tail = XCDR (spec);
5874 CONSP (tail) && CONSP (XCDR (tail));
5875 tail = XCDR (XCDR (tail)))
5876 {
5877 if (EQ (XCAR (tail), key))
5878 {
5879 if (found)
5880 *found = 1;
5881 return XCAR (XCDR (tail));
5882 }
5883 }
5884
5885 if (found)
5886 *found = 0;
5887 return Qnil;
5888 }
5889
5890
5891 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5892 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5893 PIXELS non-nil means return the size in pixels, otherwise return the
5894 size in canonical character units.
5895 FRAME is the frame on which the image will be displayed. FRAME nil
5896 or omitted means use the selected frame. */)
5897 (spec, pixels, frame)
5898 Lisp_Object spec, pixels, frame;
5899 {
5900 Lisp_Object size;
5901
5902 size = Qnil;
5903 if (valid_image_p (spec))
5904 {
5905 struct frame *f = check_x_frame (frame);
5906 int id = lookup_image (f, spec);
5907 struct image *img = IMAGE_FROM_ID (f, id);
5908 int width = img->width + 2 * img->hmargin;
5909 int height = img->height + 2 * img->vmargin;
5910
5911 if (NILP (pixels))
5912 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5913 make_float ((double) height / CANON_Y_UNIT (f)));
5914 else
5915 size = Fcons (make_number (width), make_number (height));
5916 }
5917 else
5918 error ("Invalid image specification");
5919
5920 return size;
5921 }
5922
5923
5924 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5925 doc: /* Return t if image SPEC has a mask bitmap.
5926 FRAME is the frame on which the image will be displayed. FRAME nil
5927 or omitted means use the selected frame. */)
5928 (spec, frame)
5929 Lisp_Object spec, frame;
5930 {
5931 Lisp_Object mask;
5932
5933 mask = Qnil;
5934 if (valid_image_p (spec))
5935 {
5936 struct frame *f = check_x_frame (frame);
5937 int id = lookup_image (f, spec);
5938 struct image *img = IMAGE_FROM_ID (f, id);
5939 if (img->mask)
5940 mask = Qt;
5941 }
5942 else
5943 error ("Invalid image specification");
5944
5945 return mask;
5946 }
5947
5948
5949
5950 /***********************************************************************
5951 Image type independent image structures
5952 ***********************************************************************/
5953
5954 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5955 static void free_image P_ ((struct frame *f, struct image *img));
5956
5957
5958 /* Allocate and return a new image structure for image specification
5959 SPEC. SPEC has a hash value of HASH. */
5960
5961 static struct image *
5962 make_image (spec, hash)
5963 Lisp_Object spec;
5964 unsigned hash;
5965 {
5966 struct image *img = (struct image *) xmalloc (sizeof *img);
5967
5968 xassert (valid_image_p (spec));
5969 bzero (img, sizeof *img);
5970 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5971 xassert (img->type != NULL);
5972 img->spec = spec;
5973 img->data.lisp_val = Qnil;
5974 img->ascent = DEFAULT_IMAGE_ASCENT;
5975 img->hash = hash;
5976 return img;
5977 }
5978
5979
5980 /* Free image IMG which was used on frame F, including its resources. */
5981
5982 static void
5983 free_image (f, img)
5984 struct frame *f;
5985 struct image *img;
5986 {
5987 if (img)
5988 {
5989 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5990
5991 /* Remove IMG from the hash table of its cache. */
5992 if (img->prev)
5993 img->prev->next = img->next;
5994 else
5995 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5996
5997 if (img->next)
5998 img->next->prev = img->prev;
5999
6000 c->images[img->id] = NULL;
6001
6002 /* Free resources, then free IMG. */
6003 img->type->free (f, img);
6004 xfree (img);
6005 }
6006 }
6007
6008
6009 /* Prepare image IMG for display on frame F. Must be called before
6010 drawing an image. */
6011
6012 void
6013 prepare_image_for_display (f, img)
6014 struct frame *f;
6015 struct image *img;
6016 {
6017 EMACS_TIME t;
6018
6019 /* We're about to display IMG, so set its timestamp to `now'. */
6020 EMACS_GET_TIME (t);
6021 img->timestamp = EMACS_SECS (t);
6022
6023 /* If IMG doesn't have a pixmap yet, load it now, using the image
6024 type dependent loader function. */
6025 if (img->pixmap == None && !img->load_failed_p)
6026 img->load_failed_p = img->type->load (f, img) == 0;
6027 }
6028
6029
6030 /* Value is the number of pixels for the ascent of image IMG when
6031 drawn in face FACE. */
6032
6033 int
6034 image_ascent (img, face)
6035 struct image *img;
6036 struct face *face;
6037 {
6038 int height = img->height + img->vmargin;
6039 int ascent;
6040
6041 if (img->ascent == CENTERED_IMAGE_ASCENT)
6042 {
6043 if (face->font)
6044 /* This expression is arranged so that if the image can't be
6045 exactly centered, it will be moved slightly up. This is
6046 because a typical font is `top-heavy' (due to the presence
6047 uppercase letters), so the image placement should err towards
6048 being top-heavy too. It also just generally looks better. */
6049 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
6050 else
6051 ascent = height / 2;
6052 }
6053 else
6054 ascent = height * img->ascent / 100.0;
6055
6056 return ascent;
6057 }
6058
6059
6060 /* Image background colors. */
6061
6062 static unsigned long
6063 four_corners_best (ximg, width, height)
6064 XImage *ximg;
6065 unsigned long width, height;
6066 {
6067 unsigned long corners[4], best;
6068 int i, best_count;
6069
6070 /* Get the colors at the corners of ximg. */
6071 corners[0] = XGetPixel (ximg, 0, 0);
6072 corners[1] = XGetPixel (ximg, width - 1, 0);
6073 corners[2] = XGetPixel (ximg, width - 1, height - 1);
6074 corners[3] = XGetPixel (ximg, 0, height - 1);
6075
6076 /* Choose the most frequently found color as background. */
6077 for (i = best_count = 0; i < 4; ++i)
6078 {
6079 int j, n;
6080
6081 for (j = n = 0; j < 4; ++j)
6082 if (corners[i] == corners[j])
6083 ++n;
6084
6085 if (n > best_count)
6086 best = corners[i], best_count = n;
6087 }
6088
6089 return best;
6090 }
6091
6092 /* Return the `background' field of IMG. If IMG doesn't have one yet,
6093 it is guessed heuristically. If non-zero, XIMG is an existing XImage
6094 object to use for the heuristic. */
6095
6096 unsigned long
6097 image_background (img, f, ximg)
6098 struct image *img;
6099 struct frame *f;
6100 XImage *ximg;
6101 {
6102 if (! img->background_valid)
6103 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6104 {
6105 int free_ximg = !ximg;
6106
6107 if (! ximg)
6108 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
6109 0, 0, img->width, img->height, ~0, ZPixmap);
6110
6111 img->background = four_corners_best (ximg, img->width, img->height);
6112
6113 if (free_ximg)
6114 XDestroyImage (ximg);
6115
6116 img->background_valid = 1;
6117 }
6118
6119 return img->background;
6120 }
6121
6122 /* Return the `background_transparent' field of IMG. If IMG doesn't
6123 have one yet, it is guessed heuristically. If non-zero, MASK is an
6124 existing XImage object to use for the heuristic. */
6125
6126 int
6127 image_background_transparent (img, f, mask)
6128 struct image *img;
6129 struct frame *f;
6130 XImage *mask;
6131 {
6132 if (! img->background_transparent_valid)
6133 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6134 {
6135 if (img->mask)
6136 {
6137 int free_mask = !mask;
6138
6139 if (! mask)
6140 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
6141 0, 0, img->width, img->height, ~0, ZPixmap);
6142
6143 img->background_transparent
6144 = !four_corners_best (mask, img->width, img->height);
6145
6146 if (free_mask)
6147 XDestroyImage (mask);
6148 }
6149 else
6150 img->background_transparent = 0;
6151
6152 img->background_transparent_valid = 1;
6153 }
6154
6155 return img->background_transparent;
6156 }
6157
6158
6159 /***********************************************************************
6160 Helper functions for X image types
6161 ***********************************************************************/
6162
6163 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
6164 int, int));
6165 static void x_clear_image P_ ((struct frame *f, struct image *img));
6166 static unsigned long x_alloc_image_color P_ ((struct frame *f,
6167 struct image *img,
6168 Lisp_Object color_name,
6169 unsigned long dflt));
6170
6171
6172 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6173 free the pixmap if any. MASK_P non-zero means clear the mask
6174 pixmap if any. COLORS_P non-zero means free colors allocated for
6175 the image, if any. */
6176
6177 static void
6178 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
6179 struct frame *f;
6180 struct image *img;
6181 int pixmap_p, mask_p, colors_p;
6182 {
6183 if (pixmap_p && img->pixmap)
6184 {
6185 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
6186 img->pixmap = None;
6187 img->background_valid = 0;
6188 }
6189
6190 if (mask_p && img->mask)
6191 {
6192 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6193 img->mask = None;
6194 img->background_transparent_valid = 0;
6195 }
6196
6197 if (colors_p && img->ncolors)
6198 {
6199 x_free_colors (f, img->colors, img->ncolors);
6200 xfree (img->colors);
6201 img->colors = NULL;
6202 img->ncolors = 0;
6203 }
6204 }
6205
6206 /* Free X resources of image IMG which is used on frame F. */
6207
6208 static void
6209 x_clear_image (f, img)
6210 struct frame *f;
6211 struct image *img;
6212 {
6213 BLOCK_INPUT;
6214 x_clear_image_1 (f, img, 1, 1, 1);
6215 UNBLOCK_INPUT;
6216 }
6217
6218
6219 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6220 cannot be allocated, use DFLT. Add a newly allocated color to
6221 IMG->colors, so that it can be freed again. Value is the pixel
6222 color. */
6223
6224 static unsigned long
6225 x_alloc_image_color (f, img, color_name, dflt)
6226 struct frame *f;
6227 struct image *img;
6228 Lisp_Object color_name;
6229 unsigned long dflt;
6230 {
6231 XColor color;
6232 unsigned long result;
6233
6234 xassert (STRINGP (color_name));
6235
6236 if (x_defined_color (f, SDATA (color_name), &color, 1))
6237 {
6238 /* This isn't called frequently so we get away with simply
6239 reallocating the color vector to the needed size, here. */
6240 ++img->ncolors;
6241 img->colors =
6242 (unsigned long *) xrealloc (img->colors,
6243 img->ncolors * sizeof *img->colors);
6244 img->colors[img->ncolors - 1] = color.pixel;
6245 result = color.pixel;
6246 }
6247 else
6248 result = dflt;
6249
6250 return result;
6251 }
6252
6253
6254
6255 /***********************************************************************
6256 Image Cache
6257 ***********************************************************************/
6258
6259 static void cache_image P_ ((struct frame *f, struct image *img));
6260 static void postprocess_image P_ ((struct frame *, struct image *));
6261
6262
6263 /* Return a new, initialized image cache that is allocated from the
6264 heap. Call free_image_cache to free an image cache. */
6265
6266 struct image_cache *
6267 make_image_cache ()
6268 {
6269 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
6270 int size;
6271
6272 bzero (c, sizeof *c);
6273 c->size = 50;
6274 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
6275 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
6276 c->buckets = (struct image **) xmalloc (size);
6277 bzero (c->buckets, size);
6278 return c;
6279 }
6280
6281
6282 /* Free image cache of frame F. Be aware that X frames share images
6283 caches. */
6284
6285 void
6286 free_image_cache (f)
6287 struct frame *f;
6288 {
6289 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6290 if (c)
6291 {
6292 int i;
6293
6294 /* Cache should not be referenced by any frame when freed. */
6295 xassert (c->refcount == 0);
6296
6297 for (i = 0; i < c->used; ++i)
6298 free_image (f, c->images[i]);
6299 xfree (c->images);
6300 xfree (c->buckets);
6301 xfree (c);
6302 FRAME_X_IMAGE_CACHE (f) = NULL;
6303 }
6304 }
6305
6306
6307 /* Clear image cache of frame F. FORCE_P non-zero means free all
6308 images. FORCE_P zero means clear only images that haven't been
6309 displayed for some time. Should be called from time to time to
6310 reduce the number of loaded images. If image-eviction-seconds is
6311 non-nil, this frees images in the cache which weren't displayed for
6312 at least that many seconds. */
6313
6314 void
6315 clear_image_cache (f, force_p)
6316 struct frame *f;
6317 int force_p;
6318 {
6319 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6320
6321 if (c && INTEGERP (Vimage_cache_eviction_delay))
6322 {
6323 EMACS_TIME t;
6324 unsigned long old;
6325 int i, nfreed;
6326
6327 EMACS_GET_TIME (t);
6328 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
6329
6330 /* Block input so that we won't be interrupted by a SIGIO
6331 while being in an inconsistent state. */
6332 BLOCK_INPUT;
6333
6334 for (i = nfreed = 0; i < c->used; ++i)
6335 {
6336 struct image *img = c->images[i];
6337 if (img != NULL
6338 && (force_p || img->timestamp < old))
6339 {
6340 free_image (f, img);
6341 ++nfreed;
6342 }
6343 }
6344
6345 /* We may be clearing the image cache because, for example,
6346 Emacs was iconified for a longer period of time. In that
6347 case, current matrices may still contain references to
6348 images freed above. So, clear these matrices. */
6349 if (nfreed)
6350 {
6351 Lisp_Object tail, frame;
6352
6353 FOR_EACH_FRAME (tail, frame)
6354 {
6355 struct frame *f = XFRAME (frame);
6356 if (FRAME_X_P (f)
6357 && FRAME_X_IMAGE_CACHE (f) == c)
6358 clear_current_matrices (f);
6359 }
6360
6361 ++windows_or_buffers_changed;
6362 }
6363
6364 UNBLOCK_INPUT;
6365 }
6366 }
6367
6368
6369 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
6370 0, 1, 0,
6371 doc: /* Clear the image cache of FRAME.
6372 FRAME nil or omitted means use the selected frame.
6373 FRAME t means clear the image caches of all frames. */)
6374 (frame)
6375 Lisp_Object frame;
6376 {
6377 if (EQ (frame, Qt))
6378 {
6379 Lisp_Object tail;
6380
6381 FOR_EACH_FRAME (tail, frame)
6382 if (FRAME_X_P (XFRAME (frame)))
6383 clear_image_cache (XFRAME (frame), 1);
6384 }
6385 else
6386 clear_image_cache (check_x_frame (frame), 1);
6387
6388 return Qnil;
6389 }
6390
6391
6392 /* Compute masks and transform image IMG on frame F, as specified
6393 by the image's specification, */
6394
6395 static void
6396 postprocess_image (f, img)
6397 struct frame *f;
6398 struct image *img;
6399 {
6400 /* Manipulation of the image's mask. */
6401 if (img->pixmap)
6402 {
6403 Lisp_Object conversion, spec;
6404 Lisp_Object mask;
6405
6406 spec = img->spec;
6407
6408 /* `:heuristic-mask t'
6409 `:mask heuristic'
6410 means build a mask heuristically.
6411 `:heuristic-mask (R G B)'
6412 `:mask (heuristic (R G B))'
6413 means build a mask from color (R G B) in the
6414 image.
6415 `:mask nil'
6416 means remove a mask, if any. */
6417
6418 mask = image_spec_value (spec, QCheuristic_mask, NULL);
6419 if (!NILP (mask))
6420 x_build_heuristic_mask (f, img, mask);
6421 else
6422 {
6423 int found_p;
6424
6425 mask = image_spec_value (spec, QCmask, &found_p);
6426
6427 if (EQ (mask, Qheuristic))
6428 x_build_heuristic_mask (f, img, Qt);
6429 else if (CONSP (mask)
6430 && EQ (XCAR (mask), Qheuristic))
6431 {
6432 if (CONSP (XCDR (mask)))
6433 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
6434 else
6435 x_build_heuristic_mask (f, img, XCDR (mask));
6436 }
6437 else if (NILP (mask) && found_p && img->mask)
6438 {
6439 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6440 img->mask = None;
6441 }
6442 }
6443
6444
6445 /* Should we apply an image transformation algorithm? */
6446 conversion = image_spec_value (spec, QCconversion, NULL);
6447 if (EQ (conversion, Qdisabled))
6448 x_disable_image (f, img);
6449 else if (EQ (conversion, Qlaplace))
6450 x_laplace (f, img);
6451 else if (EQ (conversion, Qemboss))
6452 x_emboss (f, img);
6453 else if (CONSP (conversion)
6454 && EQ (XCAR (conversion), Qedge_detection))
6455 {
6456 Lisp_Object tem;
6457 tem = XCDR (conversion);
6458 if (CONSP (tem))
6459 x_edge_detection (f, img,
6460 Fplist_get (tem, QCmatrix),
6461 Fplist_get (tem, QCcolor_adjustment));
6462 }
6463 }
6464 }
6465
6466
6467 /* Return the id of image with Lisp specification SPEC on frame F.
6468 SPEC must be a valid Lisp image specification (see valid_image_p). */
6469
6470 int
6471 lookup_image (f, spec)
6472 struct frame *f;
6473 Lisp_Object spec;
6474 {
6475 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6476 struct image *img;
6477 int i;
6478 unsigned hash;
6479 struct gcpro gcpro1;
6480 EMACS_TIME now;
6481
6482 /* F must be a window-system frame, and SPEC must be a valid image
6483 specification. */
6484 xassert (FRAME_WINDOW_P (f));
6485 xassert (valid_image_p (spec));
6486
6487 GCPRO1 (spec);
6488
6489 /* Look up SPEC in the hash table of the image cache. */
6490 hash = sxhash (spec, 0);
6491 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6492
6493 for (img = c->buckets[i]; img; img = img->next)
6494 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6495 break;
6496
6497 /* If not found, create a new image and cache it. */
6498 if (img == NULL)
6499 {
6500 extern Lisp_Object Qpostscript;
6501
6502 BLOCK_INPUT;
6503 img = make_image (spec, hash);
6504 cache_image (f, img);
6505 img->load_failed_p = img->type->load (f, img) == 0;
6506
6507 /* If we can't load the image, and we don't have a width and
6508 height, use some arbitrary width and height so that we can
6509 draw a rectangle for it. */
6510 if (img->load_failed_p)
6511 {
6512 Lisp_Object value;
6513
6514 value = image_spec_value (spec, QCwidth, NULL);
6515 img->width = (INTEGERP (value)
6516 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6517 value = image_spec_value (spec, QCheight, NULL);
6518 img->height = (INTEGERP (value)
6519 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6520 }
6521 else
6522 {
6523 /* Handle image type independent image attributes
6524 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6525 `:background COLOR'. */
6526 Lisp_Object ascent, margin, relief, bg;
6527
6528 ascent = image_spec_value (spec, QCascent, NULL);
6529 if (INTEGERP (ascent))
6530 img->ascent = XFASTINT (ascent);
6531 else if (EQ (ascent, Qcenter))
6532 img->ascent = CENTERED_IMAGE_ASCENT;
6533
6534 margin = image_spec_value (spec, QCmargin, NULL);
6535 if (INTEGERP (margin) && XINT (margin) >= 0)
6536 img->vmargin = img->hmargin = XFASTINT (margin);
6537 else if (CONSP (margin) && INTEGERP (XCAR (margin))
6538 && INTEGERP (XCDR (margin)))
6539 {
6540 if (XINT (XCAR (margin)) > 0)
6541 img->hmargin = XFASTINT (XCAR (margin));
6542 if (XINT (XCDR (margin)) > 0)
6543 img->vmargin = XFASTINT (XCDR (margin));
6544 }
6545
6546 relief = image_spec_value (spec, QCrelief, NULL);
6547 if (INTEGERP (relief))
6548 {
6549 img->relief = XINT (relief);
6550 img->hmargin += abs (img->relief);
6551 img->vmargin += abs (img->relief);
6552 }
6553
6554 if (! img->background_valid)
6555 {
6556 bg = image_spec_value (img->spec, QCbackground, NULL);
6557 if (!NILP (bg))
6558 {
6559 img->background
6560 = x_alloc_image_color (f, img, bg,
6561 FRAME_BACKGROUND_PIXEL (f));
6562 img->background_valid = 1;
6563 }
6564 }
6565
6566 /* Do image transformations and compute masks, unless we
6567 don't have the image yet. */
6568 if (!EQ (*img->type->type, Qpostscript))
6569 postprocess_image (f, img);
6570 }
6571
6572 UNBLOCK_INPUT;
6573 xassert (!interrupt_input_blocked);
6574 }
6575
6576 /* We're using IMG, so set its timestamp to `now'. */
6577 EMACS_GET_TIME (now);
6578 img->timestamp = EMACS_SECS (now);
6579
6580 UNGCPRO;
6581
6582 /* Value is the image id. */
6583 return img->id;
6584 }
6585
6586
6587 /* Cache image IMG in the image cache of frame F. */
6588
6589 static void
6590 cache_image (f, img)
6591 struct frame *f;
6592 struct image *img;
6593 {
6594 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6595 int i;
6596
6597 /* Find a free slot in c->images. */
6598 for (i = 0; i < c->used; ++i)
6599 if (c->images[i] == NULL)
6600 break;
6601
6602 /* If no free slot found, maybe enlarge c->images. */
6603 if (i == c->used && c->used == c->size)
6604 {
6605 c->size *= 2;
6606 c->images = (struct image **) xrealloc (c->images,
6607 c->size * sizeof *c->images);
6608 }
6609
6610 /* Add IMG to c->images, and assign IMG an id. */
6611 c->images[i] = img;
6612 img->id = i;
6613 if (i == c->used)
6614 ++c->used;
6615
6616 /* Add IMG to the cache's hash table. */
6617 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6618 img->next = c->buckets[i];
6619 if (img->next)
6620 img->next->prev = img;
6621 img->prev = NULL;
6622 c->buckets[i] = img;
6623 }
6624
6625
6626 /* Call FN on every image in the image cache of frame F. Used to mark
6627 Lisp Objects in the image cache. */
6628
6629 void
6630 forall_images_in_image_cache (f, fn)
6631 struct frame *f;
6632 void (*fn) P_ ((struct image *img));
6633 {
6634 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6635 {
6636 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6637 if (c)
6638 {
6639 int i;
6640 for (i = 0; i < c->used; ++i)
6641 if (c->images[i])
6642 fn (c->images[i]);
6643 }
6644 }
6645 }
6646
6647
6648
6649 /***********************************************************************
6650 X support code
6651 ***********************************************************************/
6652
6653 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6654 XImage **, Pixmap *));
6655 static void x_destroy_x_image P_ ((XImage *));
6656 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6657
6658
6659 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6660 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6661 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6662 via xmalloc. Print error messages via image_error if an error
6663 occurs. Value is non-zero if successful. */
6664
6665 static int
6666 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6667 struct frame *f;
6668 int width, height, depth;
6669 XImage **ximg;
6670 Pixmap *pixmap;
6671 {
6672 Display *display = FRAME_X_DISPLAY (f);
6673 Screen *screen = FRAME_X_SCREEN (f);
6674 Window window = FRAME_X_WINDOW (f);
6675
6676 xassert (interrupt_input_blocked);
6677
6678 if (depth <= 0)
6679 depth = DefaultDepthOfScreen (screen);
6680 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6681 depth, ZPixmap, 0, NULL, width, height,
6682 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6683 if (*ximg == NULL)
6684 {
6685 image_error ("Unable to allocate X image", Qnil, Qnil);
6686 return 0;
6687 }
6688
6689 /* Allocate image raster. */
6690 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6691
6692 /* Allocate a pixmap of the same size. */
6693 *pixmap = XCreatePixmap (display, window, width, height, depth);
6694 if (*pixmap == None)
6695 {
6696 x_destroy_x_image (*ximg);
6697 *ximg = NULL;
6698 image_error ("Unable to create X pixmap", Qnil, Qnil);
6699 return 0;
6700 }
6701
6702 return 1;
6703 }
6704
6705
6706 /* Destroy XImage XIMG. Free XIMG->data. */
6707
6708 static void
6709 x_destroy_x_image (ximg)
6710 XImage *ximg;
6711 {
6712 xassert (interrupt_input_blocked);
6713 if (ximg)
6714 {
6715 xfree (ximg->data);
6716 ximg->data = NULL;
6717 XDestroyImage (ximg);
6718 }
6719 }
6720
6721
6722 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6723 are width and height of both the image and pixmap. */
6724
6725 static void
6726 x_put_x_image (f, ximg, pixmap, width, height)
6727 struct frame *f;
6728 XImage *ximg;
6729 Pixmap pixmap;
6730 int width, height;
6731 {
6732 GC gc;
6733
6734 xassert (interrupt_input_blocked);
6735 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6736 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6737 XFreeGC (FRAME_X_DISPLAY (f), gc);
6738 }
6739
6740
6741
6742 /***********************************************************************
6743 File Handling
6744 ***********************************************************************/
6745
6746 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6747 static char *slurp_file P_ ((char *, int *));
6748
6749
6750 /* Find image file FILE. Look in data-directory, then
6751 x-bitmap-file-path. Value is the full name of the file found, or
6752 nil if not found. */
6753
6754 static Lisp_Object
6755 x_find_image_file (file)
6756 Lisp_Object file;
6757 {
6758 Lisp_Object file_found, search_path;
6759 struct gcpro gcpro1, gcpro2;
6760 int fd;
6761
6762 file_found = Qnil;
6763 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6764 GCPRO2 (file_found, search_path);
6765
6766 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6767 fd = openp (search_path, file, Qnil, &file_found, Qnil);
6768
6769 if (fd == -1)
6770 file_found = Qnil;
6771 else
6772 close (fd);
6773
6774 UNGCPRO;
6775 return file_found;
6776 }
6777
6778
6779 /* Read FILE into memory. Value is a pointer to a buffer allocated
6780 with xmalloc holding FILE's contents. Value is null if an error
6781 occurred. *SIZE is set to the size of the file. */
6782
6783 static char *
6784 slurp_file (file, size)
6785 char *file;
6786 int *size;
6787 {
6788 FILE *fp = NULL;
6789 char *buf = NULL;
6790 struct stat st;
6791
6792 if (stat (file, &st) == 0
6793 && (fp = fopen (file, "r")) != NULL
6794 && (buf = (char *) xmalloc (st.st_size),
6795 fread (buf, 1, st.st_size, fp) == st.st_size))
6796 {
6797 *size = st.st_size;
6798 fclose (fp);
6799 }
6800 else
6801 {
6802 if (fp)
6803 fclose (fp);
6804 if (buf)
6805 {
6806 xfree (buf);
6807 buf = NULL;
6808 }
6809 }
6810
6811 return buf;
6812 }
6813
6814
6815
6816 /***********************************************************************
6817 XBM images
6818 ***********************************************************************/
6819
6820 static int xbm_scan P_ ((char **, char *, char *, int *));
6821 static int xbm_load P_ ((struct frame *f, struct image *img));
6822 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6823 char *, char *));
6824 static int xbm_image_p P_ ((Lisp_Object object));
6825 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6826 unsigned char **));
6827 static int xbm_file_p P_ ((Lisp_Object));
6828
6829
6830 /* Indices of image specification fields in xbm_format, below. */
6831
6832 enum xbm_keyword_index
6833 {
6834 XBM_TYPE,
6835 XBM_FILE,
6836 XBM_WIDTH,
6837 XBM_HEIGHT,
6838 XBM_DATA,
6839 XBM_FOREGROUND,
6840 XBM_BACKGROUND,
6841 XBM_ASCENT,
6842 XBM_MARGIN,
6843 XBM_RELIEF,
6844 XBM_ALGORITHM,
6845 XBM_HEURISTIC_MASK,
6846 XBM_MASK,
6847 XBM_LAST
6848 };
6849
6850 /* Vector of image_keyword structures describing the format
6851 of valid XBM image specifications. */
6852
6853 static struct image_keyword xbm_format[XBM_LAST] =
6854 {
6855 {":type", IMAGE_SYMBOL_VALUE, 1},
6856 {":file", IMAGE_STRING_VALUE, 0},
6857 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6858 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6859 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6860 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6861 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6862 {":ascent", IMAGE_ASCENT_VALUE, 0},
6863 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6864 {":relief", IMAGE_INTEGER_VALUE, 0},
6865 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6866 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6867 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6868 };
6869
6870 /* Structure describing the image type XBM. */
6871
6872 static struct image_type xbm_type =
6873 {
6874 &Qxbm,
6875 xbm_image_p,
6876 xbm_load,
6877 x_clear_image,
6878 NULL
6879 };
6880
6881 /* Tokens returned from xbm_scan. */
6882
6883 enum xbm_token
6884 {
6885 XBM_TK_IDENT = 256,
6886 XBM_TK_NUMBER
6887 };
6888
6889
6890 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6891 A valid specification is a list starting with the symbol `image'
6892 The rest of the list is a property list which must contain an
6893 entry `:type xbm..
6894
6895 If the specification specifies a file to load, it must contain
6896 an entry `:file FILENAME' where FILENAME is a string.
6897
6898 If the specification is for a bitmap loaded from memory it must
6899 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6900 WIDTH and HEIGHT are integers > 0. DATA may be:
6901
6902 1. a string large enough to hold the bitmap data, i.e. it must
6903 have a size >= (WIDTH + 7) / 8 * HEIGHT
6904
6905 2. a bool-vector of size >= WIDTH * HEIGHT
6906
6907 3. a vector of strings or bool-vectors, one for each line of the
6908 bitmap.
6909
6910 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6911 may not be specified in this case because they are defined in the
6912 XBM file.
6913
6914 Both the file and data forms may contain the additional entries
6915 `:background COLOR' and `:foreground COLOR'. If not present,
6916 foreground and background of the frame on which the image is
6917 displayed is used. */
6918
6919 static int
6920 xbm_image_p (object)
6921 Lisp_Object object;
6922 {
6923 struct image_keyword kw[XBM_LAST];
6924
6925 bcopy (xbm_format, kw, sizeof kw);
6926 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6927 return 0;
6928
6929 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6930
6931 if (kw[XBM_FILE].count)
6932 {
6933 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6934 return 0;
6935 }
6936 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6937 {
6938 /* In-memory XBM file. */
6939 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6940 return 0;
6941 }
6942 else
6943 {
6944 Lisp_Object data;
6945 int width, height;
6946
6947 /* Entries for `:width', `:height' and `:data' must be present. */
6948 if (!kw[XBM_WIDTH].count
6949 || !kw[XBM_HEIGHT].count
6950 || !kw[XBM_DATA].count)
6951 return 0;
6952
6953 data = kw[XBM_DATA].value;
6954 width = XFASTINT (kw[XBM_WIDTH].value);
6955 height = XFASTINT (kw[XBM_HEIGHT].value);
6956
6957 /* Check type of data, and width and height against contents of
6958 data. */
6959 if (VECTORP (data))
6960 {
6961 int i;
6962
6963 /* Number of elements of the vector must be >= height. */
6964 if (XVECTOR (data)->size < height)
6965 return 0;
6966
6967 /* Each string or bool-vector in data must be large enough
6968 for one line of the image. */
6969 for (i = 0; i < height; ++i)
6970 {
6971 Lisp_Object elt = XVECTOR (data)->contents[i];
6972
6973 if (STRINGP (elt))
6974 {
6975 if (SCHARS (elt)
6976 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6977 return 0;
6978 }
6979 else if (BOOL_VECTOR_P (elt))
6980 {
6981 if (XBOOL_VECTOR (elt)->size < width)
6982 return 0;
6983 }
6984 else
6985 return 0;
6986 }
6987 }
6988 else if (STRINGP (data))
6989 {
6990 if (SCHARS (data)
6991 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6992 return 0;
6993 }
6994 else if (BOOL_VECTOR_P (data))
6995 {
6996 if (XBOOL_VECTOR (data)->size < width * height)
6997 return 0;
6998 }
6999 else
7000 return 0;
7001 }
7002
7003 return 1;
7004 }
7005
7006
7007 /* Scan a bitmap file. FP is the stream to read from. Value is
7008 either an enumerator from enum xbm_token, or a character for a
7009 single-character token, or 0 at end of file. If scanning an
7010 identifier, store the lexeme of the identifier in SVAL. If
7011 scanning a number, store its value in *IVAL. */
7012
7013 static int
7014 xbm_scan (s, end, sval, ival)
7015 char **s, *end;
7016 char *sval;
7017 int *ival;
7018 {
7019 int c;
7020
7021 loop:
7022
7023 /* Skip white space. */
7024 while (*s < end && (c = *(*s)++, isspace (c)))
7025 ;
7026
7027 if (*s >= end)
7028 c = 0;
7029 else if (isdigit (c))
7030 {
7031 int value = 0, digit;
7032
7033 if (c == '0' && *s < end)
7034 {
7035 c = *(*s)++;
7036 if (c == 'x' || c == 'X')
7037 {
7038 while (*s < end)
7039 {
7040 c = *(*s)++;
7041 if (isdigit (c))
7042 digit = c - '0';
7043 else if (c >= 'a' && c <= 'f')
7044 digit = c - 'a' + 10;
7045 else if (c >= 'A' && c <= 'F')
7046 digit = c - 'A' + 10;
7047 else
7048 break;
7049 value = 16 * value + digit;
7050 }
7051 }
7052 else if (isdigit (c))
7053 {
7054 value = c - '0';
7055 while (*s < end
7056 && (c = *(*s)++, isdigit (c)))
7057 value = 8 * value + c - '0';
7058 }
7059 }
7060 else
7061 {
7062 value = c - '0';
7063 while (*s < end
7064 && (c = *(*s)++, isdigit (c)))
7065 value = 10 * value + c - '0';
7066 }
7067
7068 if (*s < end)
7069 *s = *s - 1;
7070 *ival = value;
7071 c = XBM_TK_NUMBER;
7072 }
7073 else if (isalpha (c) || c == '_')
7074 {
7075 *sval++ = c;
7076 while (*s < end
7077 && (c = *(*s)++, (isalnum (c) || c == '_')))
7078 *sval++ = c;
7079 *sval = 0;
7080 if (*s < end)
7081 *s = *s - 1;
7082 c = XBM_TK_IDENT;
7083 }
7084 else if (c == '/' && **s == '*')
7085 {
7086 /* C-style comment. */
7087 ++*s;
7088 while (**s && (**s != '*' || *(*s + 1) != '/'))
7089 ++*s;
7090 if (**s)
7091 {
7092 *s += 2;
7093 goto loop;
7094 }
7095 }
7096
7097 return c;
7098 }
7099
7100
7101 /* Replacement for XReadBitmapFileData which isn't available under old
7102 X versions. CONTENTS is a pointer to a buffer to parse; END is the
7103 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
7104 the image. Return in *DATA the bitmap data allocated with xmalloc.
7105 Value is non-zero if successful. DATA null means just test if
7106 CONTENTS looks like an in-memory XBM file. */
7107
7108 static int
7109 xbm_read_bitmap_data (contents, end, width, height, data)
7110 char *contents, *end;
7111 int *width, *height;
7112 unsigned char **data;
7113 {
7114 char *s = contents;
7115 char buffer[BUFSIZ];
7116 int padding_p = 0;
7117 int v10 = 0;
7118 int bytes_per_line, i, nbytes;
7119 unsigned char *p;
7120 int value;
7121 int LA1;
7122
7123 #define match() \
7124 LA1 = xbm_scan (&s, end, buffer, &value)
7125
7126 #define expect(TOKEN) \
7127 if (LA1 != (TOKEN)) \
7128 goto failure; \
7129 else \
7130 match ()
7131
7132 #define expect_ident(IDENT) \
7133 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
7134 match (); \
7135 else \
7136 goto failure
7137
7138 *width = *height = -1;
7139 if (data)
7140 *data = NULL;
7141 LA1 = xbm_scan (&s, end, buffer, &value);
7142
7143 /* Parse defines for width, height and hot-spots. */
7144 while (LA1 == '#')
7145 {
7146 match ();
7147 expect_ident ("define");
7148 expect (XBM_TK_IDENT);
7149
7150 if (LA1 == XBM_TK_NUMBER);
7151 {
7152 char *p = strrchr (buffer, '_');
7153 p = p ? p + 1 : buffer;
7154 if (strcmp (p, "width") == 0)
7155 *width = value;
7156 else if (strcmp (p, "height") == 0)
7157 *height = value;
7158 }
7159 expect (XBM_TK_NUMBER);
7160 }
7161
7162 if (*width < 0 || *height < 0)
7163 goto failure;
7164 else if (data == NULL)
7165 goto success;
7166
7167 /* Parse bits. Must start with `static'. */
7168 expect_ident ("static");
7169 if (LA1 == XBM_TK_IDENT)
7170 {
7171 if (strcmp (buffer, "unsigned") == 0)
7172 {
7173 match ();
7174 expect_ident ("char");
7175 }
7176 else if (strcmp (buffer, "short") == 0)
7177 {
7178 match ();
7179 v10 = 1;
7180 if (*width % 16 && *width % 16 < 9)
7181 padding_p = 1;
7182 }
7183 else if (strcmp (buffer, "char") == 0)
7184 match ();
7185 else
7186 goto failure;
7187 }
7188 else
7189 goto failure;
7190
7191 expect (XBM_TK_IDENT);
7192 expect ('[');
7193 expect (']');
7194 expect ('=');
7195 expect ('{');
7196
7197 bytes_per_line = (*width + 7) / 8 + padding_p;
7198 nbytes = bytes_per_line * *height;
7199 p = *data = (char *) xmalloc (nbytes);
7200
7201 if (v10)
7202 {
7203 for (i = 0; i < nbytes; i += 2)
7204 {
7205 int val = value;
7206 expect (XBM_TK_NUMBER);
7207
7208 *p++ = val;
7209 if (!padding_p || ((i + 2) % bytes_per_line))
7210 *p++ = value >> 8;
7211
7212 if (LA1 == ',' || LA1 == '}')
7213 match ();
7214 else
7215 goto failure;
7216 }
7217 }
7218 else
7219 {
7220 for (i = 0; i < nbytes; ++i)
7221 {
7222 int val = value;
7223 expect (XBM_TK_NUMBER);
7224
7225 *p++ = val;
7226
7227 if (LA1 == ',' || LA1 == '}')
7228 match ();
7229 else
7230 goto failure;
7231 }
7232 }
7233
7234 success:
7235 return 1;
7236
7237 failure:
7238
7239 if (data && *data)
7240 {
7241 xfree (*data);
7242 *data = NULL;
7243 }
7244 return 0;
7245
7246 #undef match
7247 #undef expect
7248 #undef expect_ident
7249 }
7250
7251
7252 /* Load XBM image IMG which will be displayed on frame F from buffer
7253 CONTENTS. END is the end of the buffer. Value is non-zero if
7254 successful. */
7255
7256 static int
7257 xbm_load_image (f, img, contents, end)
7258 struct frame *f;
7259 struct image *img;
7260 char *contents, *end;
7261 {
7262 int rc;
7263 unsigned char *data;
7264 int success_p = 0;
7265
7266 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
7267 if (rc)
7268 {
7269 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7270 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7271 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7272 Lisp_Object value;
7273
7274 xassert (img->width > 0 && img->height > 0);
7275
7276 /* Get foreground and background colors, maybe allocate colors. */
7277 value = image_spec_value (img->spec, QCforeground, NULL);
7278 if (!NILP (value))
7279 foreground = x_alloc_image_color (f, img, value, foreground);
7280 value = image_spec_value (img->spec, QCbackground, NULL);
7281 if (!NILP (value))
7282 {
7283 background = x_alloc_image_color (f, img, value, background);
7284 img->background = background;
7285 img->background_valid = 1;
7286 }
7287
7288 img->pixmap
7289 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7290 FRAME_X_WINDOW (f),
7291 data,
7292 img->width, img->height,
7293 foreground, background,
7294 depth);
7295 xfree (data);
7296
7297 if (img->pixmap == None)
7298 {
7299 x_clear_image (f, img);
7300 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
7301 }
7302 else
7303 success_p = 1;
7304 }
7305 else
7306 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7307
7308 return success_p;
7309 }
7310
7311
7312 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7313
7314 static int
7315 xbm_file_p (data)
7316 Lisp_Object data;
7317 {
7318 int w, h;
7319 return (STRINGP (data)
7320 && xbm_read_bitmap_data (SDATA (data),
7321 (SDATA (data)
7322 + SBYTES (data)),
7323 &w, &h, NULL));
7324 }
7325
7326
7327 /* Fill image IMG which is used on frame F with pixmap data. Value is
7328 non-zero if successful. */
7329
7330 static int
7331 xbm_load (f, img)
7332 struct frame *f;
7333 struct image *img;
7334 {
7335 int success_p = 0;
7336 Lisp_Object file_name;
7337
7338 xassert (xbm_image_p (img->spec));
7339
7340 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7341 file_name = image_spec_value (img->spec, QCfile, NULL);
7342 if (STRINGP (file_name))
7343 {
7344 Lisp_Object file;
7345 char *contents;
7346 int size;
7347 struct gcpro gcpro1;
7348
7349 file = x_find_image_file (file_name);
7350 GCPRO1 (file);
7351 if (!STRINGP (file))
7352 {
7353 image_error ("Cannot find image file `%s'", file_name, Qnil);
7354 UNGCPRO;
7355 return 0;
7356 }
7357
7358 contents = slurp_file (SDATA (file), &size);
7359 if (contents == NULL)
7360 {
7361 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7362 UNGCPRO;
7363 return 0;
7364 }
7365
7366 success_p = xbm_load_image (f, img, contents, contents + size);
7367 UNGCPRO;
7368 }
7369 else
7370 {
7371 struct image_keyword fmt[XBM_LAST];
7372 Lisp_Object data;
7373 int depth;
7374 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7375 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7376 char *bits;
7377 int parsed_p;
7378 int in_memory_file_p = 0;
7379
7380 /* See if data looks like an in-memory XBM file. */
7381 data = image_spec_value (img->spec, QCdata, NULL);
7382 in_memory_file_p = xbm_file_p (data);
7383
7384 /* Parse the image specification. */
7385 bcopy (xbm_format, fmt, sizeof fmt);
7386 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
7387 xassert (parsed_p);
7388
7389 /* Get specified width, and height. */
7390 if (!in_memory_file_p)
7391 {
7392 img->width = XFASTINT (fmt[XBM_WIDTH].value);
7393 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
7394 xassert (img->width > 0 && img->height > 0);
7395 }
7396
7397 /* Get foreground and background colors, maybe allocate colors. */
7398 if (fmt[XBM_FOREGROUND].count
7399 && STRINGP (fmt[XBM_FOREGROUND].value))
7400 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
7401 foreground);
7402 if (fmt[XBM_BACKGROUND].count
7403 && STRINGP (fmt[XBM_BACKGROUND].value))
7404 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
7405 background);
7406
7407 if (in_memory_file_p)
7408 success_p = xbm_load_image (f, img, SDATA (data),
7409 (SDATA (data)
7410 + SBYTES (data)));
7411 else
7412 {
7413 if (VECTORP (data))
7414 {
7415 int i;
7416 char *p;
7417 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
7418
7419 p = bits = (char *) alloca (nbytes * img->height);
7420 for (i = 0; i < img->height; ++i, p += nbytes)
7421 {
7422 Lisp_Object line = XVECTOR (data)->contents[i];
7423 if (STRINGP (line))
7424 bcopy (SDATA (line), p, nbytes);
7425 else
7426 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
7427 }
7428 }
7429 else if (STRINGP (data))
7430 bits = SDATA (data);
7431 else
7432 bits = XBOOL_VECTOR (data)->data;
7433
7434 /* Create the pixmap. */
7435 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7436 img->pixmap
7437 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7438 FRAME_X_WINDOW (f),
7439 bits,
7440 img->width, img->height,
7441 foreground, background,
7442 depth);
7443 if (img->pixmap)
7444 success_p = 1;
7445 else
7446 {
7447 image_error ("Unable to create pixmap for XBM image `%s'",
7448 img->spec, Qnil);
7449 x_clear_image (f, img);
7450 }
7451 }
7452 }
7453
7454 return success_p;
7455 }
7456
7457
7458
7459 /***********************************************************************
7460 XPM images
7461 ***********************************************************************/
7462
7463 #if HAVE_XPM
7464
7465 static int xpm_image_p P_ ((Lisp_Object object));
7466 static int xpm_load P_ ((struct frame *f, struct image *img));
7467 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
7468
7469 #include "X11/xpm.h"
7470
7471 /* The symbol `xpm' identifying XPM-format images. */
7472
7473 Lisp_Object Qxpm;
7474
7475 /* Indices of image specification fields in xpm_format, below. */
7476
7477 enum xpm_keyword_index
7478 {
7479 XPM_TYPE,
7480 XPM_FILE,
7481 XPM_DATA,
7482 XPM_ASCENT,
7483 XPM_MARGIN,
7484 XPM_RELIEF,
7485 XPM_ALGORITHM,
7486 XPM_HEURISTIC_MASK,
7487 XPM_MASK,
7488 XPM_COLOR_SYMBOLS,
7489 XPM_BACKGROUND,
7490 XPM_LAST
7491 };
7492
7493 /* Vector of image_keyword structures describing the format
7494 of valid XPM image specifications. */
7495
7496 static struct image_keyword xpm_format[XPM_LAST] =
7497 {
7498 {":type", IMAGE_SYMBOL_VALUE, 1},
7499 {":file", IMAGE_STRING_VALUE, 0},
7500 {":data", IMAGE_STRING_VALUE, 0},
7501 {":ascent", IMAGE_ASCENT_VALUE, 0},
7502 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7503 {":relief", IMAGE_INTEGER_VALUE, 0},
7504 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7505 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7506 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7507 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7508 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7509 };
7510
7511 /* Structure describing the image type XBM. */
7512
7513 static struct image_type xpm_type =
7514 {
7515 &Qxpm,
7516 xpm_image_p,
7517 xpm_load,
7518 x_clear_image,
7519 NULL
7520 };
7521
7522
7523 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7524 functions for allocating image colors. Our own functions handle
7525 color allocation failures more gracefully than the ones on the XPM
7526 lib. */
7527
7528 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7529 #define ALLOC_XPM_COLORS
7530 #endif
7531
7532 #ifdef ALLOC_XPM_COLORS
7533
7534 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
7535 static void xpm_free_color_cache P_ ((void));
7536 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
7537 static int xpm_color_bucket P_ ((char *));
7538 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
7539 XColor *, int));
7540
7541 /* An entry in a hash table used to cache color definitions of named
7542 colors. This cache is necessary to speed up XPM image loading in
7543 case we do color allocations ourselves. Without it, we would need
7544 a call to XParseColor per pixel in the image. */
7545
7546 struct xpm_cached_color
7547 {
7548 /* Next in collision chain. */
7549 struct xpm_cached_color *next;
7550
7551 /* Color definition (RGB and pixel color). */
7552 XColor color;
7553
7554 /* Color name. */
7555 char name[1];
7556 };
7557
7558 /* The hash table used for the color cache, and its bucket vector
7559 size. */
7560
7561 #define XPM_COLOR_CACHE_BUCKETS 1001
7562 struct xpm_cached_color **xpm_color_cache;
7563
7564 /* Initialize the color cache. */
7565
7566 static void
7567 xpm_init_color_cache (f, attrs)
7568 struct frame *f;
7569 XpmAttributes *attrs;
7570 {
7571 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
7572 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
7573 memset (xpm_color_cache, 0, nbytes);
7574 init_color_table ();
7575
7576 if (attrs->valuemask & XpmColorSymbols)
7577 {
7578 int i;
7579 XColor color;
7580
7581 for (i = 0; i < attrs->numsymbols; ++i)
7582 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7583 attrs->colorsymbols[i].value, &color))
7584 {
7585 color.pixel = lookup_rgb_color (f, color.red, color.green,
7586 color.blue);
7587 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
7588 }
7589 }
7590 }
7591
7592
7593 /* Free the color cache. */
7594
7595 static void
7596 xpm_free_color_cache ()
7597 {
7598 struct xpm_cached_color *p, *next;
7599 int i;
7600
7601 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
7602 for (p = xpm_color_cache[i]; p; p = next)
7603 {
7604 next = p->next;
7605 xfree (p);
7606 }
7607
7608 xfree (xpm_color_cache);
7609 xpm_color_cache = NULL;
7610 free_color_table ();
7611 }
7612
7613
7614 /* Return the bucket index for color named COLOR_NAME in the color
7615 cache. */
7616
7617 static int
7618 xpm_color_bucket (color_name)
7619 char *color_name;
7620 {
7621 unsigned h = 0;
7622 char *s;
7623
7624 for (s = color_name; *s; ++s)
7625 h = (h << 2) ^ *s;
7626 return h %= XPM_COLOR_CACHE_BUCKETS;
7627 }
7628
7629
7630 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7631 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7632 entry added. */
7633
7634 static struct xpm_cached_color *
7635 xpm_cache_color (f, color_name, color, bucket)
7636 struct frame *f;
7637 char *color_name;
7638 XColor *color;
7639 int bucket;
7640 {
7641 size_t nbytes;
7642 struct xpm_cached_color *p;
7643
7644 if (bucket < 0)
7645 bucket = xpm_color_bucket (color_name);
7646
7647 nbytes = sizeof *p + strlen (color_name);
7648 p = (struct xpm_cached_color *) xmalloc (nbytes);
7649 strcpy (p->name, color_name);
7650 p->color = *color;
7651 p->next = xpm_color_cache[bucket];
7652 xpm_color_cache[bucket] = p;
7653 return p;
7654 }
7655
7656
7657 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7658 return the cached definition in *COLOR. Otherwise, make a new
7659 entry in the cache and allocate the color. Value is zero if color
7660 allocation failed. */
7661
7662 static int
7663 xpm_lookup_color (f, color_name, color)
7664 struct frame *f;
7665 char *color_name;
7666 XColor *color;
7667 {
7668 struct xpm_cached_color *p;
7669 int h = xpm_color_bucket (color_name);
7670
7671 for (p = xpm_color_cache[h]; p; p = p->next)
7672 if (strcmp (p->name, color_name) == 0)
7673 break;
7674
7675 if (p != NULL)
7676 *color = p->color;
7677 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7678 color_name, color))
7679 {
7680 color->pixel = lookup_rgb_color (f, color->red, color->green,
7681 color->blue);
7682 p = xpm_cache_color (f, color_name, color, h);
7683 }
7684
7685 return p != NULL;
7686 }
7687
7688
7689 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7690 CLOSURE is a pointer to the frame on which we allocate the
7691 color. Return in *COLOR the allocated color. Value is non-zero
7692 if successful. */
7693
7694 static int
7695 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7696 Display *dpy;
7697 Colormap cmap;
7698 char *color_name;
7699 XColor *color;
7700 void *closure;
7701 {
7702 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7703 }
7704
7705
7706 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7707 is a pointer to the frame on which we allocate the color. Value is
7708 non-zero if successful. */
7709
7710 static int
7711 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7712 Display *dpy;
7713 Colormap cmap;
7714 Pixel *pixels;
7715 int npixels;
7716 void *closure;
7717 {
7718 return 1;
7719 }
7720
7721 #endif /* ALLOC_XPM_COLORS */
7722
7723
7724 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7725 for XPM images. Such a list must consist of conses whose car and
7726 cdr are strings. */
7727
7728 static int
7729 xpm_valid_color_symbols_p (color_symbols)
7730 Lisp_Object color_symbols;
7731 {
7732 while (CONSP (color_symbols))
7733 {
7734 Lisp_Object sym = XCAR (color_symbols);
7735 if (!CONSP (sym)
7736 || !STRINGP (XCAR (sym))
7737 || !STRINGP (XCDR (sym)))
7738 break;
7739 color_symbols = XCDR (color_symbols);
7740 }
7741
7742 return NILP (color_symbols);
7743 }
7744
7745
7746 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7747
7748 static int
7749 xpm_image_p (object)
7750 Lisp_Object object;
7751 {
7752 struct image_keyword fmt[XPM_LAST];
7753 bcopy (xpm_format, fmt, sizeof fmt);
7754 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7755 /* Either `:file' or `:data' must be present. */
7756 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7757 /* Either no `:color-symbols' or it's a list of conses
7758 whose car and cdr are strings. */
7759 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7760 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7761 }
7762
7763
7764 /* Load image IMG which will be displayed on frame F. Value is
7765 non-zero if successful. */
7766
7767 static int
7768 xpm_load (f, img)
7769 struct frame *f;
7770 struct image *img;
7771 {
7772 int rc;
7773 XpmAttributes attrs;
7774 Lisp_Object specified_file, color_symbols;
7775
7776 /* Configure the XPM lib. Use the visual of frame F. Allocate
7777 close colors. Return colors allocated. */
7778 bzero (&attrs, sizeof attrs);
7779 attrs.visual = FRAME_X_VISUAL (f);
7780 attrs.colormap = FRAME_X_COLORMAP (f);
7781 attrs.valuemask |= XpmVisual;
7782 attrs.valuemask |= XpmColormap;
7783
7784 #ifdef ALLOC_XPM_COLORS
7785 /* Allocate colors with our own functions which handle
7786 failing color allocation more gracefully. */
7787 attrs.color_closure = f;
7788 attrs.alloc_color = xpm_alloc_color;
7789 attrs.free_colors = xpm_free_colors;
7790 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7791 #else /* not ALLOC_XPM_COLORS */
7792 /* Let the XPM lib allocate colors. */
7793 attrs.valuemask |= XpmReturnAllocPixels;
7794 #ifdef XpmAllocCloseColors
7795 attrs.alloc_close_colors = 1;
7796 attrs.valuemask |= XpmAllocCloseColors;
7797 #else /* not XpmAllocCloseColors */
7798 attrs.closeness = 600;
7799 attrs.valuemask |= XpmCloseness;
7800 #endif /* not XpmAllocCloseColors */
7801 #endif /* ALLOC_XPM_COLORS */
7802
7803 /* If image specification contains symbolic color definitions, add
7804 these to `attrs'. */
7805 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7806 if (CONSP (color_symbols))
7807 {
7808 Lisp_Object tail;
7809 XpmColorSymbol *xpm_syms;
7810 int i, size;
7811
7812 attrs.valuemask |= XpmColorSymbols;
7813
7814 /* Count number of symbols. */
7815 attrs.numsymbols = 0;
7816 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7817 ++attrs.numsymbols;
7818
7819 /* Allocate an XpmColorSymbol array. */
7820 size = attrs.numsymbols * sizeof *xpm_syms;
7821 xpm_syms = (XpmColorSymbol *) alloca (size);
7822 bzero (xpm_syms, size);
7823 attrs.colorsymbols = xpm_syms;
7824
7825 /* Fill the color symbol array. */
7826 for (tail = color_symbols, i = 0;
7827 CONSP (tail);
7828 ++i, tail = XCDR (tail))
7829 {
7830 Lisp_Object name = XCAR (XCAR (tail));
7831 Lisp_Object color = XCDR (XCAR (tail));
7832 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
7833 strcpy (xpm_syms[i].name, SDATA (name));
7834 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
7835 strcpy (xpm_syms[i].value, SDATA (color));
7836 }
7837 }
7838
7839 /* Create a pixmap for the image, either from a file, or from a
7840 string buffer containing data in the same format as an XPM file. */
7841 #ifdef ALLOC_XPM_COLORS
7842 xpm_init_color_cache (f, &attrs);
7843 #endif
7844
7845 specified_file = image_spec_value (img->spec, QCfile, NULL);
7846 if (STRINGP (specified_file))
7847 {
7848 Lisp_Object file = x_find_image_file (specified_file);
7849 if (!STRINGP (file))
7850 {
7851 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7852 return 0;
7853 }
7854
7855 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7856 SDATA (file), &img->pixmap, &img->mask,
7857 &attrs);
7858 }
7859 else
7860 {
7861 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7862 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7863 SDATA (buffer),
7864 &img->pixmap, &img->mask,
7865 &attrs);
7866 }
7867
7868 if (rc == XpmSuccess)
7869 {
7870 #ifdef ALLOC_XPM_COLORS
7871 img->colors = colors_in_color_table (&img->ncolors);
7872 #else /* not ALLOC_XPM_COLORS */
7873 int i;
7874
7875 img->ncolors = attrs.nalloc_pixels;
7876 img->colors = (unsigned long *) xmalloc (img->ncolors
7877 * sizeof *img->colors);
7878 for (i = 0; i < attrs.nalloc_pixels; ++i)
7879 {
7880 img->colors[i] = attrs.alloc_pixels[i];
7881 #ifdef DEBUG_X_COLORS
7882 register_color (img->colors[i]);
7883 #endif
7884 }
7885 #endif /* not ALLOC_XPM_COLORS */
7886
7887 img->width = attrs.width;
7888 img->height = attrs.height;
7889 xassert (img->width > 0 && img->height > 0);
7890
7891 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7892 XpmFreeAttributes (&attrs);
7893 }
7894 else
7895 {
7896 switch (rc)
7897 {
7898 case XpmOpenFailed:
7899 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7900 break;
7901
7902 case XpmFileInvalid:
7903 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7904 break;
7905
7906 case XpmNoMemory:
7907 image_error ("Out of memory (%s)", img->spec, Qnil);
7908 break;
7909
7910 case XpmColorFailed:
7911 image_error ("Color allocation error (%s)", img->spec, Qnil);
7912 break;
7913
7914 default:
7915 image_error ("Unknown error (%s)", img->spec, Qnil);
7916 break;
7917 }
7918 }
7919
7920 #ifdef ALLOC_XPM_COLORS
7921 xpm_free_color_cache ();
7922 #endif
7923 return rc == XpmSuccess;
7924 }
7925
7926 #endif /* HAVE_XPM != 0 */
7927
7928
7929 /***********************************************************************
7930 Color table
7931 ***********************************************************************/
7932
7933 /* An entry in the color table mapping an RGB color to a pixel color. */
7934
7935 struct ct_color
7936 {
7937 int r, g, b;
7938 unsigned long pixel;
7939
7940 /* Next in color table collision list. */
7941 struct ct_color *next;
7942 };
7943
7944 /* The bucket vector size to use. Must be prime. */
7945
7946 #define CT_SIZE 101
7947
7948 /* Value is a hash of the RGB color given by R, G, and B. */
7949
7950 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7951
7952 /* The color hash table. */
7953
7954 struct ct_color **ct_table;
7955
7956 /* Number of entries in the color table. */
7957
7958 int ct_colors_allocated;
7959
7960 /* Initialize the color table. */
7961
7962 static void
7963 init_color_table ()
7964 {
7965 int size = CT_SIZE * sizeof (*ct_table);
7966 ct_table = (struct ct_color **) xmalloc (size);
7967 bzero (ct_table, size);
7968 ct_colors_allocated = 0;
7969 }
7970
7971
7972 /* Free memory associated with the color table. */
7973
7974 static void
7975 free_color_table ()
7976 {
7977 int i;
7978 struct ct_color *p, *next;
7979
7980 for (i = 0; i < CT_SIZE; ++i)
7981 for (p = ct_table[i]; p; p = next)
7982 {
7983 next = p->next;
7984 xfree (p);
7985 }
7986
7987 xfree (ct_table);
7988 ct_table = NULL;
7989 }
7990
7991
7992 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7993 entry for that color already is in the color table, return the
7994 pixel color of that entry. Otherwise, allocate a new color for R,
7995 G, B, and make an entry in the color table. */
7996
7997 static unsigned long
7998 lookup_rgb_color (f, r, g, b)
7999 struct frame *f;
8000 int r, g, b;
8001 {
8002 unsigned hash = CT_HASH_RGB (r, g, b);
8003 int i = hash % CT_SIZE;
8004 struct ct_color *p;
8005
8006 for (p = ct_table[i]; p; p = p->next)
8007 if (p->r == r && p->g == g && p->b == b)
8008 break;
8009
8010 if (p == NULL)
8011 {
8012 XColor color;
8013 Colormap cmap;
8014 int rc;
8015
8016 color.red = r;
8017 color.green = g;
8018 color.blue = b;
8019
8020 cmap = FRAME_X_COLORMAP (f);
8021 rc = x_alloc_nearest_color (f, cmap, &color);
8022
8023 if (rc)
8024 {
8025 ++ct_colors_allocated;
8026
8027 p = (struct ct_color *) xmalloc (sizeof *p);
8028 p->r = r;
8029 p->g = g;
8030 p->b = b;
8031 p->pixel = color.pixel;
8032 p->next = ct_table[i];
8033 ct_table[i] = p;
8034 }
8035 else
8036 return FRAME_FOREGROUND_PIXEL (f);
8037 }
8038
8039 return p->pixel;
8040 }
8041
8042
8043 /* Look up pixel color PIXEL which is used on frame F in the color
8044 table. If not already present, allocate it. Value is PIXEL. */
8045
8046 static unsigned long
8047 lookup_pixel_color (f, pixel)
8048 struct frame *f;
8049 unsigned long pixel;
8050 {
8051 int i = pixel % CT_SIZE;
8052 struct ct_color *p;
8053
8054 for (p = ct_table[i]; p; p = p->next)
8055 if (p->pixel == pixel)
8056 break;
8057
8058 if (p == NULL)
8059 {
8060 XColor color;
8061 Colormap cmap;
8062 int rc;
8063
8064 cmap = FRAME_X_COLORMAP (f);
8065 color.pixel = pixel;
8066 x_query_color (f, &color);
8067 rc = x_alloc_nearest_color (f, cmap, &color);
8068
8069 if (rc)
8070 {
8071 ++ct_colors_allocated;
8072
8073 p = (struct ct_color *) xmalloc (sizeof *p);
8074 p->r = color.red;
8075 p->g = color.green;
8076 p->b = color.blue;
8077 p->pixel = pixel;
8078 p->next = ct_table[i];
8079 ct_table[i] = p;
8080 }
8081 else
8082 return FRAME_FOREGROUND_PIXEL (f);
8083 }
8084
8085 return p->pixel;
8086 }
8087
8088
8089 /* Value is a vector of all pixel colors contained in the color table,
8090 allocated via xmalloc. Set *N to the number of colors. */
8091
8092 static unsigned long *
8093 colors_in_color_table (n)
8094 int *n;
8095 {
8096 int i, j;
8097 struct ct_color *p;
8098 unsigned long *colors;
8099
8100 if (ct_colors_allocated == 0)
8101 {
8102 *n = 0;
8103 colors = NULL;
8104 }
8105 else
8106 {
8107 colors = (unsigned long *) xmalloc (ct_colors_allocated
8108 * sizeof *colors);
8109 *n = ct_colors_allocated;
8110
8111 for (i = j = 0; i < CT_SIZE; ++i)
8112 for (p = ct_table[i]; p; p = p->next)
8113 colors[j++] = p->pixel;
8114 }
8115
8116 return colors;
8117 }
8118
8119
8120
8121 /***********************************************************************
8122 Algorithms
8123 ***********************************************************************/
8124
8125 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
8126 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
8127 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
8128
8129 /* Non-zero means draw a cross on images having `:conversion
8130 disabled'. */
8131
8132 int cross_disabled_images;
8133
8134 /* Edge detection matrices for different edge-detection
8135 strategies. */
8136
8137 static int emboss_matrix[9] = {
8138 /* x - 1 x x + 1 */
8139 2, -1, 0, /* y - 1 */
8140 -1, 0, 1, /* y */
8141 0, 1, -2 /* y + 1 */
8142 };
8143
8144 static int laplace_matrix[9] = {
8145 /* x - 1 x x + 1 */
8146 1, 0, 0, /* y - 1 */
8147 0, 0, 0, /* y */
8148 0, 0, -1 /* y + 1 */
8149 };
8150
8151 /* Value is the intensity of the color whose red/green/blue values
8152 are R, G, and B. */
8153
8154 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8155
8156
8157 /* On frame F, return an array of XColor structures describing image
8158 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8159 non-zero means also fill the red/green/blue members of the XColor
8160 structures. Value is a pointer to the array of XColors structures,
8161 allocated with xmalloc; it must be freed by the caller. */
8162
8163 static XColor *
8164 x_to_xcolors (f, img, rgb_p)
8165 struct frame *f;
8166 struct image *img;
8167 int rgb_p;
8168 {
8169 int x, y;
8170 XColor *colors, *p;
8171 XImage *ximg;
8172
8173 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
8174
8175 /* Get the X image IMG->pixmap. */
8176 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8177 0, 0, img->width, img->height, ~0, ZPixmap);
8178
8179 /* Fill the `pixel' members of the XColor array. I wished there
8180 were an easy and portable way to circumvent XGetPixel. */
8181 p = colors;
8182 for (y = 0; y < img->height; ++y)
8183 {
8184 XColor *row = p;
8185
8186 for (x = 0; x < img->width; ++x, ++p)
8187 p->pixel = XGetPixel (ximg, x, y);
8188
8189 if (rgb_p)
8190 x_query_colors (f, row, img->width);
8191 }
8192
8193 XDestroyImage (ximg);
8194 return colors;
8195 }
8196
8197
8198 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8199 RGB members are set. F is the frame on which this all happens.
8200 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8201
8202 static void
8203 x_from_xcolors (f, img, colors)
8204 struct frame *f;
8205 struct image *img;
8206 XColor *colors;
8207 {
8208 int x, y;
8209 XImage *oimg;
8210 Pixmap pixmap;
8211 XColor *p;
8212
8213 init_color_table ();
8214
8215 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
8216 &oimg, &pixmap);
8217 p = colors;
8218 for (y = 0; y < img->height; ++y)
8219 for (x = 0; x < img->width; ++x, ++p)
8220 {
8221 unsigned long pixel;
8222 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
8223 XPutPixel (oimg, x, y, pixel);
8224 }
8225
8226 xfree (colors);
8227 x_clear_image_1 (f, img, 1, 0, 1);
8228
8229 x_put_x_image (f, oimg, pixmap, img->width, img->height);
8230 x_destroy_x_image (oimg);
8231 img->pixmap = pixmap;
8232 img->colors = colors_in_color_table (&img->ncolors);
8233 free_color_table ();
8234 }
8235
8236
8237 /* On frame F, perform edge-detection on image IMG.
8238
8239 MATRIX is a nine-element array specifying the transformation
8240 matrix. See emboss_matrix for an example.
8241
8242 COLOR_ADJUST is a color adjustment added to each pixel of the
8243 outgoing image. */
8244
8245 static void
8246 x_detect_edges (f, img, matrix, color_adjust)
8247 struct frame *f;
8248 struct image *img;
8249 int matrix[9], color_adjust;
8250 {
8251 XColor *colors = x_to_xcolors (f, img, 1);
8252 XColor *new, *p;
8253 int x, y, i, sum;
8254
8255 for (i = sum = 0; i < 9; ++i)
8256 sum += abs (matrix[i]);
8257
8258 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8259
8260 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
8261
8262 for (y = 0; y < img->height; ++y)
8263 {
8264 p = COLOR (new, 0, y);
8265 p->red = p->green = p->blue = 0xffff/2;
8266 p = COLOR (new, img->width - 1, y);
8267 p->red = p->green = p->blue = 0xffff/2;
8268 }
8269
8270 for (x = 1; x < img->width - 1; ++x)
8271 {
8272 p = COLOR (new, x, 0);
8273 p->red = p->green = p->blue = 0xffff/2;
8274 p = COLOR (new, x, img->height - 1);
8275 p->red = p->green = p->blue = 0xffff/2;
8276 }
8277
8278 for (y = 1; y < img->height - 1; ++y)
8279 {
8280 p = COLOR (new, 1, y);
8281
8282 for (x = 1; x < img->width - 1; ++x, ++p)
8283 {
8284 int r, g, b, y1, x1;
8285
8286 r = g = b = i = 0;
8287 for (y1 = y - 1; y1 < y + 2; ++y1)
8288 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
8289 if (matrix[i])
8290 {
8291 XColor *t = COLOR (colors, x1, y1);
8292 r += matrix[i] * t->red;
8293 g += matrix[i] * t->green;
8294 b += matrix[i] * t->blue;
8295 }
8296
8297 r = (r / sum + color_adjust) & 0xffff;
8298 g = (g / sum + color_adjust) & 0xffff;
8299 b = (b / sum + color_adjust) & 0xffff;
8300 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
8301 }
8302 }
8303
8304 xfree (colors);
8305 x_from_xcolors (f, img, new);
8306
8307 #undef COLOR
8308 }
8309
8310
8311 /* Perform the pre-defined `emboss' edge-detection on image IMG
8312 on frame F. */
8313
8314 static void
8315 x_emboss (f, img)
8316 struct frame *f;
8317 struct image *img;
8318 {
8319 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
8320 }
8321
8322
8323 /* Perform the pre-defined `laplace' edge-detection on image IMG
8324 on frame F. */
8325
8326 static void
8327 x_laplace (f, img)
8328 struct frame *f;
8329 struct image *img;
8330 {
8331 x_detect_edges (f, img, laplace_matrix, 45000);
8332 }
8333
8334
8335 /* Perform edge-detection on image IMG on frame F, with specified
8336 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8337
8338 MATRIX must be either
8339
8340 - a list of at least 9 numbers in row-major form
8341 - a vector of at least 9 numbers
8342
8343 COLOR_ADJUST nil means use a default; otherwise it must be a
8344 number. */
8345
8346 static void
8347 x_edge_detection (f, img, matrix, color_adjust)
8348 struct frame *f;
8349 struct image *img;
8350 Lisp_Object matrix, color_adjust;
8351 {
8352 int i = 0;
8353 int trans[9];
8354
8355 if (CONSP (matrix))
8356 {
8357 for (i = 0;
8358 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
8359 ++i, matrix = XCDR (matrix))
8360 trans[i] = XFLOATINT (XCAR (matrix));
8361 }
8362 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
8363 {
8364 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
8365 trans[i] = XFLOATINT (AREF (matrix, i));
8366 }
8367
8368 if (NILP (color_adjust))
8369 color_adjust = make_number (0xffff / 2);
8370
8371 if (i == 9 && NUMBERP (color_adjust))
8372 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
8373 }
8374
8375
8376 /* Transform image IMG on frame F so that it looks disabled. */
8377
8378 static void
8379 x_disable_image (f, img)
8380 struct frame *f;
8381 struct image *img;
8382 {
8383 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8384
8385 if (dpyinfo->n_planes >= 2)
8386 {
8387 /* Color (or grayscale). Convert to gray, and equalize. Just
8388 drawing such images with a stipple can look very odd, so
8389 we're using this method instead. */
8390 XColor *colors = x_to_xcolors (f, img, 1);
8391 XColor *p, *end;
8392 const int h = 15000;
8393 const int l = 30000;
8394
8395 for (p = colors, end = colors + img->width * img->height;
8396 p < end;
8397 ++p)
8398 {
8399 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
8400 int i2 = (0xffff - h - l) * i / 0xffff + l;
8401 p->red = p->green = p->blue = i2;
8402 }
8403
8404 x_from_xcolors (f, img, colors);
8405 }
8406
8407 /* Draw a cross over the disabled image, if we must or if we
8408 should. */
8409 if (dpyinfo->n_planes < 2 || cross_disabled_images)
8410 {
8411 Display *dpy = FRAME_X_DISPLAY (f);
8412 GC gc;
8413
8414 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
8415 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
8416 XDrawLine (dpy, img->pixmap, gc, 0, 0,
8417 img->width - 1, img->height - 1);
8418 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
8419 img->width - 1, 0);
8420 XFreeGC (dpy, gc);
8421
8422 if (img->mask)
8423 {
8424 gc = XCreateGC (dpy, img->mask, 0, NULL);
8425 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
8426 XDrawLine (dpy, img->mask, gc, 0, 0,
8427 img->width - 1, img->height - 1);
8428 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
8429 img->width - 1, 0);
8430 XFreeGC (dpy, gc);
8431 }
8432 }
8433 }
8434
8435
8436 /* Build a mask for image IMG which is used on frame F. FILE is the
8437 name of an image file, for error messages. HOW determines how to
8438 determine the background color of IMG. If it is a list '(R G B)',
8439 with R, G, and B being integers >= 0, take that as the color of the
8440 background. Otherwise, determine the background color of IMG
8441 heuristically. Value is non-zero if successful. */
8442
8443 static int
8444 x_build_heuristic_mask (f, img, how)
8445 struct frame *f;
8446 struct image *img;
8447 Lisp_Object how;
8448 {
8449 Display *dpy = FRAME_X_DISPLAY (f);
8450 XImage *ximg, *mask_img;
8451 int x, y, rc, use_img_background;
8452 unsigned long bg = 0;
8453
8454 if (img->mask)
8455 {
8456 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8457 img->mask = None;
8458 img->background_transparent_valid = 0;
8459 }
8460
8461 /* Create an image and pixmap serving as mask. */
8462 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
8463 &mask_img, &img->mask);
8464 if (!rc)
8465 return 0;
8466
8467 /* Get the X image of IMG->pixmap. */
8468 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
8469 ~0, ZPixmap);
8470
8471 /* Determine the background color of ximg. If HOW is `(R G B)'
8472 take that as color. Otherwise, use the image's background color. */
8473 use_img_background = 1;
8474
8475 if (CONSP (how))
8476 {
8477 int rgb[3], i;
8478
8479 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
8480 {
8481 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
8482 how = XCDR (how);
8483 }
8484
8485 if (i == 3 && NILP (how))
8486 {
8487 char color_name[30];
8488 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
8489 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
8490 use_img_background = 0;
8491 }
8492 }
8493
8494 if (use_img_background)
8495 bg = four_corners_best (ximg, img->width, img->height);
8496
8497 /* Set all bits in mask_img to 1 whose color in ximg is different
8498 from the background color bg. */
8499 for (y = 0; y < img->height; ++y)
8500 for (x = 0; x < img->width; ++x)
8501 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
8502
8503 /* Fill in the background_transparent field while we have the mask handy. */
8504 image_background_transparent (img, f, mask_img);
8505
8506 /* Put mask_img into img->mask. */
8507 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8508 x_destroy_x_image (mask_img);
8509 XDestroyImage (ximg);
8510
8511 return 1;
8512 }
8513
8514
8515
8516 /***********************************************************************
8517 PBM (mono, gray, color)
8518 ***********************************************************************/
8519
8520 static int pbm_image_p P_ ((Lisp_Object object));
8521 static int pbm_load P_ ((struct frame *f, struct image *img));
8522 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
8523
8524 /* The symbol `pbm' identifying images of this type. */
8525
8526 Lisp_Object Qpbm;
8527
8528 /* Indices of image specification fields in gs_format, below. */
8529
8530 enum pbm_keyword_index
8531 {
8532 PBM_TYPE,
8533 PBM_FILE,
8534 PBM_DATA,
8535 PBM_ASCENT,
8536 PBM_MARGIN,
8537 PBM_RELIEF,
8538 PBM_ALGORITHM,
8539 PBM_HEURISTIC_MASK,
8540 PBM_MASK,
8541 PBM_FOREGROUND,
8542 PBM_BACKGROUND,
8543 PBM_LAST
8544 };
8545
8546 /* Vector of image_keyword structures describing the format
8547 of valid user-defined image specifications. */
8548
8549 static struct image_keyword pbm_format[PBM_LAST] =
8550 {
8551 {":type", IMAGE_SYMBOL_VALUE, 1},
8552 {":file", IMAGE_STRING_VALUE, 0},
8553 {":data", IMAGE_STRING_VALUE, 0},
8554 {":ascent", IMAGE_ASCENT_VALUE, 0},
8555 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8556 {":relief", IMAGE_INTEGER_VALUE, 0},
8557 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8558 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8559 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8560 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
8561 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8562 };
8563
8564 /* Structure describing the image type `pbm'. */
8565
8566 static struct image_type pbm_type =
8567 {
8568 &Qpbm,
8569 pbm_image_p,
8570 pbm_load,
8571 x_clear_image,
8572 NULL
8573 };
8574
8575
8576 /* Return non-zero if OBJECT is a valid PBM image specification. */
8577
8578 static int
8579 pbm_image_p (object)
8580 Lisp_Object object;
8581 {
8582 struct image_keyword fmt[PBM_LAST];
8583
8584 bcopy (pbm_format, fmt, sizeof fmt);
8585
8586 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
8587 return 0;
8588
8589 /* Must specify either :data or :file. */
8590 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
8591 }
8592
8593
8594 /* Scan a decimal number from *S and return it. Advance *S while
8595 reading the number. END is the end of the string. Value is -1 at
8596 end of input. */
8597
8598 static int
8599 pbm_scan_number (s, end)
8600 unsigned char **s, *end;
8601 {
8602 int c = 0, val = -1;
8603
8604 while (*s < end)
8605 {
8606 /* Skip white-space. */
8607 while (*s < end && (c = *(*s)++, isspace (c)))
8608 ;
8609
8610 if (c == '#')
8611 {
8612 /* Skip comment to end of line. */
8613 while (*s < end && (c = *(*s)++, c != '\n'))
8614 ;
8615 }
8616 else if (isdigit (c))
8617 {
8618 /* Read decimal number. */
8619 val = c - '0';
8620 while (*s < end && (c = *(*s)++, isdigit (c)))
8621 val = 10 * val + c - '0';
8622 break;
8623 }
8624 else
8625 break;
8626 }
8627
8628 return val;
8629 }
8630
8631
8632 /* Load PBM image IMG for use on frame F. */
8633
8634 static int
8635 pbm_load (f, img)
8636 struct frame *f;
8637 struct image *img;
8638 {
8639 int raw_p, x, y;
8640 int width, height, max_color_idx = 0;
8641 XImage *ximg;
8642 Lisp_Object file, specified_file;
8643 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8644 struct gcpro gcpro1;
8645 unsigned char *contents = NULL;
8646 unsigned char *end, *p;
8647 int size;
8648
8649 specified_file = image_spec_value (img->spec, QCfile, NULL);
8650 file = Qnil;
8651 GCPRO1 (file);
8652
8653 if (STRINGP (specified_file))
8654 {
8655 file = x_find_image_file (specified_file);
8656 if (!STRINGP (file))
8657 {
8658 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8659 UNGCPRO;
8660 return 0;
8661 }
8662
8663 contents = slurp_file (SDATA (file), &size);
8664 if (contents == NULL)
8665 {
8666 image_error ("Error reading `%s'", file, Qnil);
8667 UNGCPRO;
8668 return 0;
8669 }
8670
8671 p = contents;
8672 end = contents + size;
8673 }
8674 else
8675 {
8676 Lisp_Object data;
8677 data = image_spec_value (img->spec, QCdata, NULL);
8678 p = SDATA (data);
8679 end = p + SBYTES (data);
8680 }
8681
8682 /* Check magic number. */
8683 if (end - p < 2 || *p++ != 'P')
8684 {
8685 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8686 error:
8687 xfree (contents);
8688 UNGCPRO;
8689 return 0;
8690 }
8691
8692 switch (*p++)
8693 {
8694 case '1':
8695 raw_p = 0, type = PBM_MONO;
8696 break;
8697
8698 case '2':
8699 raw_p = 0, type = PBM_GRAY;
8700 break;
8701
8702 case '3':
8703 raw_p = 0, type = PBM_COLOR;
8704 break;
8705
8706 case '4':
8707 raw_p = 1, type = PBM_MONO;
8708 break;
8709
8710 case '5':
8711 raw_p = 1, type = PBM_GRAY;
8712 break;
8713
8714 case '6':
8715 raw_p = 1, type = PBM_COLOR;
8716 break;
8717
8718 default:
8719 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8720 goto error;
8721 }
8722
8723 /* Read width, height, maximum color-component. Characters
8724 starting with `#' up to the end of a line are ignored. */
8725 width = pbm_scan_number (&p, end);
8726 height = pbm_scan_number (&p, end);
8727
8728 if (type != PBM_MONO)
8729 {
8730 max_color_idx = pbm_scan_number (&p, end);
8731 if (raw_p && max_color_idx > 255)
8732 max_color_idx = 255;
8733 }
8734
8735 if (width < 0
8736 || height < 0
8737 || (type != PBM_MONO && max_color_idx < 0))
8738 goto error;
8739
8740 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8741 &ximg, &img->pixmap))
8742 goto error;
8743
8744 /* Initialize the color hash table. */
8745 init_color_table ();
8746
8747 if (type == PBM_MONO)
8748 {
8749 int c = 0, g;
8750 struct image_keyword fmt[PBM_LAST];
8751 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8752 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8753
8754 /* Parse the image specification. */
8755 bcopy (pbm_format, fmt, sizeof fmt);
8756 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8757
8758 /* Get foreground and background colors, maybe allocate colors. */
8759 if (fmt[PBM_FOREGROUND].count
8760 && STRINGP (fmt[PBM_FOREGROUND].value))
8761 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8762 if (fmt[PBM_BACKGROUND].count
8763 && STRINGP (fmt[PBM_BACKGROUND].value))
8764 {
8765 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8766 img->background = bg;
8767 img->background_valid = 1;
8768 }
8769
8770 for (y = 0; y < height; ++y)
8771 for (x = 0; x < width; ++x)
8772 {
8773 if (raw_p)
8774 {
8775 if ((x & 7) == 0)
8776 c = *p++;
8777 g = c & 0x80;
8778 c <<= 1;
8779 }
8780 else
8781 g = pbm_scan_number (&p, end);
8782
8783 XPutPixel (ximg, x, y, g ? fg : bg);
8784 }
8785 }
8786 else
8787 {
8788 for (y = 0; y < height; ++y)
8789 for (x = 0; x < width; ++x)
8790 {
8791 int r, g, b;
8792
8793 if (type == PBM_GRAY)
8794 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8795 else if (raw_p)
8796 {
8797 r = *p++;
8798 g = *p++;
8799 b = *p++;
8800 }
8801 else
8802 {
8803 r = pbm_scan_number (&p, end);
8804 g = pbm_scan_number (&p, end);
8805 b = pbm_scan_number (&p, end);
8806 }
8807
8808 if (r < 0 || g < 0 || b < 0)
8809 {
8810 xfree (ximg->data);
8811 ximg->data = NULL;
8812 XDestroyImage (ximg);
8813 image_error ("Invalid pixel value in image `%s'",
8814 img->spec, Qnil);
8815 goto error;
8816 }
8817
8818 /* RGB values are now in the range 0..max_color_idx.
8819 Scale this to the range 0..0xffff supported by X. */
8820 r = (double) r * 65535 / max_color_idx;
8821 g = (double) g * 65535 / max_color_idx;
8822 b = (double) b * 65535 / max_color_idx;
8823 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8824 }
8825 }
8826
8827 /* Store in IMG->colors the colors allocated for the image, and
8828 free the color table. */
8829 img->colors = colors_in_color_table (&img->ncolors);
8830 free_color_table ();
8831
8832 /* Maybe fill in the background field while we have ximg handy. */
8833 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8834 IMAGE_BACKGROUND (img, f, ximg);
8835
8836 /* Put the image into a pixmap. */
8837 x_put_x_image (f, ximg, img->pixmap, width, height);
8838 x_destroy_x_image (ximg);
8839
8840 img->width = width;
8841 img->height = height;
8842
8843 UNGCPRO;
8844 xfree (contents);
8845 return 1;
8846 }
8847
8848
8849
8850 /***********************************************************************
8851 PNG
8852 ***********************************************************************/
8853
8854 #if HAVE_PNG
8855
8856 #include <png.h>
8857
8858 /* Function prototypes. */
8859
8860 static int png_image_p P_ ((Lisp_Object object));
8861 static int png_load P_ ((struct frame *f, struct image *img));
8862
8863 /* The symbol `png' identifying images of this type. */
8864
8865 Lisp_Object Qpng;
8866
8867 /* Indices of image specification fields in png_format, below. */
8868
8869 enum png_keyword_index
8870 {
8871 PNG_TYPE,
8872 PNG_DATA,
8873 PNG_FILE,
8874 PNG_ASCENT,
8875 PNG_MARGIN,
8876 PNG_RELIEF,
8877 PNG_ALGORITHM,
8878 PNG_HEURISTIC_MASK,
8879 PNG_MASK,
8880 PNG_BACKGROUND,
8881 PNG_LAST
8882 };
8883
8884 /* Vector of image_keyword structures describing the format
8885 of valid user-defined image specifications. */
8886
8887 static struct image_keyword png_format[PNG_LAST] =
8888 {
8889 {":type", IMAGE_SYMBOL_VALUE, 1},
8890 {":data", IMAGE_STRING_VALUE, 0},
8891 {":file", IMAGE_STRING_VALUE, 0},
8892 {":ascent", IMAGE_ASCENT_VALUE, 0},
8893 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8894 {":relief", IMAGE_INTEGER_VALUE, 0},
8895 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8896 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8897 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8898 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8899 };
8900
8901 /* Structure describing the image type `png'. */
8902
8903 static struct image_type png_type =
8904 {
8905 &Qpng,
8906 png_image_p,
8907 png_load,
8908 x_clear_image,
8909 NULL
8910 };
8911
8912
8913 /* Return non-zero if OBJECT is a valid PNG image specification. */
8914
8915 static int
8916 png_image_p (object)
8917 Lisp_Object object;
8918 {
8919 struct image_keyword fmt[PNG_LAST];
8920 bcopy (png_format, fmt, sizeof fmt);
8921
8922 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8923 return 0;
8924
8925 /* Must specify either the :data or :file keyword. */
8926 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8927 }
8928
8929
8930 /* Error and warning handlers installed when the PNG library
8931 is initialized. */
8932
8933 static void
8934 my_png_error (png_ptr, msg)
8935 png_struct *png_ptr;
8936 char *msg;
8937 {
8938 xassert (png_ptr != NULL);
8939 image_error ("PNG error: %s", build_string (msg), Qnil);
8940 longjmp (png_ptr->jmpbuf, 1);
8941 }
8942
8943
8944 static void
8945 my_png_warning (png_ptr, msg)
8946 png_struct *png_ptr;
8947 char *msg;
8948 {
8949 xassert (png_ptr != NULL);
8950 image_error ("PNG warning: %s", build_string (msg), Qnil);
8951 }
8952
8953 /* Memory source for PNG decoding. */
8954
8955 struct png_memory_storage
8956 {
8957 unsigned char *bytes; /* The data */
8958 size_t len; /* How big is it? */
8959 int index; /* Where are we? */
8960 };
8961
8962
8963 /* Function set as reader function when reading PNG image from memory.
8964 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8965 bytes from the input to DATA. */
8966
8967 static void
8968 png_read_from_memory (png_ptr, data, length)
8969 png_structp png_ptr;
8970 png_bytep data;
8971 png_size_t length;
8972 {
8973 struct png_memory_storage *tbr
8974 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8975
8976 if (length > tbr->len - tbr->index)
8977 png_error (png_ptr, "Read error");
8978
8979 bcopy (tbr->bytes + tbr->index, data, length);
8980 tbr->index = tbr->index + length;
8981 }
8982
8983 /* Load PNG image IMG for use on frame F. Value is non-zero if
8984 successful. */
8985
8986 static int
8987 png_load (f, img)
8988 struct frame *f;
8989 struct image *img;
8990 {
8991 Lisp_Object file, specified_file;
8992 Lisp_Object specified_data;
8993 int x, y, i;
8994 XImage *ximg, *mask_img = NULL;
8995 struct gcpro gcpro1;
8996 png_struct *png_ptr = NULL;
8997 png_info *info_ptr = NULL, *end_info = NULL;
8998 FILE *volatile fp = NULL;
8999 png_byte sig[8];
9000 png_byte * volatile pixels = NULL;
9001 png_byte ** volatile rows = NULL;
9002 png_uint_32 width, height;
9003 int bit_depth, color_type, interlace_type;
9004 png_byte channels;
9005 png_uint_32 row_bytes;
9006 int transparent_p;
9007 double screen_gamma, image_gamma;
9008 int intent;
9009 struct png_memory_storage tbr; /* Data to be read */
9010
9011 /* Find out what file to load. */
9012 specified_file = image_spec_value (img->spec, QCfile, NULL);
9013 specified_data = image_spec_value (img->spec, QCdata, NULL);
9014 file = Qnil;
9015 GCPRO1 (file);
9016
9017 if (NILP (specified_data))
9018 {
9019 file = x_find_image_file (specified_file);
9020 if (!STRINGP (file))
9021 {
9022 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9023 UNGCPRO;
9024 return 0;
9025 }
9026
9027 /* Open the image file. */
9028 fp = fopen (SDATA (file), "rb");
9029 if (!fp)
9030 {
9031 image_error ("Cannot open image file `%s'", file, Qnil);
9032 UNGCPRO;
9033 fclose (fp);
9034 return 0;
9035 }
9036
9037 /* Check PNG signature. */
9038 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
9039 || !png_check_sig (sig, sizeof sig))
9040 {
9041 image_error ("Not a PNG file: `%s'", file, Qnil);
9042 UNGCPRO;
9043 fclose (fp);
9044 return 0;
9045 }
9046 }
9047 else
9048 {
9049 /* Read from memory. */
9050 tbr.bytes = SDATA (specified_data);
9051 tbr.len = SBYTES (specified_data);
9052 tbr.index = 0;
9053
9054 /* Check PNG signature. */
9055 if (tbr.len < sizeof sig
9056 || !png_check_sig (tbr.bytes, sizeof sig))
9057 {
9058 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
9059 UNGCPRO;
9060 return 0;
9061 }
9062
9063 /* Need to skip past the signature. */
9064 tbr.bytes += sizeof (sig);
9065 }
9066
9067 /* Initialize read and info structs for PNG lib. */
9068 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
9069 my_png_error, my_png_warning);
9070 if (!png_ptr)
9071 {
9072 if (fp) fclose (fp);
9073 UNGCPRO;
9074 return 0;
9075 }
9076
9077 info_ptr = png_create_info_struct (png_ptr);
9078 if (!info_ptr)
9079 {
9080 png_destroy_read_struct (&png_ptr, NULL, NULL);
9081 if (fp) fclose (fp);
9082 UNGCPRO;
9083 return 0;
9084 }
9085
9086 end_info = png_create_info_struct (png_ptr);
9087 if (!end_info)
9088 {
9089 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
9090 if (fp) fclose (fp);
9091 UNGCPRO;
9092 return 0;
9093 }
9094
9095 /* Set error jump-back. We come back here when the PNG library
9096 detects an error. */
9097 if (setjmp (png_ptr->jmpbuf))
9098 {
9099 error:
9100 if (png_ptr)
9101 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
9102 xfree (pixels);
9103 xfree (rows);
9104 if (fp) fclose (fp);
9105 UNGCPRO;
9106 return 0;
9107 }
9108
9109 /* Read image info. */
9110 if (!NILP (specified_data))
9111 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
9112 else
9113 png_init_io (png_ptr, fp);
9114
9115 png_set_sig_bytes (png_ptr, sizeof sig);
9116 png_read_info (png_ptr, info_ptr);
9117 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
9118 &interlace_type, NULL, NULL);
9119
9120 /* If image contains simply transparency data, we prefer to
9121 construct a clipping mask. */
9122 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
9123 transparent_p = 1;
9124 else
9125 transparent_p = 0;
9126
9127 /* This function is easier to write if we only have to handle
9128 one data format: RGB or RGBA with 8 bits per channel. Let's
9129 transform other formats into that format. */
9130
9131 /* Strip more than 8 bits per channel. */
9132 if (bit_depth == 16)
9133 png_set_strip_16 (png_ptr);
9134
9135 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
9136 if available. */
9137 png_set_expand (png_ptr);
9138
9139 /* Convert grayscale images to RGB. */
9140 if (color_type == PNG_COLOR_TYPE_GRAY
9141 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
9142 png_set_gray_to_rgb (png_ptr);
9143
9144 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
9145
9146 #if 0 /* Avoid double gamma correction for PNG images. */
9147 /* Tell the PNG lib to handle gamma correction for us. */
9148 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9149 if (png_get_sRGB (png_ptr, info_ptr, &intent))
9150 /* The libpng documentation says this is right in this case. */
9151 png_set_gamma (png_ptr, screen_gamma, 0.45455);
9152 else
9153 #endif
9154 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
9155 /* Image contains gamma information. */
9156 png_set_gamma (png_ptr, screen_gamma, image_gamma);
9157 else
9158 /* Use the standard default for the image gamma. */
9159 png_set_gamma (png_ptr, screen_gamma, 0.45455);
9160 #endif /* if 0 */
9161
9162 /* Handle alpha channel by combining the image with a background
9163 color. Do this only if a real alpha channel is supplied. For
9164 simple transparency, we prefer a clipping mask. */
9165 if (!transparent_p)
9166 {
9167 png_color_16 *image_bg;
9168 Lisp_Object specified_bg
9169 = image_spec_value (img->spec, QCbackground, NULL);
9170
9171 if (STRINGP (specified_bg))
9172 /* The user specified `:background', use that. */
9173 {
9174 XColor color;
9175 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
9176 {
9177 png_color_16 user_bg;
9178
9179 bzero (&user_bg, sizeof user_bg);
9180 user_bg.red = color.red;
9181 user_bg.green = color.green;
9182 user_bg.blue = color.blue;
9183
9184 png_set_background (png_ptr, &user_bg,
9185 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
9186 }
9187 }
9188 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
9189 /* Image contains a background color with which to
9190 combine the image. */
9191 png_set_background (png_ptr, image_bg,
9192 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
9193 else
9194 {
9195 /* Image does not contain a background color with which
9196 to combine the image data via an alpha channel. Use
9197 the frame's background instead. */
9198 XColor color;
9199 Colormap cmap;
9200 png_color_16 frame_background;
9201
9202 cmap = FRAME_X_COLORMAP (f);
9203 color.pixel = FRAME_BACKGROUND_PIXEL (f);
9204 x_query_color (f, &color);
9205
9206 bzero (&frame_background, sizeof frame_background);
9207 frame_background.red = color.red;
9208 frame_background.green = color.green;
9209 frame_background.blue = color.blue;
9210
9211 png_set_background (png_ptr, &frame_background,
9212 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
9213 }
9214 }
9215
9216 /* Update info structure. */
9217 png_read_update_info (png_ptr, info_ptr);
9218
9219 /* Get number of channels. Valid values are 1 for grayscale images
9220 and images with a palette, 2 for grayscale images with transparency
9221 information (alpha channel), 3 for RGB images, and 4 for RGB
9222 images with alpha channel, i.e. RGBA. If conversions above were
9223 sufficient we should only have 3 or 4 channels here. */
9224 channels = png_get_channels (png_ptr, info_ptr);
9225 xassert (channels == 3 || channels == 4);
9226
9227 /* Number of bytes needed for one row of the image. */
9228 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
9229
9230 /* Allocate memory for the image. */
9231 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
9232 rows = (png_byte **) xmalloc (height * sizeof *rows);
9233 for (i = 0; i < height; ++i)
9234 rows[i] = pixels + i * row_bytes;
9235
9236 /* Read the entire image. */
9237 png_read_image (png_ptr, rows);
9238 png_read_end (png_ptr, info_ptr);
9239 if (fp)
9240 {
9241 fclose (fp);
9242 fp = NULL;
9243 }
9244
9245 /* Create the X image and pixmap. */
9246 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
9247 &img->pixmap))
9248 goto error;
9249
9250 /* Create an image and pixmap serving as mask if the PNG image
9251 contains an alpha channel. */
9252 if (channels == 4
9253 && !transparent_p
9254 && !x_create_x_image_and_pixmap (f, width, height, 1,
9255 &mask_img, &img->mask))
9256 {
9257 x_destroy_x_image (ximg);
9258 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
9259 img->pixmap = None;
9260 goto error;
9261 }
9262
9263 /* Fill the X image and mask from PNG data. */
9264 init_color_table ();
9265
9266 for (y = 0; y < height; ++y)
9267 {
9268 png_byte *p = rows[y];
9269
9270 for (x = 0; x < width; ++x)
9271 {
9272 unsigned r, g, b;
9273
9274 r = *p++ << 8;
9275 g = *p++ << 8;
9276 b = *p++ << 8;
9277 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
9278
9279 /* An alpha channel, aka mask channel, associates variable
9280 transparency with an image. Where other image formats
9281 support binary transparency---fully transparent or fully
9282 opaque---PNG allows up to 254 levels of partial transparency.
9283 The PNG library implements partial transparency by combining
9284 the image with a specified background color.
9285
9286 I'm not sure how to handle this here nicely: because the
9287 background on which the image is displayed may change, for
9288 real alpha channel support, it would be necessary to create
9289 a new image for each possible background.
9290
9291 What I'm doing now is that a mask is created if we have
9292 boolean transparency information. Otherwise I'm using
9293 the frame's background color to combine the image with. */
9294
9295 if (channels == 4)
9296 {
9297 if (mask_img)
9298 XPutPixel (mask_img, x, y, *p > 0);
9299 ++p;
9300 }
9301 }
9302 }
9303
9304 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9305 /* Set IMG's background color from the PNG image, unless the user
9306 overrode it. */
9307 {
9308 png_color_16 *bg;
9309 if (png_get_bKGD (png_ptr, info_ptr, &bg))
9310 {
9311 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
9312 img->background_valid = 1;
9313 }
9314 }
9315
9316 /* Remember colors allocated for this image. */
9317 img->colors = colors_in_color_table (&img->ncolors);
9318 free_color_table ();
9319
9320 /* Clean up. */
9321 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
9322 xfree (rows);
9323 xfree (pixels);
9324
9325 img->width = width;
9326 img->height = height;
9327
9328 /* Maybe fill in the background field while we have ximg handy. */
9329 IMAGE_BACKGROUND (img, f, ximg);
9330
9331 /* Put the image into the pixmap, then free the X image and its buffer. */
9332 x_put_x_image (f, ximg, img->pixmap, width, height);
9333 x_destroy_x_image (ximg);
9334
9335 /* Same for the mask. */
9336 if (mask_img)
9337 {
9338 /* Fill in the background_transparent field while we have the mask
9339 handy. */
9340 image_background_transparent (img, f, mask_img);
9341
9342 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
9343 x_destroy_x_image (mask_img);
9344 }
9345
9346 UNGCPRO;
9347 return 1;
9348 }
9349
9350 #endif /* HAVE_PNG != 0 */
9351
9352
9353
9354 /***********************************************************************
9355 JPEG
9356 ***********************************************************************/
9357
9358 #if HAVE_JPEG
9359
9360 /* Work around a warning about HAVE_STDLIB_H being redefined in
9361 jconfig.h. */
9362 #ifdef HAVE_STDLIB_H
9363 #define HAVE_STDLIB_H_1
9364 #undef HAVE_STDLIB_H
9365 #endif /* HAVE_STLIB_H */
9366
9367 #include <jpeglib.h>
9368 #include <jerror.h>
9369 #include <setjmp.h>
9370
9371 #ifdef HAVE_STLIB_H_1
9372 #define HAVE_STDLIB_H 1
9373 #endif
9374
9375 static int jpeg_image_p P_ ((Lisp_Object object));
9376 static int jpeg_load P_ ((struct frame *f, struct image *img));
9377
9378 /* The symbol `jpeg' identifying images of this type. */
9379
9380 Lisp_Object Qjpeg;
9381
9382 /* Indices of image specification fields in gs_format, below. */
9383
9384 enum jpeg_keyword_index
9385 {
9386 JPEG_TYPE,
9387 JPEG_DATA,
9388 JPEG_FILE,
9389 JPEG_ASCENT,
9390 JPEG_MARGIN,
9391 JPEG_RELIEF,
9392 JPEG_ALGORITHM,
9393 JPEG_HEURISTIC_MASK,
9394 JPEG_MASK,
9395 JPEG_BACKGROUND,
9396 JPEG_LAST
9397 };
9398
9399 /* Vector of image_keyword structures describing the format
9400 of valid user-defined image specifications. */
9401
9402 static struct image_keyword jpeg_format[JPEG_LAST] =
9403 {
9404 {":type", IMAGE_SYMBOL_VALUE, 1},
9405 {":data", IMAGE_STRING_VALUE, 0},
9406 {":file", IMAGE_STRING_VALUE, 0},
9407 {":ascent", IMAGE_ASCENT_VALUE, 0},
9408 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9409 {":relief", IMAGE_INTEGER_VALUE, 0},
9410 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9411 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9412 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9413 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9414 };
9415
9416 /* Structure describing the image type `jpeg'. */
9417
9418 static struct image_type jpeg_type =
9419 {
9420 &Qjpeg,
9421 jpeg_image_p,
9422 jpeg_load,
9423 x_clear_image,
9424 NULL
9425 };
9426
9427
9428 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9429
9430 static int
9431 jpeg_image_p (object)
9432 Lisp_Object object;
9433 {
9434 struct image_keyword fmt[JPEG_LAST];
9435
9436 bcopy (jpeg_format, fmt, sizeof fmt);
9437
9438 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
9439 return 0;
9440
9441 /* Must specify either the :data or :file keyword. */
9442 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
9443 }
9444
9445
9446 struct my_jpeg_error_mgr
9447 {
9448 struct jpeg_error_mgr pub;
9449 jmp_buf setjmp_buffer;
9450 };
9451
9452
9453 static void
9454 my_error_exit (cinfo)
9455 j_common_ptr cinfo;
9456 {
9457 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
9458 longjmp (mgr->setjmp_buffer, 1);
9459 }
9460
9461
9462 /* Init source method for JPEG data source manager. Called by
9463 jpeg_read_header() before any data is actually read. See
9464 libjpeg.doc from the JPEG lib distribution. */
9465
9466 static void
9467 our_init_source (cinfo)
9468 j_decompress_ptr cinfo;
9469 {
9470 }
9471
9472
9473 /* Fill input buffer method for JPEG data source manager. Called
9474 whenever more data is needed. We read the whole image in one step,
9475 so this only adds a fake end of input marker at the end. */
9476
9477 static boolean
9478 our_fill_input_buffer (cinfo)
9479 j_decompress_ptr cinfo;
9480 {
9481 /* Insert a fake EOI marker. */
9482 struct jpeg_source_mgr *src = cinfo->src;
9483 static JOCTET buffer[2];
9484
9485 buffer[0] = (JOCTET) 0xFF;
9486 buffer[1] = (JOCTET) JPEG_EOI;
9487
9488 src->next_input_byte = buffer;
9489 src->bytes_in_buffer = 2;
9490 return TRUE;
9491 }
9492
9493
9494 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9495 is the JPEG data source manager. */
9496
9497 static void
9498 our_skip_input_data (cinfo, num_bytes)
9499 j_decompress_ptr cinfo;
9500 long num_bytes;
9501 {
9502 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
9503
9504 if (src)
9505 {
9506 if (num_bytes > src->bytes_in_buffer)
9507 ERREXIT (cinfo, JERR_INPUT_EOF);
9508
9509 src->bytes_in_buffer -= num_bytes;
9510 src->next_input_byte += num_bytes;
9511 }
9512 }
9513
9514
9515 /* Method to terminate data source. Called by
9516 jpeg_finish_decompress() after all data has been processed. */
9517
9518 static void
9519 our_term_source (cinfo)
9520 j_decompress_ptr cinfo;
9521 {
9522 }
9523
9524
9525 /* Set up the JPEG lib for reading an image from DATA which contains
9526 LEN bytes. CINFO is the decompression info structure created for
9527 reading the image. */
9528
9529 static void
9530 jpeg_memory_src (cinfo, data, len)
9531 j_decompress_ptr cinfo;
9532 JOCTET *data;
9533 unsigned int len;
9534 {
9535 struct jpeg_source_mgr *src;
9536
9537 if (cinfo->src == NULL)
9538 {
9539 /* First time for this JPEG object? */
9540 cinfo->src = (struct jpeg_source_mgr *)
9541 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
9542 sizeof (struct jpeg_source_mgr));
9543 src = (struct jpeg_source_mgr *) cinfo->src;
9544 src->next_input_byte = data;
9545 }
9546
9547 src = (struct jpeg_source_mgr *) cinfo->src;
9548 src->init_source = our_init_source;
9549 src->fill_input_buffer = our_fill_input_buffer;
9550 src->skip_input_data = our_skip_input_data;
9551 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
9552 src->term_source = our_term_source;
9553 src->bytes_in_buffer = len;
9554 src->next_input_byte = data;
9555 }
9556
9557
9558 /* Load image IMG for use on frame F. Patterned after example.c
9559 from the JPEG lib. */
9560
9561 static int
9562 jpeg_load (f, img)
9563 struct frame *f;
9564 struct image *img;
9565 {
9566 struct jpeg_decompress_struct cinfo;
9567 struct my_jpeg_error_mgr mgr;
9568 Lisp_Object file, specified_file;
9569 Lisp_Object specified_data;
9570 FILE * volatile fp = NULL;
9571 JSAMPARRAY buffer;
9572 int row_stride, x, y;
9573 XImage *ximg = NULL;
9574 int rc;
9575 unsigned long *colors;
9576 int width, height;
9577 struct gcpro gcpro1;
9578
9579 /* Open the JPEG file. */
9580 specified_file = image_spec_value (img->spec, QCfile, NULL);
9581 specified_data = image_spec_value (img->spec, QCdata, NULL);
9582 file = Qnil;
9583 GCPRO1 (file);
9584
9585 if (NILP (specified_data))
9586 {
9587 file = x_find_image_file (specified_file);
9588 if (!STRINGP (file))
9589 {
9590 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9591 UNGCPRO;
9592 return 0;
9593 }
9594
9595 fp = fopen (SDATA (file), "r");
9596 if (fp == NULL)
9597 {
9598 image_error ("Cannot open `%s'", file, Qnil);
9599 UNGCPRO;
9600 return 0;
9601 }
9602 }
9603
9604 /* Customize libjpeg's error handling to call my_error_exit when an
9605 error is detected. This function will perform a longjmp. */
9606 cinfo.err = jpeg_std_error (&mgr.pub);
9607 mgr.pub.error_exit = my_error_exit;
9608
9609 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
9610 {
9611 if (rc == 1)
9612 {
9613 /* Called from my_error_exit. Display a JPEG error. */
9614 char buffer[JMSG_LENGTH_MAX];
9615 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
9616 image_error ("Error reading JPEG image `%s': %s", img->spec,
9617 build_string (buffer));
9618 }
9619
9620 /* Close the input file and destroy the JPEG object. */
9621 if (fp)
9622 fclose ((FILE *) fp);
9623 jpeg_destroy_decompress (&cinfo);
9624
9625 /* If we already have an XImage, free that. */
9626 x_destroy_x_image (ximg);
9627
9628 /* Free pixmap and colors. */
9629 x_clear_image (f, img);
9630
9631 UNGCPRO;
9632 return 0;
9633 }
9634
9635 /* Create the JPEG decompression object. Let it read from fp.
9636 Read the JPEG image header. */
9637 jpeg_create_decompress (&cinfo);
9638
9639 if (NILP (specified_data))
9640 jpeg_stdio_src (&cinfo, (FILE *) fp);
9641 else
9642 jpeg_memory_src (&cinfo, SDATA (specified_data),
9643 SBYTES (specified_data));
9644
9645 jpeg_read_header (&cinfo, TRUE);
9646
9647 /* Customize decompression so that color quantization will be used.
9648 Start decompression. */
9649 cinfo.quantize_colors = TRUE;
9650 jpeg_start_decompress (&cinfo);
9651 width = img->width = cinfo.output_width;
9652 height = img->height = cinfo.output_height;
9653
9654 /* Create X image and pixmap. */
9655 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9656 longjmp (mgr.setjmp_buffer, 2);
9657
9658 /* Allocate colors. When color quantization is used,
9659 cinfo.actual_number_of_colors has been set with the number of
9660 colors generated, and cinfo.colormap is a two-dimensional array
9661 of color indices in the range 0..cinfo.actual_number_of_colors.
9662 No more than 255 colors will be generated. */
9663 {
9664 int i, ir, ig, ib;
9665
9666 if (cinfo.out_color_components > 2)
9667 ir = 0, ig = 1, ib = 2;
9668 else if (cinfo.out_color_components > 1)
9669 ir = 0, ig = 1, ib = 0;
9670 else
9671 ir = 0, ig = 0, ib = 0;
9672
9673 /* Use the color table mechanism because it handles colors that
9674 cannot be allocated nicely. Such colors will be replaced with
9675 a default color, and we don't have to care about which colors
9676 can be freed safely, and which can't. */
9677 init_color_table ();
9678 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
9679 * sizeof *colors);
9680
9681 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9682 {
9683 /* Multiply RGB values with 255 because X expects RGB values
9684 in the range 0..0xffff. */
9685 int r = cinfo.colormap[ir][i] << 8;
9686 int g = cinfo.colormap[ig][i] << 8;
9687 int b = cinfo.colormap[ib][i] << 8;
9688 colors[i] = lookup_rgb_color (f, r, g, b);
9689 }
9690
9691 /* Remember those colors actually allocated. */
9692 img->colors = colors_in_color_table (&img->ncolors);
9693 free_color_table ();
9694 }
9695
9696 /* Read pixels. */
9697 row_stride = width * cinfo.output_components;
9698 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9699 row_stride, 1);
9700 for (y = 0; y < height; ++y)
9701 {
9702 jpeg_read_scanlines (&cinfo, buffer, 1);
9703 for (x = 0; x < cinfo.output_width; ++x)
9704 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9705 }
9706
9707 /* Clean up. */
9708 jpeg_finish_decompress (&cinfo);
9709 jpeg_destroy_decompress (&cinfo);
9710 if (fp)
9711 fclose ((FILE *) fp);
9712
9713 /* Maybe fill in the background field while we have ximg handy. */
9714 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9715 IMAGE_BACKGROUND (img, f, ximg);
9716
9717 /* Put the image into the pixmap. */
9718 x_put_x_image (f, ximg, img->pixmap, width, height);
9719 x_destroy_x_image (ximg);
9720 UNGCPRO;
9721 return 1;
9722 }
9723
9724 #endif /* HAVE_JPEG */
9725
9726
9727
9728 /***********************************************************************
9729 TIFF
9730 ***********************************************************************/
9731
9732 #if HAVE_TIFF
9733
9734 #include <tiffio.h>
9735
9736 static int tiff_image_p P_ ((Lisp_Object object));
9737 static int tiff_load P_ ((struct frame *f, struct image *img));
9738
9739 /* The symbol `tiff' identifying images of this type. */
9740
9741 Lisp_Object Qtiff;
9742
9743 /* Indices of image specification fields in tiff_format, below. */
9744
9745 enum tiff_keyword_index
9746 {
9747 TIFF_TYPE,
9748 TIFF_DATA,
9749 TIFF_FILE,
9750 TIFF_ASCENT,
9751 TIFF_MARGIN,
9752 TIFF_RELIEF,
9753 TIFF_ALGORITHM,
9754 TIFF_HEURISTIC_MASK,
9755 TIFF_MASK,
9756 TIFF_BACKGROUND,
9757 TIFF_LAST
9758 };
9759
9760 /* Vector of image_keyword structures describing the format
9761 of valid user-defined image specifications. */
9762
9763 static struct image_keyword tiff_format[TIFF_LAST] =
9764 {
9765 {":type", IMAGE_SYMBOL_VALUE, 1},
9766 {":data", IMAGE_STRING_VALUE, 0},
9767 {":file", IMAGE_STRING_VALUE, 0},
9768 {":ascent", IMAGE_ASCENT_VALUE, 0},
9769 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9770 {":relief", IMAGE_INTEGER_VALUE, 0},
9771 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9772 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9773 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9774 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9775 };
9776
9777 /* Structure describing the image type `tiff'. */
9778
9779 static struct image_type tiff_type =
9780 {
9781 &Qtiff,
9782 tiff_image_p,
9783 tiff_load,
9784 x_clear_image,
9785 NULL
9786 };
9787
9788
9789 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9790
9791 static int
9792 tiff_image_p (object)
9793 Lisp_Object object;
9794 {
9795 struct image_keyword fmt[TIFF_LAST];
9796 bcopy (tiff_format, fmt, sizeof fmt);
9797
9798 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9799 return 0;
9800
9801 /* Must specify either the :data or :file keyword. */
9802 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9803 }
9804
9805
9806 /* Reading from a memory buffer for TIFF images Based on the PNG
9807 memory source, but we have to provide a lot of extra functions.
9808 Blah.
9809
9810 We really only need to implement read and seek, but I am not
9811 convinced that the TIFF library is smart enough not to destroy
9812 itself if we only hand it the function pointers we need to
9813 override. */
9814
9815 typedef struct
9816 {
9817 unsigned char *bytes;
9818 size_t len;
9819 int index;
9820 }
9821 tiff_memory_source;
9822
9823
9824 static size_t
9825 tiff_read_from_memory (data, buf, size)
9826 thandle_t data;
9827 tdata_t buf;
9828 tsize_t size;
9829 {
9830 tiff_memory_source *src = (tiff_memory_source *) data;
9831
9832 if (size > src->len - src->index)
9833 return (size_t) -1;
9834 bcopy (src->bytes + src->index, buf, size);
9835 src->index += size;
9836 return size;
9837 }
9838
9839
9840 static size_t
9841 tiff_write_from_memory (data, buf, size)
9842 thandle_t data;
9843 tdata_t buf;
9844 tsize_t size;
9845 {
9846 return (size_t) -1;
9847 }
9848
9849
9850 static toff_t
9851 tiff_seek_in_memory (data, off, whence)
9852 thandle_t data;
9853 toff_t off;
9854 int whence;
9855 {
9856 tiff_memory_source *src = (tiff_memory_source *) data;
9857 int idx;
9858
9859 switch (whence)
9860 {
9861 case SEEK_SET: /* Go from beginning of source. */
9862 idx = off;
9863 break;
9864
9865 case SEEK_END: /* Go from end of source. */
9866 idx = src->len + off;
9867 break;
9868
9869 case SEEK_CUR: /* Go from current position. */
9870 idx = src->index + off;
9871 break;
9872
9873 default: /* Invalid `whence'. */
9874 return -1;
9875 }
9876
9877 if (idx > src->len || idx < 0)
9878 return -1;
9879
9880 src->index = idx;
9881 return src->index;
9882 }
9883
9884
9885 static int
9886 tiff_close_memory (data)
9887 thandle_t data;
9888 {
9889 /* NOOP */
9890 return 0;
9891 }
9892
9893
9894 static int
9895 tiff_mmap_memory (data, pbase, psize)
9896 thandle_t data;
9897 tdata_t *pbase;
9898 toff_t *psize;
9899 {
9900 /* It is already _IN_ memory. */
9901 return 0;
9902 }
9903
9904
9905 static void
9906 tiff_unmap_memory (data, base, size)
9907 thandle_t data;
9908 tdata_t base;
9909 toff_t size;
9910 {
9911 /* We don't need to do this. */
9912 }
9913
9914
9915 static toff_t
9916 tiff_size_of_memory (data)
9917 thandle_t data;
9918 {
9919 return ((tiff_memory_source *) data)->len;
9920 }
9921
9922
9923 static void
9924 tiff_error_handler (title, format, ap)
9925 const char *title, *format;
9926 va_list ap;
9927 {
9928 char buf[512];
9929 int len;
9930
9931 len = sprintf (buf, "TIFF error: %s ", title);
9932 vsprintf (buf + len, format, ap);
9933 add_to_log (buf, Qnil, Qnil);
9934 }
9935
9936
9937 static void
9938 tiff_warning_handler (title, format, ap)
9939 const char *title, *format;
9940 va_list ap;
9941 {
9942 char buf[512];
9943 int len;
9944
9945 len = sprintf (buf, "TIFF warning: %s ", title);
9946 vsprintf (buf + len, format, ap);
9947 add_to_log (buf, Qnil, Qnil);
9948 }
9949
9950
9951 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9952 successful. */
9953
9954 static int
9955 tiff_load (f, img)
9956 struct frame *f;
9957 struct image *img;
9958 {
9959 Lisp_Object file, specified_file;
9960 Lisp_Object specified_data;
9961 TIFF *tiff;
9962 int width, height, x, y;
9963 uint32 *buf;
9964 int rc;
9965 XImage *ximg;
9966 struct gcpro gcpro1;
9967 tiff_memory_source memsrc;
9968
9969 specified_file = image_spec_value (img->spec, QCfile, NULL);
9970 specified_data = image_spec_value (img->spec, QCdata, NULL);
9971 file = Qnil;
9972 GCPRO1 (file);
9973
9974 TIFFSetErrorHandler (tiff_error_handler);
9975 TIFFSetWarningHandler (tiff_warning_handler);
9976
9977 if (NILP (specified_data))
9978 {
9979 /* Read from a file */
9980 file = x_find_image_file (specified_file);
9981 if (!STRINGP (file))
9982 {
9983 image_error ("Cannot find image file `%s'", file, Qnil);
9984 UNGCPRO;
9985 return 0;
9986 }
9987
9988 /* Try to open the image file. */
9989 tiff = TIFFOpen (SDATA (file), "r");
9990 if (tiff == NULL)
9991 {
9992 image_error ("Cannot open `%s'", file, Qnil);
9993 UNGCPRO;
9994 return 0;
9995 }
9996 }
9997 else
9998 {
9999 /* Memory source! */
10000 memsrc.bytes = SDATA (specified_data);
10001 memsrc.len = SBYTES (specified_data);
10002 memsrc.index = 0;
10003
10004 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
10005 (TIFFReadWriteProc) tiff_read_from_memory,
10006 (TIFFReadWriteProc) tiff_write_from_memory,
10007 tiff_seek_in_memory,
10008 tiff_close_memory,
10009 tiff_size_of_memory,
10010 tiff_mmap_memory,
10011 tiff_unmap_memory);
10012
10013 if (!tiff)
10014 {
10015 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
10016 UNGCPRO;
10017 return 0;
10018 }
10019 }
10020
10021 /* Get width and height of the image, and allocate a raster buffer
10022 of width x height 32-bit values. */
10023 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
10024 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
10025 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
10026
10027 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
10028 TIFFClose (tiff);
10029 if (!rc)
10030 {
10031 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
10032 xfree (buf);
10033 UNGCPRO;
10034 return 0;
10035 }
10036
10037 /* Create the X image and pixmap. */
10038 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
10039 {
10040 xfree (buf);
10041 UNGCPRO;
10042 return 0;
10043 }
10044
10045 /* Initialize the color table. */
10046 init_color_table ();
10047
10048 /* Process the pixel raster. Origin is in the lower-left corner. */
10049 for (y = 0; y < height; ++y)
10050 {
10051 uint32 *row = buf + y * width;
10052
10053 for (x = 0; x < width; ++x)
10054 {
10055 uint32 abgr = row[x];
10056 int r = TIFFGetR (abgr) << 8;
10057 int g = TIFFGetG (abgr) << 8;
10058 int b = TIFFGetB (abgr) << 8;
10059 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
10060 }
10061 }
10062
10063 /* Remember the colors allocated for the image. Free the color table. */
10064 img->colors = colors_in_color_table (&img->ncolors);
10065 free_color_table ();
10066
10067 img->width = width;
10068 img->height = height;
10069
10070 /* Maybe fill in the background field while we have ximg handy. */
10071 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10072 IMAGE_BACKGROUND (img, f, ximg);
10073
10074 /* Put the image into the pixmap, then free the X image and its buffer. */
10075 x_put_x_image (f, ximg, img->pixmap, width, height);
10076 x_destroy_x_image (ximg);
10077 xfree (buf);
10078
10079 UNGCPRO;
10080 return 1;
10081 }
10082
10083 #endif /* HAVE_TIFF != 0 */
10084
10085
10086
10087 /***********************************************************************
10088 GIF
10089 ***********************************************************************/
10090
10091 #if HAVE_GIF
10092
10093 #include <gif_lib.h>
10094
10095 static int gif_image_p P_ ((Lisp_Object object));
10096 static int gif_load P_ ((struct frame *f, struct image *img));
10097
10098 /* The symbol `gif' identifying images of this type. */
10099
10100 Lisp_Object Qgif;
10101
10102 /* Indices of image specification fields in gif_format, below. */
10103
10104 enum gif_keyword_index
10105 {
10106 GIF_TYPE,
10107 GIF_DATA,
10108 GIF_FILE,
10109 GIF_ASCENT,
10110 GIF_MARGIN,
10111 GIF_RELIEF,
10112 GIF_ALGORITHM,
10113 GIF_HEURISTIC_MASK,
10114 GIF_MASK,
10115 GIF_IMAGE,
10116 GIF_BACKGROUND,
10117 GIF_LAST
10118 };
10119
10120 /* Vector of image_keyword structures describing the format
10121 of valid user-defined image specifications. */
10122
10123 static struct image_keyword gif_format[GIF_LAST] =
10124 {
10125 {":type", IMAGE_SYMBOL_VALUE, 1},
10126 {":data", IMAGE_STRING_VALUE, 0},
10127 {":file", IMAGE_STRING_VALUE, 0},
10128 {":ascent", IMAGE_ASCENT_VALUE, 0},
10129 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10130 {":relief", IMAGE_INTEGER_VALUE, 0},
10131 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10132 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10133 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10134 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
10135 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10136 };
10137
10138 /* Structure describing the image type `gif'. */
10139
10140 static struct image_type gif_type =
10141 {
10142 &Qgif,
10143 gif_image_p,
10144 gif_load,
10145 x_clear_image,
10146 NULL
10147 };
10148
10149
10150 /* Return non-zero if OBJECT is a valid GIF image specification. */
10151
10152 static int
10153 gif_image_p (object)
10154 Lisp_Object object;
10155 {
10156 struct image_keyword fmt[GIF_LAST];
10157 bcopy (gif_format, fmt, sizeof fmt);
10158
10159 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
10160 return 0;
10161
10162 /* Must specify either the :data or :file keyword. */
10163 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
10164 }
10165
10166
10167 /* Reading a GIF image from memory
10168 Based on the PNG memory stuff to a certain extent. */
10169
10170 typedef struct
10171 {
10172 unsigned char *bytes;
10173 size_t len;
10174 int index;
10175 }
10176 gif_memory_source;
10177
10178
10179 /* Make the current memory source available to gif_read_from_memory.
10180 It's done this way because not all versions of libungif support
10181 a UserData field in the GifFileType structure. */
10182 static gif_memory_source *current_gif_memory_src;
10183
10184 static int
10185 gif_read_from_memory (file, buf, len)
10186 GifFileType *file;
10187 GifByteType *buf;
10188 int len;
10189 {
10190 gif_memory_source *src = current_gif_memory_src;
10191
10192 if (len > src->len - src->index)
10193 return -1;
10194
10195 bcopy (src->bytes + src->index, buf, len);
10196 src->index += len;
10197 return len;
10198 }
10199
10200
10201 /* Load GIF image IMG for use on frame F. Value is non-zero if
10202 successful. */
10203
10204 static int
10205 gif_load (f, img)
10206 struct frame *f;
10207 struct image *img;
10208 {
10209 Lisp_Object file, specified_file;
10210 Lisp_Object specified_data;
10211 int rc, width, height, x, y, i;
10212 XImage *ximg;
10213 ColorMapObject *gif_color_map;
10214 unsigned long pixel_colors[256];
10215 GifFileType *gif;
10216 struct gcpro gcpro1;
10217 Lisp_Object image;
10218 int ino, image_left, image_top, image_width, image_height;
10219 gif_memory_source memsrc;
10220 unsigned char *raster;
10221
10222 specified_file = image_spec_value (img->spec, QCfile, NULL);
10223 specified_data = image_spec_value (img->spec, QCdata, NULL);
10224 file = Qnil;
10225 GCPRO1 (file);
10226
10227 if (NILP (specified_data))
10228 {
10229 file = x_find_image_file (specified_file);
10230 if (!STRINGP (file))
10231 {
10232 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10233 UNGCPRO;
10234 return 0;
10235 }
10236
10237 /* Open the GIF file. */
10238 gif = DGifOpenFileName (SDATA (file));
10239 if (gif == NULL)
10240 {
10241 image_error ("Cannot open `%s'", file, Qnil);
10242 UNGCPRO;
10243 return 0;
10244 }
10245 }
10246 else
10247 {
10248 /* Read from memory! */
10249 current_gif_memory_src = &memsrc;
10250 memsrc.bytes = SDATA (specified_data);
10251 memsrc.len = SBYTES (specified_data);
10252 memsrc.index = 0;
10253
10254 gif = DGifOpen(&memsrc, gif_read_from_memory);
10255 if (!gif)
10256 {
10257 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
10258 UNGCPRO;
10259 return 0;
10260 }
10261 }
10262
10263 /* Read entire contents. */
10264 rc = DGifSlurp (gif);
10265 if (rc == GIF_ERROR)
10266 {
10267 image_error ("Error reading `%s'", img->spec, Qnil);
10268 DGifCloseFile (gif);
10269 UNGCPRO;
10270 return 0;
10271 }
10272
10273 image = image_spec_value (img->spec, QCindex, NULL);
10274 ino = INTEGERP (image) ? XFASTINT (image) : 0;
10275 if (ino >= gif->ImageCount)
10276 {
10277 image_error ("Invalid image number `%s' in image `%s'",
10278 image, img->spec);
10279 DGifCloseFile (gif);
10280 UNGCPRO;
10281 return 0;
10282 }
10283
10284 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
10285 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
10286
10287 /* Create the X image and pixmap. */
10288 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
10289 {
10290 DGifCloseFile (gif);
10291 UNGCPRO;
10292 return 0;
10293 }
10294
10295 /* Allocate colors. */
10296 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
10297 if (!gif_color_map)
10298 gif_color_map = gif->SColorMap;
10299 init_color_table ();
10300 bzero (pixel_colors, sizeof pixel_colors);
10301
10302 for (i = 0; i < gif_color_map->ColorCount; ++i)
10303 {
10304 int r = gif_color_map->Colors[i].Red << 8;
10305 int g = gif_color_map->Colors[i].Green << 8;
10306 int b = gif_color_map->Colors[i].Blue << 8;
10307 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
10308 }
10309
10310 img->colors = colors_in_color_table (&img->ncolors);
10311 free_color_table ();
10312
10313 /* Clear the part of the screen image that are not covered by
10314 the image from the GIF file. Full animated GIF support
10315 requires more than can be done here (see the gif89 spec,
10316 disposal methods). Let's simply assume that the part
10317 not covered by a sub-image is in the frame's background color. */
10318 image_top = gif->SavedImages[ino].ImageDesc.Top;
10319 image_left = gif->SavedImages[ino].ImageDesc.Left;
10320 image_width = gif->SavedImages[ino].ImageDesc.Width;
10321 image_height = gif->SavedImages[ino].ImageDesc.Height;
10322
10323 for (y = 0; y < image_top; ++y)
10324 for (x = 0; x < width; ++x)
10325 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10326
10327 for (y = image_top + image_height; y < height; ++y)
10328 for (x = 0; x < width; ++x)
10329 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10330
10331 for (y = image_top; y < image_top + image_height; ++y)
10332 {
10333 for (x = 0; x < image_left; ++x)
10334 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10335 for (x = image_left + image_width; x < width; ++x)
10336 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10337 }
10338
10339 /* Read the GIF image into the X image. We use a local variable
10340 `raster' here because RasterBits below is a char *, and invites
10341 problems with bytes >= 0x80. */
10342 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
10343
10344 if (gif->SavedImages[ino].ImageDesc.Interlace)
10345 {
10346 static int interlace_start[] = {0, 4, 2, 1};
10347 static int interlace_increment[] = {8, 8, 4, 2};
10348 int pass;
10349 int row = interlace_start[0];
10350
10351 pass = 0;
10352
10353 for (y = 0; y < image_height; y++)
10354 {
10355 if (row >= image_height)
10356 {
10357 row = interlace_start[++pass];
10358 while (row >= image_height)
10359 row = interlace_start[++pass];
10360 }
10361
10362 for (x = 0; x < image_width; x++)
10363 {
10364 int i = raster[(y * image_width) + x];
10365 XPutPixel (ximg, x + image_left, row + image_top,
10366 pixel_colors[i]);
10367 }
10368
10369 row += interlace_increment[pass];
10370 }
10371 }
10372 else
10373 {
10374 for (y = 0; y < image_height; ++y)
10375 for (x = 0; x < image_width; ++x)
10376 {
10377 int i = raster[y * image_width + x];
10378 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
10379 }
10380 }
10381
10382 DGifCloseFile (gif);
10383
10384 /* Maybe fill in the background field while we have ximg handy. */
10385 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10386 IMAGE_BACKGROUND (img, f, ximg);
10387
10388 /* Put the image into the pixmap, then free the X image and its buffer. */
10389 x_put_x_image (f, ximg, img->pixmap, width, height);
10390 x_destroy_x_image (ximg);
10391
10392 UNGCPRO;
10393 return 1;
10394 }
10395
10396 #endif /* HAVE_GIF != 0 */
10397
10398
10399
10400 /***********************************************************************
10401 Ghostscript
10402 ***********************************************************************/
10403
10404 static int gs_image_p P_ ((Lisp_Object object));
10405 static int gs_load P_ ((struct frame *f, struct image *img));
10406 static void gs_clear_image P_ ((struct frame *f, struct image *img));
10407
10408 /* The symbol `postscript' identifying images of this type. */
10409
10410 Lisp_Object Qpostscript;
10411
10412 /* Keyword symbols. */
10413
10414 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
10415
10416 /* Indices of image specification fields in gs_format, below. */
10417
10418 enum gs_keyword_index
10419 {
10420 GS_TYPE,
10421 GS_PT_WIDTH,
10422 GS_PT_HEIGHT,
10423 GS_FILE,
10424 GS_LOADER,
10425 GS_BOUNDING_BOX,
10426 GS_ASCENT,
10427 GS_MARGIN,
10428 GS_RELIEF,
10429 GS_ALGORITHM,
10430 GS_HEURISTIC_MASK,
10431 GS_MASK,
10432 GS_BACKGROUND,
10433 GS_LAST
10434 };
10435
10436 /* Vector of image_keyword structures describing the format
10437 of valid user-defined image specifications. */
10438
10439 static struct image_keyword gs_format[GS_LAST] =
10440 {
10441 {":type", IMAGE_SYMBOL_VALUE, 1},
10442 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10443 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10444 {":file", IMAGE_STRING_VALUE, 1},
10445 {":loader", IMAGE_FUNCTION_VALUE, 0},
10446 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
10447 {":ascent", IMAGE_ASCENT_VALUE, 0},
10448 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10449 {":relief", IMAGE_INTEGER_VALUE, 0},
10450 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10451 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10452 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10453 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10454 };
10455
10456 /* Structure describing the image type `ghostscript'. */
10457
10458 static struct image_type gs_type =
10459 {
10460 &Qpostscript,
10461 gs_image_p,
10462 gs_load,
10463 gs_clear_image,
10464 NULL
10465 };
10466
10467
10468 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10469
10470 static void
10471 gs_clear_image (f, img)
10472 struct frame *f;
10473 struct image *img;
10474 {
10475 /* IMG->data.ptr_val may contain a recorded colormap. */
10476 xfree (img->data.ptr_val);
10477 x_clear_image (f, img);
10478 }
10479
10480
10481 /* Return non-zero if OBJECT is a valid Ghostscript image
10482 specification. */
10483
10484 static int
10485 gs_image_p (object)
10486 Lisp_Object object;
10487 {
10488 struct image_keyword fmt[GS_LAST];
10489 Lisp_Object tem;
10490 int i;
10491
10492 bcopy (gs_format, fmt, sizeof fmt);
10493
10494 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
10495 return 0;
10496
10497 /* Bounding box must be a list or vector containing 4 integers. */
10498 tem = fmt[GS_BOUNDING_BOX].value;
10499 if (CONSP (tem))
10500 {
10501 for (i = 0; i < 4; ++i, tem = XCDR (tem))
10502 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
10503 return 0;
10504 if (!NILP (tem))
10505 return 0;
10506 }
10507 else if (VECTORP (tem))
10508 {
10509 if (XVECTOR (tem)->size != 4)
10510 return 0;
10511 for (i = 0; i < 4; ++i)
10512 if (!INTEGERP (XVECTOR (tem)->contents[i]))
10513 return 0;
10514 }
10515 else
10516 return 0;
10517
10518 return 1;
10519 }
10520
10521
10522 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10523 if successful. */
10524
10525 static int
10526 gs_load (f, img)
10527 struct frame *f;
10528 struct image *img;
10529 {
10530 char buffer[100];
10531 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
10532 struct gcpro gcpro1, gcpro2;
10533 Lisp_Object frame;
10534 double in_width, in_height;
10535 Lisp_Object pixel_colors = Qnil;
10536
10537 /* Compute pixel size of pixmap needed from the given size in the
10538 image specification. Sizes in the specification are in pt. 1 pt
10539 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10540 info. */
10541 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
10542 in_width = XFASTINT (pt_width) / 72.0;
10543 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
10544 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
10545 in_height = XFASTINT (pt_height) / 72.0;
10546 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
10547
10548 /* Create the pixmap. */
10549 xassert (img->pixmap == None);
10550 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10551 img->width, img->height,
10552 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
10553
10554 if (!img->pixmap)
10555 {
10556 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
10557 return 0;
10558 }
10559
10560 /* Call the loader to fill the pixmap. It returns a process object
10561 if successful. We do not record_unwind_protect here because
10562 other places in redisplay like calling window scroll functions
10563 don't either. Let the Lisp loader use `unwind-protect' instead. */
10564 GCPRO2 (window_and_pixmap_id, pixel_colors);
10565
10566 sprintf (buffer, "%lu %lu",
10567 (unsigned long) FRAME_X_WINDOW (f),
10568 (unsigned long) img->pixmap);
10569 window_and_pixmap_id = build_string (buffer);
10570
10571 sprintf (buffer, "%lu %lu",
10572 FRAME_FOREGROUND_PIXEL (f),
10573 FRAME_BACKGROUND_PIXEL (f));
10574 pixel_colors = build_string (buffer);
10575
10576 XSETFRAME (frame, f);
10577 loader = image_spec_value (img->spec, QCloader, NULL);
10578 if (NILP (loader))
10579 loader = intern ("gs-load-image");
10580
10581 img->data.lisp_val = call6 (loader, frame, img->spec,
10582 make_number (img->width),
10583 make_number (img->height),
10584 window_and_pixmap_id,
10585 pixel_colors);
10586 UNGCPRO;
10587 return PROCESSP (img->data.lisp_val);
10588 }
10589
10590
10591 /* Kill the Ghostscript process that was started to fill PIXMAP on
10592 frame F. Called from XTread_socket when receiving an event
10593 telling Emacs that Ghostscript has finished drawing. */
10594
10595 void
10596 x_kill_gs_process (pixmap, f)
10597 Pixmap pixmap;
10598 struct frame *f;
10599 {
10600 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
10601 int class, i;
10602 struct image *img;
10603
10604 /* Find the image containing PIXMAP. */
10605 for (i = 0; i < c->used; ++i)
10606 if (c->images[i]->pixmap == pixmap)
10607 break;
10608
10609 /* Should someone in between have cleared the image cache, for
10610 instance, give up. */
10611 if (i == c->used)
10612 return;
10613
10614 /* Kill the GS process. We should have found PIXMAP in the image
10615 cache and its image should contain a process object. */
10616 img = c->images[i];
10617 xassert (PROCESSP (img->data.lisp_val));
10618 Fkill_process (img->data.lisp_val, Qnil);
10619 img->data.lisp_val = Qnil;
10620
10621 /* On displays with a mutable colormap, figure out the colors
10622 allocated for the image by looking at the pixels of an XImage for
10623 img->pixmap. */
10624 class = FRAME_X_VISUAL (f)->class;
10625 if (class != StaticColor && class != StaticGray && class != TrueColor)
10626 {
10627 XImage *ximg;
10628
10629 BLOCK_INPUT;
10630
10631 /* Try to get an XImage for img->pixmep. */
10632 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10633 0, 0, img->width, img->height, ~0, ZPixmap);
10634 if (ximg)
10635 {
10636 int x, y;
10637
10638 /* Initialize the color table. */
10639 init_color_table ();
10640
10641 /* For each pixel of the image, look its color up in the
10642 color table. After having done so, the color table will
10643 contain an entry for each color used by the image. */
10644 for (y = 0; y < img->height; ++y)
10645 for (x = 0; x < img->width; ++x)
10646 {
10647 unsigned long pixel = XGetPixel (ximg, x, y);
10648 lookup_pixel_color (f, pixel);
10649 }
10650
10651 /* Record colors in the image. Free color table and XImage. */
10652 img->colors = colors_in_color_table (&img->ncolors);
10653 free_color_table ();
10654 XDestroyImage (ximg);
10655
10656 #if 0 /* This doesn't seem to be the case. If we free the colors
10657 here, we get a BadAccess later in x_clear_image when
10658 freeing the colors. */
10659 /* We have allocated colors once, but Ghostscript has also
10660 allocated colors on behalf of us. So, to get the
10661 reference counts right, free them once. */
10662 if (img->ncolors)
10663 x_free_colors (f, img->colors, img->ncolors);
10664 #endif
10665 }
10666 else
10667 image_error ("Cannot get X image of `%s'; colors will not be freed",
10668 img->spec, Qnil);
10669
10670 UNBLOCK_INPUT;
10671 }
10672
10673 /* Now that we have the pixmap, compute mask and transform the
10674 image if requested. */
10675 BLOCK_INPUT;
10676 postprocess_image (f, img);
10677 UNBLOCK_INPUT;
10678 }
10679
10680
10681
10682 /***********************************************************************
10683 Window properties 4126 Window properties
10684 ***********************************************************************/ 4127 ***********************************************************************/
10685 4128
10686 DEFUN ("x-change-window-property", Fx_change_window_property, 4129 DEFUN ("x-change-window-property", Fx_change_window_property,
10687 Sx_change_window_property, 2, 3, 0, 4130 Sx_change_window_property, 2, 6, 0,
10688 doc: /* Change window property PROP to VALUE on the X window of FRAME. 4131 doc: /* Change window property PROP to VALUE on the X window of FRAME.
10689 PROP and VALUE must be strings. FRAME nil or omitted means use the 4132 PROP must be a string.
10690 selected frame. Value is VALUE. */) 4133 VALUE may be a string or a list of conses, numbers and/or strings.
10691 (prop, value, frame) 4134 If an element in the list is a string, it is converted to
10692 Lisp_Object frame, prop, value; 4135 an Atom and the value of the Atom is used. If an element is a cons,
4136 it is converted to a 32 bit number where the car is the 16 top bits and the
4137 cdr is the lower 16 bits.
4138 FRAME nil or omitted means use the selected frame.
4139 If TYPE is given and non-nil, it is the name of the type of VALUE.
4140 If TYPE is not given or nil, the type is STRING.
4141 FORMAT gives the size in bits of each element if VALUE is a list.
4142 It must be one of 8, 16 or 32.
4143 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
4144 If OUTER_P is non-nil, the property is changed for the outer X window of
4145 FRAME. Default is to change on the edit X window.
4146
4147 Value is VALUE. */)
4148 (prop, value, frame, type, format, outer_p)
4149 Lisp_Object prop, value, frame, type, format, outer_p;
10693 { 4150 {
10694 struct frame *f = check_x_frame (frame); 4151 struct frame *f = check_x_frame (frame);
10695 Atom prop_atom; 4152 Atom prop_atom;
4153 Atom target_type = XA_STRING;
4154 int element_format = 8;
4155 unsigned char *data;
4156 int nelements;
4157 Window w;
10696 4158
10697 CHECK_STRING (prop); 4159 CHECK_STRING (prop);
10698 CHECK_STRING (value); 4160
4161 if (! NILP (format))
4162 {
4163 CHECK_NUMBER (format);
4164 element_format = XFASTINT (format);
4165
4166 if (element_format != 8 && element_format != 16
4167 && element_format != 32)
4168 error ("FORMAT must be one of 8, 16 or 32");
4169 }
4170
4171 if (CONSP (value))
4172 {
4173 nelements = x_check_property_data (value);
4174 if (nelements == -1)
4175 error ("Bad data in VALUE, must be number, string or cons");
4176
4177 if (element_format == 8)
4178 data = (unsigned char *) xmalloc (nelements);
4179 else if (element_format == 16)
4180 data = (unsigned char *) xmalloc (nelements*2);
4181 else /* format == 32 */
4182 /* The man page for XChangeProperty:
4183 "If the specified format is 32, the property data must be a
4184 long array."
4185 This applies even if long is more than 64 bits. The X library
4186 converts to 32 bits before sending to the X server. */
4187 data = (unsigned char *) xmalloc (nelements * sizeof(long));
4188
4189 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
4190 }
4191 else
4192 {
4193 CHECK_STRING (value);
4194 data = SDATA (value);
4195 nelements = SCHARS (value);
4196 }
10699 4197
10700 BLOCK_INPUT; 4198 BLOCK_INPUT;
10701 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False); 4199 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
10702 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 4200 if (! NILP (type))
10703 prop_atom, XA_STRING, 8, PropModeReplace, 4201 {
10704 SDATA (value), SCHARS (value)); 4202 CHECK_STRING (type);
4203 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4204 }
4205
4206 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
4207 else w = FRAME_X_WINDOW (f);
4208
4209 XChangeProperty (FRAME_X_DISPLAY (f), w,
4210 prop_atom, target_type, element_format, PropModeReplace,
4211 data, nelements);
4212
4213 if (CONSP (value)) xfree (data);
10705 4214
10706 /* Make sure the property is set when we return. */ 4215 /* Make sure the property is set when we return. */
10707 XFlush (FRAME_X_DISPLAY (f)); 4216 XFlush (FRAME_X_DISPLAY (f));
10708 UNBLOCK_INPUT; 4217 UNBLOCK_INPUT;
10709 4218
10733 return prop; 4242 return prop;
10734 } 4243 }
10735 4244
10736 4245
10737 DEFUN ("x-window-property", Fx_window_property, Sx_window_property, 4246 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
10738 1, 2, 0, 4247 1, 6, 0,
10739 doc: /* Value is the value of window property PROP on FRAME. 4248 doc: /* Value is the value of window property PROP on FRAME.
10740 If FRAME is nil or omitted, use the selected frame. Value is nil 4249 If FRAME is nil or omitted, use the selected frame.
10741 if FRAME hasn't a property with name PROP or if PROP has no string 4250 If TYPE is nil or omitted, get the property as a string. Otherwise TYPE
10742 value. */) 4251 is the name of the Atom that denotes the type expected.
10743 (prop, frame) 4252 If SOURCE is non-nil, get the property on that window instead of from
10744 Lisp_Object prop, frame; 4253 FRAME. The number 0 denotes the root window.
4254 If DELETE_P is non-nil, delete the property after retreiving it.
4255 If VECTOR_RET_P is non-nil, don't return a string but a vector of values.
4256
4257 Value is nil if FRAME hasn't a property with name PROP or if PROP has
4258 no value of TYPE. */)
4259 (prop, frame, type, source, delete_p, vector_ret_p)
4260 Lisp_Object prop, frame, type, source, delete_p, vector_ret_p;
10745 { 4261 {
10746 struct frame *f = check_x_frame (frame); 4262 struct frame *f = check_x_frame (frame);
10747 Atom prop_atom; 4263 Atom prop_atom;
10748 int rc; 4264 int rc;
10749 Lisp_Object prop_value = Qnil; 4265 Lisp_Object prop_value = Qnil;
10750 char *tmp_data = NULL; 4266 unsigned char *tmp_data = NULL;
10751 Atom actual_type; 4267 Atom actual_type;
4268 Atom target_type = XA_STRING;
10752 int actual_format; 4269 int actual_format;
10753 unsigned long actual_size, bytes_remaining; 4270 unsigned long actual_size, bytes_remaining;
10754 4271 Window target_window = FRAME_X_WINDOW (f);
4272 struct gcpro gcpro1;
4273
4274 GCPRO1 (prop_value);
10755 CHECK_STRING (prop); 4275 CHECK_STRING (prop);
4276
4277 if (! NILP (source))
4278 {
4279 if (NUMBERP (source))
4280 {
4281 if (FLOATP (source))
4282 target_window = (Window) XFLOAT (source);
4283 else
4284 target_window = XFASTINT (source);
4285
4286 if (target_window == 0)
4287 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4288 }
4289 else if (CONSP (source))
4290 target_window = cons_to_long (source);
4291 }
4292
10756 BLOCK_INPUT; 4293 BLOCK_INPUT;
4294 if (STRINGP (type))
4295 {
4296 if (strcmp ("AnyPropertyType", SDATA (type)) == 0)
4297 target_type = AnyPropertyType;
4298 else
4299 target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
4300 }
4301
10757 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False); 4302 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
10758 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 4303 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
10759 prop_atom, 0, 0, False, XA_STRING, 4304 prop_atom, 0, 0, False, target_type,
10760 &actual_type, &actual_format, &actual_size, 4305 &actual_type, &actual_format, &actual_size,
10761 &bytes_remaining, (unsigned char **) &tmp_data); 4306 &bytes_remaining, &tmp_data);
10762 if (rc == Success) 4307 if (rc == Success)
10763 { 4308 {
10764 int size = bytes_remaining; 4309 int size = bytes_remaining;
10765 4310
10766 XFree (tmp_data); 4311 XFree (tmp_data);
10767 tmp_data = NULL; 4312 tmp_data = NULL;
10768 4313
10769 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 4314 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
10770 prop_atom, 0, bytes_remaining, 4315 prop_atom, 0, bytes_remaining,
10771 False, XA_STRING, 4316 ! NILP (delete_p), target_type,
10772 &actual_type, &actual_format, 4317 &actual_type, &actual_format,
10773 &actual_size, &bytes_remaining, 4318 &actual_size, &bytes_remaining,
10774 (unsigned char **) &tmp_data); 4319 &tmp_data);
10775 if (rc == Success && tmp_data) 4320 if (rc == Success && tmp_data)
10776 prop_value = make_string (tmp_data, size); 4321 {
10777 4322 /* The man page for XGetWindowProperty says:
10778 XFree (tmp_data); 4323 "If the returned format is 32, the returned data is represented
4324 as a long array and should be cast to that type to obtain the
4325 elements."
4326 This applies even if long is more than 32 bits, the X library
4327 converts from 32 bit elements received from the X server to long
4328 and passes the long array to us. Thus, for that case bcopy can not
4329 be used. We convert to a 32 bit type here, because so much code
4330 assume on that.
4331
4332 The bytes and offsets passed to XGetWindowProperty refers to the
4333 property and those are indeed in 32 bit quantities if format is
4334 32. */
4335
4336 if (actual_format == 32 && actual_format < BITS_PER_LONG)
4337 {
4338 unsigned long i;
4339 int *idata = (int *) tmp_data;
4340 long *ldata = (long *) tmp_data;
4341
4342 for (i = 0; i < actual_size; ++i)
4343 idata[i] = (int) ldata[i];
4344 }
4345
4346 if (NILP (vector_ret_p))
4347 prop_value = make_string (tmp_data, size);
4348 else
4349 prop_value = x_property_data_to_lisp (f,
4350 tmp_data,
4351 actual_type,
4352 actual_format,
4353 actual_size);
4354 }
4355
4356 if (tmp_data) XFree (tmp_data);
10779 } 4357 }
10780 4358
10781 UNBLOCK_INPUT; 4359 UNBLOCK_INPUT;
4360 UNGCPRO;
10782 return prop_value; 4361 return prop_value;
10783 } 4362 }
10784 4363
10785 4364
10786 4365
10809 /* Function prototypes. */ 4388 /* Function prototypes. */
10810 4389
10811 static void show_hourglass P_ ((struct atimer *)); 4390 static void show_hourglass P_ ((struct atimer *));
10812 static void hide_hourglass P_ ((void)); 4391 static void hide_hourglass P_ ((void));
10813 4392
4393 /* Return non-zero if houglass timer has been started or hourglass is shown. */
4394
4395 int
4396 hourglass_started ()
4397 {
4398 return hourglass_shown_p || hourglass_atimer != NULL;
4399 }
4400
10814 4401
10815 /* Cancel a currently active hourglass timer, and start a new one. */ 4402 /* Cancel a currently active hourglass timer, and start a new one. */
10816 4403
10817 void 4404 void
10818 start_hourglass () 4405 start_hourglass ()
10819 { 4406 {
10820 EMACS_TIME delay; 4407 EMACS_TIME delay;
10821 int secs, usecs = 0; 4408 int secs, usecs = 0;
4409
4410 /* Don't bother for ttys. */
4411 if (NILP (Vwindow_system))
4412 return;
10822 4413
10823 cancel_hourglass (); 4414 cancel_hourglass ();
10824 4415
10825 if (INTEGERP (Vhourglass_delay) 4416 if (INTEGERP (Vhourglass_delay)
10826 && XINT (Vhourglass_delay) > 0) 4417 && XINT (Vhourglass_delay) > 0)
10900 4491
10901 if (!f->output_data.x->hourglass_window) 4492 if (!f->output_data.x->hourglass_window)
10902 { 4493 {
10903 unsigned long mask = CWCursor; 4494 unsigned long mask = CWCursor;
10904 XSetWindowAttributes attrs; 4495 XSetWindowAttributes attrs;
10905 4496 #ifdef USE_GTK
4497 Window parent = FRAME_X_WINDOW (f);
4498 #else
4499 Window parent = FRAME_OUTER_WINDOW (f);
4500 #endif
10906 attrs.cursor = f->output_data.x->hourglass_cursor; 4501 attrs.cursor = f->output_data.x->hourglass_cursor;
10907 4502
10908 f->output_data.x->hourglass_window 4503 f->output_data.x->hourglass_window
10909 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f), 4504 = XCreateWindow (dpy, parent,
10910 0, 0, 32000, 32000, 0, 0, 4505 0, 0, 32000, 32000, 0, 0,
10911 InputOnly, 4506 InputOnly,
10912 CopyFromParent, 4507 CopyFromParent,
10913 mask, &attrs); 4508 mask, &attrs);
10914 } 4509 }
11032 Lisp_Object buffer; 4627 Lisp_Object buffer;
11033 struct buffer *old_buffer; 4628 struct buffer *old_buffer;
11034 4629
11035 check_x (); 4630 check_x ();
11036 4631
11037 /* Use this general default value to start with until we know if
11038 this frame has a specified name. */
11039 Vx_resource_name = Vinvocation_name;
11040 4632
11041 #ifdef MULTI_KBOARD 4633 #ifdef MULTI_KBOARD
11042 kb = dpyinfo->kboard; 4634 kb = dpyinfo->kboard;
11043 #else 4635 #else
11044 kb = &the_only_kboard; 4636 kb = &the_only_kboard;
11048 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); 4640 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
11049 if (!STRINGP (name) 4641 if (!STRINGP (name)
11050 && !EQ (name, Qunbound) 4642 && !EQ (name, Qunbound)
11051 && !NILP (name)) 4643 && !NILP (name))
11052 error ("Invalid frame name--not a string or nil"); 4644 error ("Invalid frame name--not a string or nil");
11053 Vx_resource_name = name;
11054 4645
11055 frame = Qnil; 4646 frame = Qnil;
11056 GCPRO3 (parms, name, frame); 4647 GCPRO3 (parms, name, frame);
11057 f = make_frame (1); 4648 f = make_frame (1);
11058 XSETFRAME (frame, f); 4649 XSETFRAME (frame, f);
11059 4650
11060 buffer = Fget_buffer_create (build_string (" *tip*")); 4651 buffer = Fget_buffer_create (build_string (" *tip*"));
11061 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer); 4652 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
11062 old_buffer = current_buffer; 4653 old_buffer = current_buffer;
11063 set_buffer_internal_1 (XBUFFER (buffer)); 4654 set_buffer_internal_1 (XBUFFER (buffer));
11064 current_buffer->truncate_lines = Qnil; 4655 current_buffer->truncate_lines = Qnil;
4656 specbind (Qinhibit_read_only, Qt);
4657 specbind (Qinhibit_modification_hooks, Qt);
11065 Ferase_buffer (); 4658 Ferase_buffer ();
11066 Finsert (1, &text); 4659 Finsert (1, &text);
11067 set_buffer_internal_1 (old_buffer); 4660 set_buffer_internal_1 (old_buffer);
11068 4661
11069 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; 4662 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
11075 counts etc. */ 4668 counts etc. */
11076 f->output_method = output_x_window; 4669 f->output_method = output_x_window;
11077 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output)); 4670 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
11078 bzero (f->output_data.x, sizeof (struct x_output)); 4671 bzero (f->output_data.x, sizeof (struct x_output));
11079 f->output_data.x->icon_bitmap = -1; 4672 f->output_data.x->icon_bitmap = -1;
11080 f->output_data.x->fontset = -1; 4673 FRAME_FONTSET (f) = -1;
11081 f->output_data.x->scroll_bar_foreground_pixel = -1; 4674 f->output_data.x->scroll_bar_foreground_pixel = -1;
11082 f->output_data.x->scroll_bar_background_pixel = -1; 4675 f->output_data.x->scroll_bar_background_pixel = -1;
11083 #ifdef USE_TOOLKIT_SCROLL_BARS 4676 #ifdef USE_TOOLKIT_SCROLL_BARS
11084 f->output_data.x->scroll_bar_top_shadow_pixel = -1; 4677 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
11085 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; 4678 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
11214 end up in init_iterator with a null face cache, which should not 4807 end up in init_iterator with a null face cache, which should not
11215 happen. */ 4808 happen. */
11216 init_frame_faces (f); 4809 init_frame_faces (f);
11217 4810
11218 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window; 4811 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
11219 window_prompting = x_figure_window_size (f, parms); 4812
11220 4813 window_prompting = x_figure_window_size (f, parms, 0);
11221 if (window_prompting & XNegative) 4814
11222 {
11223 if (window_prompting & YNegative)
11224 f->output_data.x->win_gravity = SouthEastGravity;
11225 else
11226 f->output_data.x->win_gravity = NorthEastGravity;
11227 }
11228 else
11229 {
11230 if (window_prompting & YNegative)
11231 f->output_data.x->win_gravity = SouthWestGravity;
11232 else
11233 f->output_data.x->win_gravity = NorthWestGravity;
11234 }
11235
11236 f->output_data.x->size_hint_flags = window_prompting;
11237 { 4815 {
11238 XSetWindowAttributes attrs; 4816 XSetWindowAttributes attrs;
11239 unsigned long mask; 4817 unsigned long mask;
11240 4818
11241 BLOCK_INPUT; 4819 BLOCK_INPUT;
11271 x_default_parameter (f, parms, Qauto_lower, Qnil, 4849 x_default_parameter (f, parms, Qauto_lower, Qnil,
11272 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); 4850 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
11273 x_default_parameter (f, parms, Qcursor_type, Qbox, 4851 x_default_parameter (f, parms, Qcursor_type, Qbox,
11274 "cursorType", "CursorType", RES_TYPE_SYMBOL); 4852 "cursorType", "CursorType", RES_TYPE_SYMBOL);
11275 4853
11276 /* Dimensions, especially f->height, must be done via change_frame_size. 4854 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
11277 Change will not be effected unless different from the current 4855 Change will not be effected unless different from the current
11278 f->height. */ 4856 FRAME_LINES (f). */
11279 width = f->width; 4857 width = FRAME_COLS (f);
11280 height = f->height; 4858 height = FRAME_LINES (f);
11281 f->height = 0; 4859 SET_FRAME_COLS (f, 0);
11282 SET_FRAME_WIDTH (f, 0); 4860 FRAME_LINES (f) = 0;
11283 change_frame_size (f, height, width, 1, 0, 0); 4861 change_frame_size (f, height, width, 1, 0, 0);
11284 4862
11285 /* Add `tooltip' frame parameter's default value. */ 4863 /* Add `tooltip' frame parameter's default value. */
11286 if (NILP (Fframe_parameter (frame, intern ("tooltip")))) 4864 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
11287 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt), 4865 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
11364 UNBLOCK_INPUT; 4942 UNBLOCK_INPUT;
11365 } 4943 }
11366 4944
11367 if (INTEGERP (top)) 4945 if (INTEGERP (top))
11368 *root_y = XINT (top); 4946 *root_y = XINT (top);
11369 else if (*root_y + XINT (dy) - height < 0) 4947 else if (*root_y + XINT (dy) <= 0)
11370 *root_y -= XINT (dy); 4948 *root_y = 0; /* Can happen for negative dy */
4949 else if (*root_y + XINT (dy) + height <= FRAME_X_DISPLAY_INFO (f)->height)
4950 /* It fits below the pointer */
4951 *root_y += XINT (dy);
4952 else if (height + XINT (dy) <= *root_y)
4953 /* It fits above the pointer. */
4954 *root_y -= height + XINT (dy);
11371 else 4955 else
11372 { 4956 /* Put it on the top. */
11373 *root_y -= height; 4957 *root_y = 0;
11374 *root_y += XINT (dy);
11375 }
11376 4958
11377 if (INTEGERP (left)) 4959 if (INTEGERP (left))
11378 *root_x = XINT (left); 4960 *root_x = XINT (left);
4961 else if (*root_x + XINT (dx) <= 0)
4962 *root_x = 0; /* Can happen for negative dx */
11379 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width) 4963 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
11380 /* It fits to the right of the pointer. */ 4964 /* It fits to the right of the pointer. */
11381 *root_x += XINT (dx); 4965 *root_x += XINT (dx);
11382 else if (width + XINT (dx) <= *root_x) 4966 else if (width + XINT (dx) <= *root_x)
11383 /* It fits to the left of the pointer. */ 4967 /* It fits to the left of the pointer. */
11466 tip_timer = Qnil; 5050 tip_timer = Qnil;
11467 call1 (Qcancel_timer, timer); 5051 call1 (Qcancel_timer, timer);
11468 } 5052 }
11469 5053
11470 BLOCK_INPUT; 5054 BLOCK_INPUT;
11471 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f), 5055 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
11472 PIXEL_HEIGHT (f), &root_x, &root_y); 5056 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
11473 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 5057 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11474 root_x, root_y); 5058 root_x, root_y);
11475 UNBLOCK_INPUT; 5059 UNBLOCK_INPUT;
11476 goto start_timer; 5060 goto start_timer;
11477 } 5061 }
11502 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string); 5086 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
11503 f = XFRAME (frame); 5087 f = XFRAME (frame);
11504 5088
11505 /* Set up the frame's root window. */ 5089 /* Set up the frame's root window. */
11506 w = XWINDOW (FRAME_ROOT_WINDOW (f)); 5090 w = XWINDOW (FRAME_ROOT_WINDOW (f));
11507 w->left = w->top = make_number (0); 5091 w->left_col = w->top_line = make_number (0);
11508 5092
11509 if (CONSP (Vx_max_tooltip_size) 5093 if (CONSP (Vx_max_tooltip_size)
11510 && INTEGERP (XCAR (Vx_max_tooltip_size)) 5094 && INTEGERP (XCAR (Vx_max_tooltip_size))
11511 && XINT (XCAR (Vx_max_tooltip_size)) > 0 5095 && XINT (XCAR (Vx_max_tooltip_size)) > 0
11512 && INTEGERP (XCDR (Vx_max_tooltip_size)) 5096 && INTEGERP (XCDR (Vx_max_tooltip_size))
11513 && XINT (XCDR (Vx_max_tooltip_size)) > 0) 5097 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
11514 { 5098 {
11515 w->width = XCAR (Vx_max_tooltip_size); 5099 w->total_cols = XCAR (Vx_max_tooltip_size);
11516 w->height = XCDR (Vx_max_tooltip_size); 5100 w->total_lines = XCDR (Vx_max_tooltip_size);
11517 } 5101 }
11518 else 5102 else
11519 { 5103 {
11520 w->width = make_number (80); 5104 w->total_cols = make_number (80);
11521 w->height = make_number (40); 5105 w->total_lines = make_number (40);
11522 } 5106 }
11523 5107
11524 f->window_width = XINT (w->width); 5108 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
11525 adjust_glyphs (f); 5109 adjust_glyphs (f);
11526 w->pseudo_window_p = 1; 5110 w->pseudo_window_p = 1;
11527 5111
11528 /* Display the tooltip text in a temporary buffer. */ 5112 /* Display the tooltip text in a temporary buffer. */
11529 old_buffer = current_buffer; 5113 old_buffer = current_buffer;
11530 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer)); 5114 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
11531 current_buffer->truncate_lines = Qnil; 5115 current_buffer->truncate_lines = Qnil;
11532 clear_glyph_matrix (w->desired_matrix); 5116 clear_glyph_matrix (w->desired_matrix);
11533 clear_glyph_matrix (w->current_matrix); 5117 clear_glyph_matrix (w->current_matrix);
11534 SET_TEXT_POS (pos, BEGV, BEGV_BYTE); 5118 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
11535 try_window (FRAME_ROOT_WINDOW (f), pos); 5119 try_window (FRAME_ROOT_WINDOW (f), pos, 0);
11536 5120
11537 /* Compute width and height of the tooltip. */ 5121 /* Compute width and height of the tooltip. */
11538 width = height = 0; 5122 width = height = 0;
11539 for (i = 0; i < w->desired_matrix->nrows; ++i) 5123 for (i = 0; i < w->desired_matrix->nrows; ++i)
11540 { 5124 {
11654 5238
11655 /*********************************************************************** 5239 /***********************************************************************
11656 File selection dialog 5240 File selection dialog
11657 ***********************************************************************/ 5241 ***********************************************************************/
11658 5242
5243 DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
5244 Sx_uses_old_gtk_dialog,
5245 0, 0, 0,
5246 doc: /* Return t if the old Gtk+ file selection dialog is used. */)
5247 ()
5248 {
5249 #ifdef USE_GTK
5250 extern int use_dialog_box;
5251 extern int use_file_dialog;
5252
5253 if (use_dialog_box
5254 && use_file_dialog
5255 && have_menus_p ()
5256 && xg_uses_old_file_dialog ())
5257 return Qt;
5258 #endif
5259 return Qnil;
5260 }
5261
5262
11659 #ifdef USE_MOTIF 5263 #ifdef USE_MOTIF
11660
11661 /* Callback for "OK" and "Cancel" on file selection dialog. */ 5264 /* Callback for "OK" and "Cancel" on file selection dialog. */
11662 5265
11663 static void 5266 static void
11664 file_dialog_cb (widget, client_data, call_data) 5267 file_dialog_cb (widget, client_data, call_data)
11665 Widget widget; 5268 Widget widget;
11683 { 5286 {
11684 int *result = (int *) client_data; 5287 int *result = (int *) client_data;
11685 *result = XmCR_CANCEL; 5288 *result = XmCR_CANCEL;
11686 } 5289 }
11687 5290
11688 5291 static Lisp_Object
11689 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0, 5292 clean_up_file_dialog (arg)
5293 Lisp_Object arg;
5294 {
5295 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
5296 Widget dialog = (Widget) p->pointer;
5297
5298 /* Clean up. */
5299 BLOCK_INPUT;
5300 XtUnmanageChild (dialog);
5301 XtDestroyWidget (dialog);
5302 x_menu_set_in_use (0);
5303 UNBLOCK_INPUT;
5304
5305 return Qnil;
5306 }
5307
5308
5309 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
11690 doc: /* Read file name, prompting with PROMPT in directory DIR. 5310 doc: /* Read file name, prompting with PROMPT in directory DIR.
11691 Use a file selection dialog. 5311 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
11692 Select DEFAULT-FILENAME in the dialog's file selection box, if 5312 selection box, if specified. If MUSTMATCH is non-nil, the returned file
11693 specified. Don't let the user enter a file name in the file 5313 or directory must exist. ONLY-DIR-P is ignored." */)
11694 selection dialog's entry field, if MUSTMATCH is non-nil. */) 5314 (prompt, dir, default_filename, mustmatch, only_dir_p)
11695 (prompt, dir, default_filename, mustmatch) 5315 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
11696 Lisp_Object prompt, dir, default_filename, mustmatch;
11697 { 5316 {
11698 int result; 5317 int result;
11699 struct frame *f = SELECTED_FRAME (); 5318 struct frame *f = SELECTED_FRAME ();
11700 Lisp_Object file = Qnil; 5319 Lisp_Object file = Qnil;
11701 Widget dialog, text, list, help; 5320 Widget dialog, text, help;
11702 Arg al[10]; 5321 Arg al[10];
11703 int ac = 0; 5322 int ac = 0;
11704 extern XtAppContext Xt_app_con; 5323 extern XtAppContext Xt_app_con;
11705 XmString dir_xmstring, pattern_xmstring; 5324 XmString dir_xmstring, pattern_xmstring;
11706 int count = SPECPDL_INDEX (); 5325 int count = SPECPDL_INDEX ();
11707 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 5326 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
11708 5327
11709 GCPRO5 (prompt, dir, default_filename, mustmatch, file); 5328 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
5329
5330 if (popup_activated ())
5331 error ("Trying to use a menu from within a menu-entry");
5332
11710 CHECK_STRING (prompt); 5333 CHECK_STRING (prompt);
11711 CHECK_STRING (dir); 5334 CHECK_STRING (dir);
11712 5335
11713 /* Prevent redisplay. */ 5336 /* Prevent redisplay. */
11714 specbind (Qinhibit_redisplay, Qt); 5337 specbind (Qinhibit_redisplay, Qt);
11737 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb, 5360 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
11738 (XtPointer) &result); 5361 (XtPointer) &result);
11739 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb, 5362 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
11740 (XtPointer) &result); 5363 (XtPointer) &result);
11741 5364
11742 /* Disable the help button since we can't display help. */ 5365 /* Remove the help button since we can't display help. */
11743 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON); 5366 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
11744 XtSetSensitive (help, False); 5367 XtUnmanageChild (help);
11745 5368
11746 /* Mark OK button as default. */ 5369 /* Mark OK button as default. */
11747 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON), 5370 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
11748 XmNshowAsDefault, True, NULL); 5371 XmNshowAsDefault, True, NULL);
11749 5372
11761 } 5384 }
11762 5385
11763 /* Manage the dialog, so that list boxes get filled. */ 5386 /* Manage the dialog, so that list boxes get filled. */
11764 XtManageChild (dialog); 5387 XtManageChild (dialog);
11765 5388
11766 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11767 must include the path for this to work. */
11768 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11769 if (STRINGP (default_filename)) 5389 if (STRINGP (default_filename))
11770 { 5390 {
11771 XmString default_xmstring; 5391 XmString default_xmstring;
11772 int item_pos; 5392 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
11773 5393 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11774 default_xmstring 5394
11775 = XmStringCreateLocalized (SDATA (default_filename)); 5395 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
11776 5396 XmTextFieldReplace (wtext, 0, last_pos,
11777 if (!XmListItemExists (list, default_xmstring)) 5397 (SDATA (Ffile_name_nondirectory (default_filename))));
11778 { 5398
11779 /* Add a new item if DEFAULT_FILENAME is not in the list. */ 5399 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11780 XmListAddItem (list, default_xmstring, 0); 5400 must include the path for this to work. */
11781 item_pos = 0; 5401
11782 } 5402 default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
11783 else 5403
11784 item_pos = XmListItemPos (list, default_xmstring); 5404 if (XmListItemExists (list, default_xmstring))
5405 {
5406 int item_pos = XmListItemPos (list, default_xmstring);
5407 /* Select the item and scroll it into view. */
5408 XmListSelectPos (list, item_pos, True);
5409 XmListSetPos (list, item_pos);
5410 }
5411
11785 XmStringFree (default_xmstring); 5412 XmStringFree (default_xmstring);
11786 5413 }
11787 /* Select the item and scroll it into view. */ 5414
11788 XmListSelectPos (list, item_pos, True); 5415 record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
11789 XmListSetPos (list, item_pos);
11790 }
11791 5416
11792 /* Process events until the user presses Cancel or OK. */ 5417 /* Process events until the user presses Cancel or OK. */
5418 x_menu_set_in_use (1);
11793 result = 0; 5419 result = 0;
11794 while (result == 0) 5420 while (result == 0)
11795 { 5421 {
11796 XEvent event; 5422 XEvent event;
5423 x_menu_wait_for_event (0);
11797 XtAppNextEvent (Xt_app_con, &event); 5424 XtAppNextEvent (Xt_app_con, &event);
11798 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f) ); 5425 if (event.type == KeyPress
5426 && FRAME_X_DISPLAY (f) == event.xkey.display)
5427 {
5428 KeySym keysym = XLookupKeysym (&event.xkey, 0);
5429
5430 /* Pop down on C-g. */
5431 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
5432 XtUnmanageChild (dialog);
5433 }
5434
5435 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
11799 } 5436 }
11800 5437
11801 /* Get the result. */ 5438 /* Get the result. */
11802 if (result == XmCR_OK) 5439 if (result == XmCR_OK)
11803 { 5440 {
11811 XtFree (data); 5448 XtFree (data);
11812 } 5449 }
11813 else 5450 else
11814 file = Qnil; 5451 file = Qnil;
11815 5452
11816 /* Clean up. */
11817 XtUnmanageChild (dialog);
11818 XtDestroyWidget (dialog);
11819 UNBLOCK_INPUT; 5453 UNBLOCK_INPUT;
11820 UNGCPRO; 5454 UNGCPRO;
11821 5455
11822 /* Make "Cancel" equivalent to C-g. */ 5456 /* Make "Cancel" equivalent to C-g. */
11823 if (NILP (file)) 5457 if (NILP (file))
11828 5462
11829 #endif /* USE_MOTIF */ 5463 #endif /* USE_MOTIF */
11830 5464
11831 #ifdef USE_GTK 5465 #ifdef USE_GTK
11832 5466
11833 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0, 5467 static Lisp_Object
11834 "Read file name, prompting with PROMPT in directory DIR.\n\ 5468 clean_up_dialog (arg)
11835 Use a file selection dialog.\n\ 5469 Lisp_Object arg;
11836 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\ 5470 {
11837 specified. Don't let the user enter a file name in the file\n\ 5471 x_menu_set_in_use (0);
11838 selection dialog's entry field, if MUSTMATCH is non-nil.") 5472
11839 (prompt, dir, default_filename, mustmatch) 5473 return Qnil;
11840 Lisp_Object prompt, dir, default_filename, mustmatch; 5474 }
5475
5476 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
5477 doc: /* Read file name, prompting with PROMPT in directory DIR.
5478 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5479 selection box, if specified. If MUSTMATCH is non-nil, the returned file
5480 or directory must exist. If ONLY-DIR-P is non-nil, the user can only select
5481 directories. */)
5482 (prompt, dir, default_filename, mustmatch, only_dir_p)
5483 Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
11841 { 5484 {
11842 FRAME_PTR f = SELECTED_FRAME (); 5485 FRAME_PTR f = SELECTED_FRAME ();
11843 char *fn; 5486 char *fn;
11844 Lisp_Object file = Qnil; 5487 Lisp_Object file = Qnil;
11845 int count = specpdl_ptr - specpdl; 5488 int count = SPECPDL_INDEX ();
11846 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 5489 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
11847 char *cdef_file; 5490 char *cdef_file;
11848 char *cprompt; 5491
11849 5492 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
11850 GCPRO5 (prompt, dir, default_filename, mustmatch, file); 5493
5494 if (popup_activated ())
5495 error ("Trying to use a menu from within a menu-entry");
5496
11851 CHECK_STRING (prompt); 5497 CHECK_STRING (prompt);
11852 CHECK_STRING (dir); 5498 CHECK_STRING (dir);
11853 5499
11854 /* Prevent redisplay. */ 5500 /* Prevent redisplay. */
11855 specbind (Qinhibit_redisplay, Qt); 5501 specbind (Qinhibit_redisplay, Qt);
5502 record_unwind_protect (clean_up_dialog, Qnil);
11856 5503
11857 BLOCK_INPUT; 5504 BLOCK_INPUT;
11858 5505
11859 if (STRINGP (default_filename)) 5506 if (STRINGP (default_filename))
11860 cdef_file = SDATA (default_filename); 5507 cdef_file = SDATA (default_filename);
11861 else 5508 else
11862 cdef_file = SDATA (dir); 5509 cdef_file = SDATA (dir);
11863 5510
11864 fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch)); 5511 fn = xg_get_file_name (f, SDATA (prompt), cdef_file,
5512 ! NILP (mustmatch),
5513 ! NILP (only_dir_p));
11865 5514
11866 if (fn) 5515 if (fn)
11867 { 5516 {
11868 file = build_string (fn); 5517 file = build_string (fn);
11869 xfree (fn); 5518 xfree (fn);
11894 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p, 5543 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
11895 Sx_backspace_delete_keys_p, 0, 1, 0, 5544 Sx_backspace_delete_keys_p, 0, 1, 0,
11896 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME. 5545 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11897 FRAME nil means use the selected frame. 5546 FRAME nil means use the selected frame.
11898 Value is t if we know that both keys are present, and are mapped to the 5547 Value is t if we know that both keys are present, and are mapped to the
11899 usual X keysyms. */) 5548 usual X keysyms. Value is `lambda' if we cannot determine if both keys are
5549 present and mapped to the usual X keysyms. */)
11900 (frame) 5550 (frame)
11901 Lisp_Object frame; 5551 Lisp_Object frame;
11902 { 5552 {
11903 #ifdef HAVE_XKBGETKEYBOARD 5553 #ifdef HAVE_XKBGETKEYBOARD
11904 XkbDescPtr kb; 5554 XkbDescPtr kb;
11913 major = XkbMajorVersion; 5563 major = XkbMajorVersion;
11914 minor = XkbMinorVersion; 5564 minor = XkbMinorVersion;
11915 if (!XkbLibraryVersion (&major, &minor)) 5565 if (!XkbLibraryVersion (&major, &minor))
11916 { 5566 {
11917 UNBLOCK_INPUT; 5567 UNBLOCK_INPUT;
11918 return Qnil; 5568 return Qlambda;
11919 } 5569 }
11920 5570
11921 /* Check that the server supports XKB. */ 5571 /* Check that the server supports XKB. */
11922 major = XkbMajorVersion; 5572 major = XkbMajorVersion;
11923 minor = XkbMinorVersion; 5573 minor = XkbMinorVersion;
11924 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor)) 5574 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
11925 { 5575 {
11926 UNBLOCK_INPUT; 5576 UNBLOCK_INPUT;
11927 return Qnil; 5577 return Qlambda;
11928 } 5578 }
5579
5580 /* In this code we check that the keyboard has physical keys with names
5581 that start with BKSP (Backspace) and DELE (Delete), and that they
5582 generate keysym XK_BackSpace and XK_Delete respectively.
5583 This function is used to test if normal-erase-is-backspace should be
5584 turned on.
5585 An alternative approach would be to just check if XK_BackSpace and
5586 XK_Delete are mapped to any key. But if any of those are mapped to
5587 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
5588 user doesn't know about it, it is better to return false here.
5589 It is more obvious to the user what to do if she/he has two keys
5590 clearly marked with names/symbols and one key does something not
5591 expected (i.e. she/he then tries the other).
5592 The cases where Backspace/Delete is mapped to some other key combination
5593 are rare, and in those cases, normal-erase-is-backspace can be turned on
5594 manually. */
11929 5595
11930 have_keys = Qnil; 5596 have_keys = Qnil;
11931 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd); 5597 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
11932 if (kb) 5598 if (kb)
11933 { 5599 {
11961 have_keys = Qt; 5627 have_keys = Qt;
11962 } 5628 }
11963 UNBLOCK_INPUT; 5629 UNBLOCK_INPUT;
11964 return have_keys; 5630 return have_keys;
11965 #else /* not HAVE_XKBGETKEYBOARD */ 5631 #else /* not HAVE_XKBGETKEYBOARD */
11966 return Qnil; 5632 return Qlambda;
11967 #endif /* not HAVE_XKBGETKEYBOARD */ 5633 #endif /* not HAVE_XKBGETKEYBOARD */
11968 } 5634 }
11969 5635
11970 5636
11971 5637
11972 /*********************************************************************** 5638 /***********************************************************************
11973 Initialization 5639 Initialization
11974 ***********************************************************************/ 5640 ***********************************************************************/
11975 5641
5642 /* Keep this list in the same order as frame_parms in frame.c.
5643 Use 0 for unsupported frame parameters. */
5644
5645 frame_parm_handler x_frame_parm_handlers[] =
5646 {
5647 x_set_autoraise,
5648 x_set_autolower,
5649 x_set_background_color,
5650 x_set_border_color,
5651 x_set_border_width,
5652 x_set_cursor_color,
5653 x_set_cursor_type,
5654 x_set_font,
5655 x_set_foreground_color,
5656 x_set_icon_name,
5657 x_set_icon_type,
5658 x_set_internal_border_width,
5659 x_set_menu_bar_lines,
5660 x_set_mouse_color,
5661 x_explicitly_set_name,
5662 x_set_scroll_bar_width,
5663 x_set_title,
5664 x_set_unsplittable,
5665 x_set_vertical_scroll_bars,
5666 x_set_visibility,
5667 x_set_tool_bar_lines,
5668 x_set_scroll_bar_foreground,
5669 x_set_scroll_bar_background,
5670 x_set_screen_gamma,
5671 x_set_line_spacing,
5672 x_set_fringe_width,
5673 x_set_fringe_width,
5674 x_set_wait_for_wm,
5675 x_set_fullscreen,
5676 };
5677
11976 void 5678 void
11977 syms_of_xfns () 5679 syms_of_xfns ()
11978 { 5680 {
11979 /* This is zero if not using X windows. */ 5681 /* This is zero if not using X windows. */
11980 x_in_use = 0; 5682 x_in_use = 0;
11981 5683
11982 /* The section below is built by the lisp expression at the top of the file, 5684 /* The section below is built by the lisp expression at the top of the file,
11983 just above where these variables are declared. */ 5685 just above where these variables are declared. */
11984 /*&&& init symbols here &&&*/ 5686 /*&&& init symbols here &&&*/
11985 Qauto_raise = intern ("auto-raise");
11986 staticpro (&Qauto_raise);
11987 Qauto_lower = intern ("auto-lower");
11988 staticpro (&Qauto_lower);
11989 Qborder_color = intern ("border-color");
11990 staticpro (&Qborder_color);
11991 Qborder_width = intern ("border-width");
11992 staticpro (&Qborder_width);
11993 Qcursor_color = intern ("cursor-color");
11994 staticpro (&Qcursor_color);
11995 Qcursor_type = intern ("cursor-type");
11996 staticpro (&Qcursor_type);
11997 Qgeometry = intern ("geometry");
11998 staticpro (&Qgeometry);
11999 Qicon_left = intern ("icon-left");
12000 staticpro (&Qicon_left);
12001 Qicon_top = intern ("icon-top");
12002 staticpro (&Qicon_top);
12003 Qicon_type = intern ("icon-type");
12004 staticpro (&Qicon_type);
12005 Qicon_name = intern ("icon-name");
12006 staticpro (&Qicon_name);
12007 Qinternal_border_width = intern ("internal-border-width");
12008 staticpro (&Qinternal_border_width);
12009 Qleft = intern ("left");
12010 staticpro (&Qleft);
12011 Qright = intern ("right");
12012 staticpro (&Qright);
12013 Qmouse_color = intern ("mouse-color");
12014 staticpro (&Qmouse_color);
12015 Qnone = intern ("none"); 5687 Qnone = intern ("none");
12016 staticpro (&Qnone); 5688 staticpro (&Qnone);
12017 Qparent_id = intern ("parent-id");
12018 staticpro (&Qparent_id);
12019 Qscroll_bar_width = intern ("scroll-bar-width");
12020 staticpro (&Qscroll_bar_width);
12021 Qsuppress_icon = intern ("suppress-icon"); 5689 Qsuppress_icon = intern ("suppress-icon");
12022 staticpro (&Qsuppress_icon); 5690 staticpro (&Qsuppress_icon);
12023 Qundefined_color = intern ("undefined-color"); 5691 Qundefined_color = intern ("undefined-color");
12024 staticpro (&Qundefined_color); 5692 staticpro (&Qundefined_color);
12025 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
12026 staticpro (&Qvertical_scroll_bars);
12027 Qvisibility = intern ("visibility");
12028 staticpro (&Qvisibility);
12029 Qwindow_id = intern ("window-id");
12030 staticpro (&Qwindow_id);
12031 Qouter_window_id = intern ("outer-window-id");
12032 staticpro (&Qouter_window_id);
12033 Qx_frame_parameter = intern ("x-frame-parameter");
12034 staticpro (&Qx_frame_parameter);
12035 Qx_resource_name = intern ("x-resource-name");
12036 staticpro (&Qx_resource_name);
12037 Quser_position = intern ("user-position");
12038 staticpro (&Quser_position);
12039 Quser_size = intern ("user-size");
12040 staticpro (&Quser_size);
12041 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
12042 staticpro (&Qscroll_bar_foreground);
12043 Qscroll_bar_background = intern ("scroll-bar-background");
12044 staticpro (&Qscroll_bar_background);
12045 Qscreen_gamma = intern ("screen-gamma");
12046 staticpro (&Qscreen_gamma);
12047 Qline_spacing = intern ("line-spacing");
12048 staticpro (&Qline_spacing);
12049 Qcenter = intern ("center");
12050 staticpro (&Qcenter);
12051 Qcompound_text = intern ("compound-text"); 5693 Qcompound_text = intern ("compound-text");
12052 staticpro (&Qcompound_text); 5694 staticpro (&Qcompound_text);
12053 Qcancel_timer = intern ("cancel-timer"); 5695 Qcancel_timer = intern ("cancel-timer");
12054 staticpro (&Qcancel_timer); 5696 staticpro (&Qcancel_timer);
12055 Qwait_for_wm = intern ("wait-for-wm");
12056 staticpro (&Qwait_for_wm);
12057 Qfullscreen = intern ("fullscreen");
12058 staticpro (&Qfullscreen);
12059 Qfullwidth = intern ("fullwidth");
12060 staticpro (&Qfullwidth);
12061 Qfullheight = intern ("fullheight");
12062 staticpro (&Qfullheight);
12063 Qfullboth = intern ("fullboth");
12064 staticpro (&Qfullboth);
12065 /* This is the end of symbol initialization. */ 5697 /* This is the end of symbol initialization. */
12066 5698
12067 /* Text property `display' should be nonsticky by default. */ 5699 /* Text property `display' should be nonsticky by default. */
12068 Vtext_property_default_nonsticky 5700 Vtext_property_default_nonsticky
12069 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky); 5701 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
12070 5702
12071
12072 Qlaplace = intern ("laplace");
12073 staticpro (&Qlaplace);
12074 Qemboss = intern ("emboss");
12075 staticpro (&Qemboss);
12076 Qedge_detection = intern ("edge-detection");
12077 staticpro (&Qedge_detection);
12078 Qheuristic = intern ("heuristic");
12079 staticpro (&Qheuristic);
12080 QCmatrix = intern (":matrix");
12081 staticpro (&QCmatrix);
12082 QCcolor_adjustment = intern (":color-adjustment");
12083 staticpro (&QCcolor_adjustment);
12084 QCmask = intern (":mask");
12085 staticpro (&QCmask);
12086
12087 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
12088 staticpro (&Qface_set_after_frame_default);
12089 5703
12090 Fput (Qundefined_color, Qerror_conditions, 5704 Fput (Qundefined_color, Qerror_conditions,
12091 Fcons (Qundefined_color, Fcons (Qerror, Qnil))); 5705 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
12092 Fput (Qundefined_color, Qerror_message, 5706 Fput (Qundefined_color, Qerror_message,
12093 build_string ("Undefined color")); 5707 build_string ("Undefined color"));
12094
12095 init_x_parm_symbols ();
12096
12097 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
12098 doc: /* Non-nil means always draw a cross over disabled images.
12099 Disabled images are those having an `:conversion disabled' property.
12100 A cross is always drawn on black & white displays. */);
12101 cross_disabled_images = 0;
12102
12103 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
12104 doc: /* List of directories to search for window system bitmap files. */);
12105 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
12106 5708
12107 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape, 5709 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
12108 doc: /* The shape of the pointer when over text. 5710 doc: /* The shape of the pointer when over text.
12109 Changing the value does not affect existing frames 5711 Changing the value does not affect existing frames
12110 unless you set the mouse color. */); 5712 unless you set the mouse color. */);
12111 Vx_pointer_shape = Qnil; 5713 Vx_pointer_shape = Qnil;
12112
12113 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
12114 doc: /* The name Emacs uses to look up X resources.
12115 `x-get-resource' uses this as the first component of the instance name
12116 when requesting resource values.
12117 Emacs initially sets `x-resource-name' to the name under which Emacs
12118 was invoked, or to the value specified with the `-name' or `-rn'
12119 switches, if present.
12120
12121 It may be useful to bind this variable locally around a call
12122 to `x-get-resource'. See also the variable `x-resource-class'. */);
12123 Vx_resource_name = Qnil;
12124
12125 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
12126 doc: /* The class Emacs uses to look up X resources.
12127 `x-get-resource' uses this as the first component of the instance class
12128 when requesting resource values.
12129
12130 Emacs initially sets `x-resource-class' to "Emacs".
12131
12132 Setting this variable permanently is not a reasonable thing to do,
12133 but binding this variable locally around a call to `x-get-resource'
12134 is a reasonable practice. See also the variable `x-resource-name'. */);
12135 Vx_resource_class = build_string (EMACS_CLASS);
12136 5714
12137 #if 0 /* This doesn't really do anything. */ 5715 #if 0 /* This doesn't really do anything. */
12138 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape, 5716 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
12139 doc: /* The shape of the pointer when not over text. 5717 doc: /* The shape of the pointer when not over text.
12140 This variable takes effect when you create a new frame 5718 This variable takes effect when you create a new frame
12204 PIXEL_SIZE field of the name, font finding mechanism gets faster for 5782 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12205 such a font. This is especially effective for such large fonts as 5783 such a font. This is especially effective for such large fonts as
12206 Chinese, Japanese, and Korean. */); 5784 Chinese, Japanese, and Korean. */);
12207 Vx_pixel_size_width_font_regexp = Qnil; 5785 Vx_pixel_size_width_font_regexp = Qnil;
12208 5786
12209 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay, 5787 /* This is not ifdef:ed, so other builds than GTK can customize it. */
12210 doc: /* Time after which cached images are removed from the cache. 5788 DEFVAR_BOOL ("x-use-old-gtk-file-dialog", &x_use_old_gtk_file_dialog,
12211 When an image has not been displayed this many seconds, remove it 5789 doc: /* *Non-nil means prompt with the old GTK file selection dialog.
12212 from the image cache. Value must be an integer or nil with nil 5790 If nil or if the file selection dialog is not available, the new GTK file
12213 meaning don't clear the cache. */); 5791 chooser is used instead. To turn off all file dialogs set the
12214 Vimage_cache_eviction_delay = make_number (30 * 60); 5792 variable `use-file-dialog'. */);
5793 x_use_old_gtk_file_dialog = 0;
5794
5795 DEFVAR_BOOL ("x-gtk-show-hidden-files", &x_gtk_show_hidden_files,
5796 doc: /* *If non-nil, the GTK file chooser will by default show hidden files.
5797 Note that this is just the default, there is a toggle button on the file
5798 chooser to show or not show hidden files on a case by case basis. */);
5799 x_gtk_show_hidden_files = 0;
5800
5801 Fprovide (intern ("x"), Qnil);
12215 5802
12216 #ifdef USE_X_TOOLKIT 5803 #ifdef USE_X_TOOLKIT
12217 Fprovide (intern ("x-toolkit"), Qnil); 5804 Fprovide (intern ("x-toolkit"), Qnil);
12218 #ifdef USE_MOTIF 5805 #ifdef USE_MOTIF
12219 Fprovide (intern ("motif"), Qnil); 5806 Fprovide (intern ("motif"), Qnil);
12222 doc: /* Version info for LessTif/Motif. */); 5809 doc: /* Version info for LessTif/Motif. */);
12223 Vmotif_version_string = build_string (XmVERSION_STRING); 5810 Vmotif_version_string = build_string (XmVERSION_STRING);
12224 #endif /* USE_MOTIF */ 5811 #endif /* USE_MOTIF */
12225 #endif /* USE_X_TOOLKIT */ 5812 #endif /* USE_X_TOOLKIT */
12226 5813
12227 defsubr (&Sx_get_resource); 5814 #ifdef USE_GTK
5815 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
5816 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
5817 But for a user it is a toolkit for X, and indeed, configure
5818 accepts --with-x-toolkit=gtk. */
5819 Fprovide (intern ("x-toolkit"), Qnil);
5820 Fprovide (intern ("gtk"), Qnil);
5821
5822 DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
5823 doc: /* Version info for GTK+. */);
5824 {
5825 char gtk_version[40];
5826 g_snprintf (gtk_version, sizeof (gtk_version), "%u.%u.%u",
5827 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
5828 Vgtk_version_string = build_string (gtk_version);
5829 }
5830 #endif /* USE_GTK */
12228 5831
12229 /* X window properties. */ 5832 /* X window properties. */
12230 defsubr (&Sx_change_window_property); 5833 defsubr (&Sx_change_window_property);
12231 defsubr (&Sx_delete_window_property); 5834 defsubr (&Sx_delete_window_property);
12232 defsubr (&Sx_window_property); 5835 defsubr (&Sx_window_property);
12246 defsubr (&Sx_display_planes); 5849 defsubr (&Sx_display_planes);
12247 defsubr (&Sx_display_color_cells); 5850 defsubr (&Sx_display_color_cells);
12248 defsubr (&Sx_display_visual_class); 5851 defsubr (&Sx_display_visual_class);
12249 defsubr (&Sx_display_backing_store); 5852 defsubr (&Sx_display_backing_store);
12250 defsubr (&Sx_display_save_under); 5853 defsubr (&Sx_display_save_under);
12251 defsubr (&Sx_parse_geometry);
12252 defsubr (&Sx_create_frame); 5854 defsubr (&Sx_create_frame);
12253 defsubr (&Sx_open_connection); 5855 defsubr (&Sx_open_connection);
12254 defsubr (&Sx_close_connection); 5856 defsubr (&Sx_close_connection);
12255 defsubr (&Sx_display_list); 5857 defsubr (&Sx_display_list);
12256 defsubr (&Sx_synchronize); 5858 defsubr (&Sx_synchronize);
12269 find_ccl_program_func = x_find_ccl_program; 5871 find_ccl_program_func = x_find_ccl_program;
12270 query_font_func = x_query_font; 5872 query_font_func = x_query_font;
12271 set_frame_fontset_func = x_set_font; 5873 set_frame_fontset_func = x_set_font;
12272 check_window_system_func = check_x; 5874 check_window_system_func = check_x;
12273 5875
12274 /* Images. */
12275 Qxbm = intern ("xbm");
12276 staticpro (&Qxbm);
12277 QCconversion = intern (":conversion");
12278 staticpro (&QCconversion);
12279 QCheuristic_mask = intern (":heuristic-mask");
12280 staticpro (&QCheuristic_mask);
12281 QCcolor_symbols = intern (":color-symbols");
12282 staticpro (&QCcolor_symbols);
12283 QCascent = intern (":ascent");
12284 staticpro (&QCascent);
12285 QCmargin = intern (":margin");
12286 staticpro (&QCmargin);
12287 QCrelief = intern (":relief");
12288 staticpro (&QCrelief);
12289 Qpostscript = intern ("postscript");
12290 staticpro (&Qpostscript);
12291 QCloader = intern (":loader");
12292 staticpro (&QCloader);
12293 QCbounding_box = intern (":bounding-box");
12294 staticpro (&QCbounding_box);
12295 QCpt_width = intern (":pt-width");
12296 staticpro (&QCpt_width);
12297 QCpt_height = intern (":pt-height");
12298 staticpro (&QCpt_height);
12299 QCindex = intern (":index");
12300 staticpro (&QCindex);
12301 Qpbm = intern ("pbm");
12302 staticpro (&Qpbm);
12303
12304 #if HAVE_XPM
12305 Qxpm = intern ("xpm");
12306 staticpro (&Qxpm);
12307 #endif
12308
12309 #if HAVE_JPEG
12310 Qjpeg = intern ("jpeg");
12311 staticpro (&Qjpeg);
12312 #endif
12313
12314 #if HAVE_TIFF
12315 Qtiff = intern ("tiff");
12316 staticpro (&Qtiff);
12317 #endif
12318
12319 #if HAVE_GIF
12320 Qgif = intern ("gif");
12321 staticpro (&Qgif);
12322 #endif
12323
12324 #if HAVE_PNG
12325 Qpng = intern ("png");
12326 staticpro (&Qpng);
12327 #endif
12328
12329 defsubr (&Sclear_image_cache);
12330 defsubr (&Simage_size);
12331 defsubr (&Simage_mask_p);
12332
12333 hourglass_atimer = NULL; 5876 hourglass_atimer = NULL;
12334 hourglass_shown_p = 0; 5877 hourglass_shown_p = 0;
12335 5878
12336 defsubr (&Sx_show_tip); 5879 defsubr (&Sx_show_tip);
12337 defsubr (&Sx_hide_tip); 5880 defsubr (&Sx_hide_tip);
12341 staticpro (&tip_frame); 5884 staticpro (&tip_frame);
12342 5885
12343 last_show_tip_args = Qnil; 5886 last_show_tip_args = Qnil;
12344 staticpro (&last_show_tip_args); 5887 staticpro (&last_show_tip_args);
12345 5888
12346 #ifdef USE_MOTIF 5889 defsubr (&Sx_uses_old_gtk_dialog);
5890 #if defined (USE_MOTIF) || defined (USE_GTK)
12347 defsubr (&Sx_file_dialog); 5891 defsubr (&Sx_file_dialog);
12348 #endif 5892 #endif
12349 } 5893 }
12350 5894
12351
12352 void
12353 init_xfns ()
12354 {
12355 image_types = NULL;
12356 Vimage_types = Qnil;
12357
12358 define_image_type (&xbm_type);
12359 define_image_type (&gs_type);
12360 define_image_type (&pbm_type);
12361
12362 #if HAVE_XPM
12363 define_image_type (&xpm_type);
12364 #endif
12365
12366 #if HAVE_JPEG
12367 define_image_type (&jpeg_type);
12368 #endif
12369
12370 #if HAVE_TIFF
12371 define_image_type (&tiff_type);
12372 #endif
12373
12374 #if HAVE_GIF
12375 define_image_type (&gif_type);
12376 #endif
12377
12378 #if HAVE_PNG
12379 define_image_type (&png_type);
12380 #endif
12381 }
12382
12383 #endif /* HAVE_X_WINDOWS */ 5895 #endif /* HAVE_X_WINDOWS */
5896
5897 /* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
5898 (do not change this comment) */