1 /* Graphical user interface functions for the Microsoft W32 API.
2 Copyright (C) 1989, 92, 93, 94, 95, 1996, 1997, 1998, 1999
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Added by Kevin Gallo */
37 #include "dispextern.h"
39 #include "intervals.h"
41 #include "blockinput.h"
44 #include "termhooks.h"
49 #include "bitmaps/gray.xbm"
55 extern void free_frame_menubar ();
56 extern double atof ();
57 extern int w32_console_toggle_lock_key (int vk_code
, Lisp_Object new_state
);
60 /* A definition of XColor for non-X frames. */
61 #ifndef HAVE_X_WINDOWS
64 unsigned short red
, green
, blue
;
70 extern char *lispy_function_keys
[];
72 /* The gray bitmap `bitmaps/gray'. This is done because w32term.c uses
73 it, and including `bitmaps/gray' more than once is a problem when
74 config.h defines `static' as an empty replacement string. */
76 int gray_bitmap_width
= gray_width
;
77 int gray_bitmap_height
= gray_height
;
78 unsigned char *gray_bitmap_bits
= gray_bits
;
80 /* The colormap for converting color names to RGB values */
81 Lisp_Object Vw32_color_map
;
83 /* Non nil if alt key presses are passed on to Windows. */
84 Lisp_Object Vw32_pass_alt_to_system
;
86 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
88 Lisp_Object Vw32_alt_is_meta
;
90 /* If non-zero, the windows virtual key code for an alternative quit key. */
91 Lisp_Object Vw32_quit_key
;
93 /* Non nil if left window key events are passed on to Windows (this only
94 affects whether "tapping" the key opens the Start menu). */
95 Lisp_Object Vw32_pass_lwindow_to_system
;
97 /* Non nil if right window key events are passed on to Windows (this
98 only affects whether "tapping" the key opens the Start menu). */
99 Lisp_Object Vw32_pass_rwindow_to_system
;
101 /* Virtual key code used to generate "phantom" key presses in order
102 to stop system from acting on Windows key events. */
103 Lisp_Object Vw32_phantom_key_code
;
105 /* Modifier associated with the left "Windows" key, or nil to act as a
107 Lisp_Object Vw32_lwindow_modifier
;
109 /* Modifier associated with the right "Windows" key, or nil to act as a
111 Lisp_Object Vw32_rwindow_modifier
;
113 /* Modifier associated with the "Apps" key, or nil to act as a normal
115 Lisp_Object Vw32_apps_modifier
;
117 /* Value is nil if Num Lock acts as a function key. */
118 Lisp_Object Vw32_enable_num_lock
;
120 /* Value is nil if Caps Lock acts as a function key. */
121 Lisp_Object Vw32_enable_caps_lock
;
123 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
124 Lisp_Object Vw32_scroll_lock_modifier
;
126 /* Switch to control whether we inhibit requests for synthesized bold
127 and italic versions of fonts. */
128 Lisp_Object Vw32_enable_synthesized_fonts
;
130 /* Enable palette management. */
131 Lisp_Object Vw32_enable_palette
;
133 /* Control how close left/right button down events must be to
134 be converted to a middle button down event. */
135 Lisp_Object Vw32_mouse_button_tolerance
;
137 /* Minimum interval between mouse movement (and scroll bar drag)
138 events that are passed on to the event loop. */
139 Lisp_Object Vw32_mouse_move_interval
;
141 /* The name we're using in resource queries. */
142 Lisp_Object Vx_resource_name
;
144 /* Non nil if no window manager is in use. */
145 Lisp_Object Vx_no_window_manager
;
147 /* Non-zero means we're allowed to display a busy cursor. */
149 int display_busy_cursor_p
;
151 /* The background and shape of the mouse pointer, and shape when not
152 over text or in the modeline. */
154 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
155 Lisp_Object Vx_busy_pointer_shape
;
157 /* The shape when over mouse-sensitive text. */
159 Lisp_Object Vx_sensitive_text_pointer_shape
;
161 /* Color of chars displayed in cursor box. */
163 Lisp_Object Vx_cursor_fore_pixel
;
165 /* Nonzero if using Windows. */
167 static int w32_in_use
;
169 /* Search path for bitmap files. */
171 Lisp_Object Vx_bitmap_file_path
;
173 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
175 Lisp_Object Vx_pixel_size_width_font_regexp
;
177 /* Alist of bdf fonts and the files that define them. */
178 Lisp_Object Vw32_bdf_filename_alist
;
180 Lisp_Object Vw32_system_coding_system
;
182 /* A flag to control whether fonts are matched strictly or not. */
183 int w32_strict_fontnames
;
185 /* A flag to control whether we should only repaint if GetUpdateRect
186 indicates there is an update region. */
187 int w32_strict_painting
;
189 /* Associative list linking character set strings to Windows codepages. */
190 Lisp_Object Vw32_charset_info_alist
;
192 /* VIETNAMESE_CHARSET is not defined in some versions of MSVC. */
193 #ifndef VIETNAMESE_CHARSET
194 #define VIETNAMESE_CHARSET 163
198 /* Evaluate this expression to rebuild the section of syms_of_w32fns
199 that initializes and staticpros the symbols declared below. Note
200 that Emacs 18 has a bug that keeps C-x C-e from being able to
201 evaluate this expression.
204 ;; Accumulate a list of the symbols we want to initialize from the
205 ;; declarations at the top of the file.
206 (goto-char (point-min))
207 (search-forward "/\*&&& symbols declared here &&&*\/\n")
209 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
211 (cons (buffer-substring (match-beginning 1) (match-end 1))
214 (setq symbol-list (nreverse symbol-list))
215 ;; Delete the section of syms_of_... where we initialize the symbols.
216 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
217 (let ((start (point)))
218 (while (looking-at "^ Q")
220 (kill-region start (point)))
221 ;; Write a new symbol initialization section.
223 (insert (format " %s = intern (\"" (car symbol-list)))
224 (let ((start (point)))
225 (insert (substring (car symbol-list) 1))
226 (subst-char-in-region start (point) ?_ ?-))
227 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
228 (setq symbol-list (cdr symbol-list)))))
232 /*&&& symbols declared here &&&*/
233 Lisp_Object Qauto_raise
;
234 Lisp_Object Qauto_lower
;
236 Lisp_Object Qborder_color
;
237 Lisp_Object Qborder_width
;
239 Lisp_Object Qcursor_color
;
240 Lisp_Object Qcursor_type
;
241 Lisp_Object Qgeometry
;
242 Lisp_Object Qicon_left
;
243 Lisp_Object Qicon_top
;
244 Lisp_Object Qicon_type
;
245 Lisp_Object Qicon_name
;
246 Lisp_Object Qinternal_border_width
;
249 Lisp_Object Qmouse_color
;
251 Lisp_Object Qparent_id
;
252 Lisp_Object Qscroll_bar_width
;
253 Lisp_Object Qsuppress_icon
;
254 Lisp_Object Qundefined_color
;
255 Lisp_Object Qvertical_scroll_bars
;
256 Lisp_Object Qvisibility
;
257 Lisp_Object Qwindow_id
;
258 Lisp_Object Qx_frame_parameter
;
259 Lisp_Object Qx_resource_name
;
260 Lisp_Object Quser_position
;
261 Lisp_Object Quser_size
;
262 Lisp_Object Qscreen_gamma
;
263 Lisp_Object Qline_spacing
;
270 Lisp_Object Qcontrol
;
273 Lisp_Object Qw32_charset_ansi
;
274 Lisp_Object Qw32_charset_default
;
275 Lisp_Object Qw32_charset_symbol
;
276 Lisp_Object Qw32_charset_shiftjis
;
277 Lisp_Object Qw32_charset_hangul
;
278 Lisp_Object Qw32_charset_gb2312
;
279 Lisp_Object Qw32_charset_chinesebig5
;
280 Lisp_Object Qw32_charset_oem
;
283 Lisp_Object Qw32_charset_easteurope
;
284 Lisp_Object Qw32_charset_turkish
;
285 Lisp_Object Qw32_charset_baltic
;
286 Lisp_Object Qw32_charset_russian
;
287 Lisp_Object Qw32_charset_arabic
;
288 Lisp_Object Qw32_charset_greek
;
289 Lisp_Object Qw32_charset_hebrew
;
290 Lisp_Object Qw32_charset_thai
;
291 Lisp_Object Qw32_charset_johab
;
292 Lisp_Object Qw32_charset_mac
;
295 #ifdef UNICODE_CHARSET
296 Lisp_Object Qw32_charset_unicode
;
299 extern Lisp_Object Qtop
;
300 extern Lisp_Object Qdisplay
;
301 extern Lisp_Object Qtool_bar_lines
;
303 /* State variables for emulating a three button mouse. */
308 static int button_state
= 0;
309 static W32Msg saved_mouse_button_msg
;
310 static unsigned mouse_button_timer
; /* non-zero when timer is active */
311 static W32Msg saved_mouse_move_msg
;
312 static unsigned mouse_move_timer
;
314 /* W95 mousewheel handler */
315 unsigned int msh_mousewheel
= 0;
317 #define MOUSE_BUTTON_ID 1
318 #define MOUSE_MOVE_ID 2
320 /* The below are defined in frame.c. */
322 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
323 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
324 extern Lisp_Object Qtool_bar_lines
;
326 extern Lisp_Object Vwindow_system_version
;
328 Lisp_Object Qface_set_after_frame_default
;
330 /* From w32term.c. */
331 extern Lisp_Object Vw32_num_mouse_buttons
;
332 extern Lisp_Object Vw32_recognize_altgr
;
335 /* Error if we are not connected to MS-Windows. */
340 error ("MS-Windows not in use or not initialized");
343 /* Nonzero if we can use mouse menus.
344 You should not call this unless HAVE_MENUS is defined. */
352 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
353 and checking validity for W32. */
356 check_x_frame (frame
)
362 frame
= selected_frame
;
363 CHECK_LIVE_FRAME (frame
, 0);
365 if (! FRAME_W32_P (f
))
366 error ("non-w32 frame used");
370 /* Let the user specify an display with a frame.
371 nil stands for the selected frame--or, if that is not a w32 frame,
372 the first display on the list. */
374 static struct w32_display_info
*
375 check_x_display_info (frame
)
380 struct frame
*sf
= XFRAME (selected_frame
);
382 if (FRAME_W32_P (sf
) && FRAME_LIVE_P (sf
))
383 return FRAME_W32_DISPLAY_INFO (sf
);
385 return &one_w32_display_info
;
387 else if (STRINGP (frame
))
388 return x_display_info_for_name (frame
);
393 CHECK_LIVE_FRAME (frame
, 0);
395 if (! FRAME_W32_P (f
))
396 error ("non-w32 frame used");
397 return FRAME_W32_DISPLAY_INFO (f
);
401 /* Return the Emacs frame-object corresponding to an w32 window.
402 It could be the frame's main window or an icon window. */
404 /* This function can be called during GC, so use GC_xxx type test macros. */
407 x_window_to_frame (dpyinfo
, wdesc
)
408 struct w32_display_info
*dpyinfo
;
411 Lisp_Object tail
, frame
;
414 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
417 if (!GC_FRAMEP (frame
))
420 if (!FRAME_W32_P (f
) || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
422 if (f
->output_data
.w32
->busy_window
== wdesc
)
425 /* NTEMACS_TODO: Check tooltips when supported. */
426 if (FRAME_W32_WINDOW (f
) == wdesc
)
434 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
435 id, which is just an int that this section returns. Bitmaps are
436 reference counted so they can be shared among frames.
438 Bitmap indices are guaranteed to be > 0, so a negative number can
439 be used to indicate no bitmap.
441 If you use x_create_bitmap_from_data, then you must keep track of
442 the bitmaps yourself. That is, creating a bitmap from the same
443 data more than once will not be caught. */
446 /* Functions to access the contents of a bitmap, given an id. */
449 x_bitmap_height (f
, id
)
453 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
457 x_bitmap_width (f
, id
)
461 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
465 x_bitmap_pixmap (f
, id
)
469 return (int) FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
473 /* Allocate a new bitmap record. Returns index of new record. */
476 x_allocate_bitmap_record (f
)
479 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
482 if (dpyinfo
->bitmaps
== NULL
)
484 dpyinfo
->bitmaps_size
= 10;
486 = (struct w32_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
487 dpyinfo
->bitmaps_last
= 1;
491 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
492 return ++dpyinfo
->bitmaps_last
;
494 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
495 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
498 dpyinfo
->bitmaps_size
*= 2;
500 = (struct w32_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
501 dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
502 return ++dpyinfo
->bitmaps_last
;
505 /* Add one reference to the reference count of the bitmap with id ID. */
508 x_reference_bitmap (f
, id
)
512 ++FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
515 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
518 x_create_bitmap_from_data (f
, bits
, width
, height
)
521 unsigned int width
, height
;
523 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
527 bitmap
= CreateBitmap (width
, height
,
528 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
529 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
535 id
= x_allocate_bitmap_record (f
);
536 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
537 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
538 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
539 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
540 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
541 dpyinfo
->bitmaps
[id
- 1].height
= height
;
542 dpyinfo
->bitmaps
[id
- 1].width
= width
;
547 /* Create bitmap from file FILE for frame F. */
550 x_create_bitmap_from_file (f
, file
)
555 #if 0 /* NTEMACS_TODO : bitmap support */
556 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
557 unsigned int width
, height
;
559 int xhot
, yhot
, result
, id
;
565 /* Look for an existing bitmap with the same name. */
566 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
568 if (dpyinfo
->bitmaps
[id
].refcount
569 && dpyinfo
->bitmaps
[id
].file
570 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
572 ++dpyinfo
->bitmaps
[id
].refcount
;
577 /* Search bitmap-file-path for the file, if appropriate. */
578 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
581 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
586 filename
= (char *) XSTRING (found
)->data
;
588 hinst
= LoadLibraryEx (filename
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
594 result
= XReadBitmapFile (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
595 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
596 if (result
!= BitmapSuccess
)
599 id
= x_allocate_bitmap_record (f
);
600 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
601 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
602 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (XSTRING (file
)->size
+ 1);
603 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
604 dpyinfo
->bitmaps
[id
- 1].height
= height
;
605 dpyinfo
->bitmaps
[id
- 1].width
= width
;
606 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
609 #endif /* NTEMACS_TODO */
612 /* Remove reference to bitmap with id number ID. */
615 x_destroy_bitmap (f
, id
)
619 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
623 --dpyinfo
->bitmaps
[id
- 1].refcount
;
624 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
627 DeleteObject (dpyinfo
->bitmaps
[id
- 1].pixmap
);
628 if (dpyinfo
->bitmaps
[id
- 1].file
)
630 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
631 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
638 /* Free all the bitmaps for the display specified by DPYINFO. */
641 x_destroy_all_bitmaps (dpyinfo
)
642 struct w32_display_info
*dpyinfo
;
645 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
646 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
648 DeleteObject (dpyinfo
->bitmaps
[i
].pixmap
);
649 if (dpyinfo
->bitmaps
[i
].file
)
650 xfree (dpyinfo
->bitmaps
[i
].file
);
652 dpyinfo
->bitmaps_last
= 0;
655 /* Connect the frame-parameter names for W32 frames
656 to the ways of passing the parameter values to the window system.
658 The name of a parameter, as a Lisp symbol,
659 has an `x-frame-parameter' property which is an integer in Lisp
660 but can be interpreted as an `enum x_frame_parm' in C. */
664 X_PARM_FOREGROUND_COLOR
,
665 X_PARM_BACKGROUND_COLOR
,
672 X_PARM_INTERNAL_BORDER_WIDTH
,
676 X_PARM_VERT_SCROLL_BAR
,
678 X_PARM_MENU_BAR_LINES
682 struct x_frame_parm_table
685 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
688 /* NTEMACS_TODO: Native Input Method support; see x_create_im. */
689 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
690 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
691 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
692 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
693 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
694 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
695 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
696 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
697 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
698 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
699 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
700 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
702 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
703 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
704 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
705 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
707 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
708 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
709 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
710 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
711 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
712 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
713 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
715 static struct x_frame_parm_table x_frame_parms
[] =
717 "auto-raise", x_set_autoraise
,
718 "auto-lower", x_set_autolower
,
719 "background-color", x_set_background_color
,
720 "border-color", x_set_border_color
,
721 "border-width", x_set_border_width
,
722 "cursor-color", x_set_cursor_color
,
723 "cursor-type", x_set_cursor_type
,
725 "foreground-color", x_set_foreground_color
,
726 "icon-name", x_set_icon_name
,
727 "icon-type", x_set_icon_type
,
728 "internal-border-width", x_set_internal_border_width
,
729 "menu-bar-lines", x_set_menu_bar_lines
,
730 "mouse-color", x_set_mouse_color
,
731 "name", x_explicitly_set_name
,
732 "scroll-bar-width", x_set_scroll_bar_width
,
733 "title", x_set_title
,
734 "unsplittable", x_set_unsplittable
,
735 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
736 "visibility", x_set_visibility
,
737 "tool-bar-lines", x_set_tool_bar_lines
,
738 "screen-gamma", x_set_screen_gamma
,
739 "line-spacing", x_set_line_spacing
742 /* Attach the `x-frame-parameter' properties to
743 the Lisp symbol names of parameters relevant to W32. */
746 init_x_parm_symbols ()
750 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
751 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
755 /* Change the parameters of frame F as specified by ALIST.
756 If a parameter is not specially recognized, do nothing;
757 otherwise call the `x_set_...' function for that parameter. */
760 x_set_frame_parameters (f
, alist
)
766 /* If both of these parameters are present, it's more efficient to
767 set them both at once. So we wait until we've looked at the
768 entire list before we set them. */
772 Lisp_Object left
, top
;
774 /* Same with these. */
775 Lisp_Object icon_left
, icon_top
;
777 /* Record in these vectors all the parms specified. */
781 int left_no_change
= 0, top_no_change
= 0;
782 int icon_left_no_change
= 0, icon_top_no_change
= 0;
784 struct gcpro gcpro1
, gcpro2
;
787 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
790 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
791 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
793 /* Extract parm names and values into those vectors. */
796 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
801 parms
[i
] = Fcar (elt
);
802 values
[i
] = Fcdr (elt
);
805 /* TAIL and ALIST are not used again below here. */
808 GCPRO2 (*parms
, *values
);
812 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
813 because their values appear in VALUES and strings are not valid. */
814 top
= left
= Qunbound
;
815 icon_left
= icon_top
= Qunbound
;
817 /* Provide default values for HEIGHT and WIDTH. */
818 if (FRAME_NEW_WIDTH (f
))
819 width
= FRAME_NEW_WIDTH (f
);
821 width
= FRAME_WIDTH (f
);
823 if (FRAME_NEW_HEIGHT (f
))
824 height
= FRAME_NEW_HEIGHT (f
);
826 height
= FRAME_HEIGHT (f
);
828 /* Process foreground_color and background_color before anything else.
829 They are independent of other properties, but other properties (e.g.,
830 cursor_color) are dependent upon them. */
831 for (p
= 0; p
< i
; p
++)
833 Lisp_Object prop
, val
;
837 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
839 register Lisp_Object param_index
, old_value
;
841 param_index
= Fget (prop
, Qx_frame_parameter
);
842 old_value
= get_frame_param (f
, prop
);
843 store_frame_param (f
, prop
, val
);
844 if (NATNUMP (param_index
)
845 && (XFASTINT (param_index
)
846 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
847 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
851 /* Now process them in reverse of specified order. */
852 for (i
--; i
>= 0; i
--)
854 Lisp_Object prop
, val
;
859 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
860 width
= XFASTINT (val
);
861 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
862 height
= XFASTINT (val
);
863 else if (EQ (prop
, Qtop
))
865 else if (EQ (prop
, Qleft
))
867 else if (EQ (prop
, Qicon_top
))
869 else if (EQ (prop
, Qicon_left
))
871 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
872 /* Processed above. */
876 register Lisp_Object param_index
, old_value
;
878 param_index
= Fget (prop
, Qx_frame_parameter
);
879 old_value
= get_frame_param (f
, prop
);
880 store_frame_param (f
, prop
, val
);
881 if (NATNUMP (param_index
)
882 && (XFASTINT (param_index
)
883 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
884 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
888 /* Don't die if just one of these was set. */
889 if (EQ (left
, Qunbound
))
892 if (f
->output_data
.w32
->left_pos
< 0)
893 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->left_pos
), Qnil
));
895 XSETINT (left
, f
->output_data
.w32
->left_pos
);
897 if (EQ (top
, Qunbound
))
900 if (f
->output_data
.w32
->top_pos
< 0)
901 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->top_pos
), Qnil
));
903 XSETINT (top
, f
->output_data
.w32
->top_pos
);
906 /* If one of the icon positions was not set, preserve or default it. */
907 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
909 icon_left_no_change
= 1;
910 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
911 if (NILP (icon_left
))
912 XSETINT (icon_left
, 0);
914 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
916 icon_top_no_change
= 1;
917 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
919 XSETINT (icon_top
, 0);
922 /* Don't set these parameters unless they've been explicitly
923 specified. The window might be mapped or resized while we're in
924 this function, and we don't want to override that unless the lisp
925 code has asked for it.
927 Don't set these parameters unless they actually differ from the
928 window's current parameters; the window may not actually exist
933 check_frame_size (f
, &height
, &width
);
935 XSETFRAME (frame
, f
);
937 if (width
!= FRAME_WIDTH (f
)
938 || height
!= FRAME_HEIGHT (f
)
939 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
940 Fset_frame_size (frame
, make_number (width
), make_number (height
));
942 if ((!NILP (left
) || !NILP (top
))
943 && ! (left_no_change
&& top_no_change
)
944 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.w32
->left_pos
945 && NUMBERP (top
) && XINT (top
) == f
->output_data
.w32
->top_pos
))
950 /* Record the signs. */
951 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
952 if (EQ (left
, Qminus
))
953 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
954 else if (INTEGERP (left
))
956 leftpos
= XINT (left
);
958 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
960 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
961 && CONSP (XCDR (left
))
962 && INTEGERP (XCAR (XCDR (left
))))
964 leftpos
= - XINT (XCAR (XCDR (left
)));
965 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
967 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
968 && CONSP (XCDR (left
))
969 && INTEGERP (XCAR (XCDR (left
))))
971 leftpos
= XINT (XCAR (XCDR (left
)));
974 if (EQ (top
, Qminus
))
975 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
976 else if (INTEGERP (top
))
980 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
982 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
983 && CONSP (XCDR (top
))
984 && INTEGERP (XCAR (XCDR (top
))))
986 toppos
= - XINT (XCAR (XCDR (top
)));
987 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
989 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
990 && CONSP (XCDR (top
))
991 && INTEGERP (XCAR (XCDR (top
))))
993 toppos
= XINT (XCAR (XCDR (top
)));
997 /* Store the numeric value of the position. */
998 f
->output_data
.w32
->top_pos
= toppos
;
999 f
->output_data
.w32
->left_pos
= leftpos
;
1001 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
1003 /* Actually set that position, and convert to absolute. */
1004 x_set_offset (f
, leftpos
, toppos
, -1);
1007 if ((!NILP (icon_left
) || !NILP (icon_top
))
1008 && ! (icon_left_no_change
&& icon_top_no_change
))
1009 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1015 /* Store the screen positions of frame F into XPTR and YPTR.
1016 These are the positions of the containing window manager window,
1017 not Emacs's own window. */
1020 x_real_positions (f
, xptr
, yptr
)
1029 GetClientRect(FRAME_W32_WINDOW(f
), &rect
);
1030 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
, FRAME_EXTERNAL_MENU_BAR(f
));
1036 ClientToScreen (FRAME_W32_WINDOW(f
), &pt
);
1042 /* Insert a description of internally-recorded parameters of frame X
1043 into the parameter alist *ALISTPTR that is to be given to the user.
1044 Only parameters that are specific to W32
1045 and whose values are not correctly recorded in the frame's
1046 param_alist need to be considered here. */
1049 x_report_frame_params (f
, alistptr
)
1051 Lisp_Object
*alistptr
;
1056 /* Represent negative positions (off the top or left screen edge)
1057 in a way that Fmodify_frame_parameters will understand correctly. */
1058 XSETINT (tem
, f
->output_data
.w32
->left_pos
);
1059 if (f
->output_data
.w32
->left_pos
>= 0)
1060 store_in_alist (alistptr
, Qleft
, tem
);
1062 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1064 XSETINT (tem
, f
->output_data
.w32
->top_pos
);
1065 if (f
->output_data
.w32
->top_pos
>= 0)
1066 store_in_alist (alistptr
, Qtop
, tem
);
1068 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1070 store_in_alist (alistptr
, Qborder_width
,
1071 make_number (f
->output_data
.w32
->border_width
));
1072 store_in_alist (alistptr
, Qinternal_border_width
,
1073 make_number (f
->output_data
.w32
->internal_border_width
));
1074 sprintf (buf
, "%ld", (long) FRAME_W32_WINDOW (f
));
1075 store_in_alist (alistptr
, Qwindow_id
,
1076 build_string (buf
));
1077 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1078 FRAME_SAMPLE_VISIBILITY (f
);
1079 store_in_alist (alistptr
, Qvisibility
,
1080 (FRAME_VISIBLE_P (f
) ? Qt
1081 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1082 store_in_alist (alistptr
, Qdisplay
,
1083 XCAR (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
));
1087 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
, Sw32_define_rgb_color
, 4, 4, 0,
1088 "Convert RGB numbers to a windows color reference and associate with NAME (a string).\n\
1089 This adds or updates a named color to w32-color-map, making it available for use.\n\
1090 The original entry's RGB ref is returned, or nil if the entry is new.")
1091 (red
, green
, blue
, name
)
1092 Lisp_Object red
, green
, blue
, name
;
1095 Lisp_Object oldrgb
= Qnil
;
1098 CHECK_NUMBER (red
, 0);
1099 CHECK_NUMBER (green
, 0);
1100 CHECK_NUMBER (blue
, 0);
1101 CHECK_STRING (name
, 0);
1103 XSET (rgb
, Lisp_Int
, RGB(XUINT (red
), XUINT (green
), XUINT (blue
)));
1107 /* replace existing entry in w32-color-map or add new entry. */
1108 entry
= Fassoc (name
, Vw32_color_map
);
1111 entry
= Fcons (name
, rgb
);
1112 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
1116 oldrgb
= Fcdr (entry
);
1117 Fsetcdr (entry
, rgb
);
1125 DEFUN ("w32-load-color-file", Fw32_load_color_file
, Sw32_load_color_file
, 1, 1, 0,
1126 "Create an alist of color entries from an external file (ie. rgb.txt).\n\
1127 Assign this value to w32-color-map to replace the existing color map.\n\
1129 The file should define one named RGB color per line like so:\
1131 where R,G,B are numbers between 0 and 255 and name is an arbitrary string.")
1133 Lisp_Object filename
;
1136 Lisp_Object cmap
= Qnil
;
1137 Lisp_Object abspath
;
1139 CHECK_STRING (filename
, 0);
1140 abspath
= Fexpand_file_name (filename
, Qnil
);
1142 fp
= fopen (XSTRING (filename
)->data
, "rt");
1146 int red
, green
, blue
;
1151 while (fgets (buf
, sizeof (buf
), fp
) != NULL
) {
1152 if (sscanf (buf
, "%u %u %u %n", &red
, &green
, &blue
, &num
) == 3)
1154 char *name
= buf
+ num
;
1155 num
= strlen (name
) - 1;
1156 if (name
[num
] == '\n')
1158 cmap
= Fcons (Fcons (build_string (name
),
1159 make_number (RGB (red
, green
, blue
))),
1171 /* The default colors for the w32 color map */
1172 typedef struct colormap_t
1178 colormap_t w32_color_map
[] =
1180 {"snow" , PALETTERGB (255,250,250)},
1181 {"ghost white" , PALETTERGB (248,248,255)},
1182 {"GhostWhite" , PALETTERGB (248,248,255)},
1183 {"white smoke" , PALETTERGB (245,245,245)},
1184 {"WhiteSmoke" , PALETTERGB (245,245,245)},
1185 {"gainsboro" , PALETTERGB (220,220,220)},
1186 {"floral white" , PALETTERGB (255,250,240)},
1187 {"FloralWhite" , PALETTERGB (255,250,240)},
1188 {"old lace" , PALETTERGB (253,245,230)},
1189 {"OldLace" , PALETTERGB (253,245,230)},
1190 {"linen" , PALETTERGB (250,240,230)},
1191 {"antique white" , PALETTERGB (250,235,215)},
1192 {"AntiqueWhite" , PALETTERGB (250,235,215)},
1193 {"papaya whip" , PALETTERGB (255,239,213)},
1194 {"PapayaWhip" , PALETTERGB (255,239,213)},
1195 {"blanched almond" , PALETTERGB (255,235,205)},
1196 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
1197 {"bisque" , PALETTERGB (255,228,196)},
1198 {"peach puff" , PALETTERGB (255,218,185)},
1199 {"PeachPuff" , PALETTERGB (255,218,185)},
1200 {"navajo white" , PALETTERGB (255,222,173)},
1201 {"NavajoWhite" , PALETTERGB (255,222,173)},
1202 {"moccasin" , PALETTERGB (255,228,181)},
1203 {"cornsilk" , PALETTERGB (255,248,220)},
1204 {"ivory" , PALETTERGB (255,255,240)},
1205 {"lemon chiffon" , PALETTERGB (255,250,205)},
1206 {"LemonChiffon" , PALETTERGB (255,250,205)},
1207 {"seashell" , PALETTERGB (255,245,238)},
1208 {"honeydew" , PALETTERGB (240,255,240)},
1209 {"mint cream" , PALETTERGB (245,255,250)},
1210 {"MintCream" , PALETTERGB (245,255,250)},
1211 {"azure" , PALETTERGB (240,255,255)},
1212 {"alice blue" , PALETTERGB (240,248,255)},
1213 {"AliceBlue" , PALETTERGB (240,248,255)},
1214 {"lavender" , PALETTERGB (230,230,250)},
1215 {"lavender blush" , PALETTERGB (255,240,245)},
1216 {"LavenderBlush" , PALETTERGB (255,240,245)},
1217 {"misty rose" , PALETTERGB (255,228,225)},
1218 {"MistyRose" , PALETTERGB (255,228,225)},
1219 {"white" , PALETTERGB (255,255,255)},
1220 {"black" , PALETTERGB ( 0, 0, 0)},
1221 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1222 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1223 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1224 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1225 {"dim gray" , PALETTERGB (105,105,105)},
1226 {"DimGray" , PALETTERGB (105,105,105)},
1227 {"dim grey" , PALETTERGB (105,105,105)},
1228 {"DimGrey" , PALETTERGB (105,105,105)},
1229 {"slate gray" , PALETTERGB (112,128,144)},
1230 {"SlateGray" , PALETTERGB (112,128,144)},
1231 {"slate grey" , PALETTERGB (112,128,144)},
1232 {"SlateGrey" , PALETTERGB (112,128,144)},
1233 {"light slate gray" , PALETTERGB (119,136,153)},
1234 {"LightSlateGray" , PALETTERGB (119,136,153)},
1235 {"light slate grey" , PALETTERGB (119,136,153)},
1236 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1237 {"gray" , PALETTERGB (190,190,190)},
1238 {"grey" , PALETTERGB (190,190,190)},
1239 {"light grey" , PALETTERGB (211,211,211)},
1240 {"LightGrey" , PALETTERGB (211,211,211)},
1241 {"light gray" , PALETTERGB (211,211,211)},
1242 {"LightGray" , PALETTERGB (211,211,211)},
1243 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1244 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1245 {"navy" , PALETTERGB ( 0, 0,128)},
1246 {"navy blue" , PALETTERGB ( 0, 0,128)},
1247 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1248 {"cornflower blue" , PALETTERGB (100,149,237)},
1249 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1250 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1251 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1252 {"slate blue" , PALETTERGB (106, 90,205)},
1253 {"SlateBlue" , PALETTERGB (106, 90,205)},
1254 {"medium slate blue" , PALETTERGB (123,104,238)},
1255 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1256 {"light slate blue" , PALETTERGB (132,112,255)},
1257 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1258 {"medium blue" , PALETTERGB ( 0, 0,205)},
1259 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1260 {"royal blue" , PALETTERGB ( 65,105,225)},
1261 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1262 {"blue" , PALETTERGB ( 0, 0,255)},
1263 {"dodger blue" , PALETTERGB ( 30,144,255)},
1264 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1265 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1266 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1267 {"sky blue" , PALETTERGB (135,206,235)},
1268 {"SkyBlue" , PALETTERGB (135,206,235)},
1269 {"light sky blue" , PALETTERGB (135,206,250)},
1270 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1271 {"steel blue" , PALETTERGB ( 70,130,180)},
1272 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1273 {"light steel blue" , PALETTERGB (176,196,222)},
1274 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1275 {"light blue" , PALETTERGB (173,216,230)},
1276 {"LightBlue" , PALETTERGB (173,216,230)},
1277 {"powder blue" , PALETTERGB (176,224,230)},
1278 {"PowderBlue" , PALETTERGB (176,224,230)},
1279 {"pale turquoise" , PALETTERGB (175,238,238)},
1280 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1281 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1282 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1283 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1284 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1285 {"turquoise" , PALETTERGB ( 64,224,208)},
1286 {"cyan" , PALETTERGB ( 0,255,255)},
1287 {"light cyan" , PALETTERGB (224,255,255)},
1288 {"LightCyan" , PALETTERGB (224,255,255)},
1289 {"cadet blue" , PALETTERGB ( 95,158,160)},
1290 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1291 {"medium aquamarine" , PALETTERGB (102,205,170)},
1292 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1293 {"aquamarine" , PALETTERGB (127,255,212)},
1294 {"dark green" , PALETTERGB ( 0,100, 0)},
1295 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1296 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1297 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1298 {"dark sea green" , PALETTERGB (143,188,143)},
1299 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1300 {"sea green" , PALETTERGB ( 46,139, 87)},
1301 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1302 {"medium sea green" , PALETTERGB ( 60,179,113)},
1303 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1304 {"light sea green" , PALETTERGB ( 32,178,170)},
1305 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1306 {"pale green" , PALETTERGB (152,251,152)},
1307 {"PaleGreen" , PALETTERGB (152,251,152)},
1308 {"spring green" , PALETTERGB ( 0,255,127)},
1309 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1310 {"lawn green" , PALETTERGB (124,252, 0)},
1311 {"LawnGreen" , PALETTERGB (124,252, 0)},
1312 {"green" , PALETTERGB ( 0,255, 0)},
1313 {"chartreuse" , PALETTERGB (127,255, 0)},
1314 {"medium spring green" , PALETTERGB ( 0,250,154)},
1315 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1316 {"green yellow" , PALETTERGB (173,255, 47)},
1317 {"GreenYellow" , PALETTERGB (173,255, 47)},
1318 {"lime green" , PALETTERGB ( 50,205, 50)},
1319 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1320 {"yellow green" , PALETTERGB (154,205, 50)},
1321 {"YellowGreen" , PALETTERGB (154,205, 50)},
1322 {"forest green" , PALETTERGB ( 34,139, 34)},
1323 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1324 {"olive drab" , PALETTERGB (107,142, 35)},
1325 {"OliveDrab" , PALETTERGB (107,142, 35)},
1326 {"dark khaki" , PALETTERGB (189,183,107)},
1327 {"DarkKhaki" , PALETTERGB (189,183,107)},
1328 {"khaki" , PALETTERGB (240,230,140)},
1329 {"pale goldenrod" , PALETTERGB (238,232,170)},
1330 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1331 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1332 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1333 {"light yellow" , PALETTERGB (255,255,224)},
1334 {"LightYellow" , PALETTERGB (255,255,224)},
1335 {"yellow" , PALETTERGB (255,255, 0)},
1336 {"gold" , PALETTERGB (255,215, 0)},
1337 {"light goldenrod" , PALETTERGB (238,221,130)},
1338 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1339 {"goldenrod" , PALETTERGB (218,165, 32)},
1340 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1341 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1342 {"rosy brown" , PALETTERGB (188,143,143)},
1343 {"RosyBrown" , PALETTERGB (188,143,143)},
1344 {"indian red" , PALETTERGB (205, 92, 92)},
1345 {"IndianRed" , PALETTERGB (205, 92, 92)},
1346 {"saddle brown" , PALETTERGB (139, 69, 19)},
1347 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1348 {"sienna" , PALETTERGB (160, 82, 45)},
1349 {"peru" , PALETTERGB (205,133, 63)},
1350 {"burlywood" , PALETTERGB (222,184,135)},
1351 {"beige" , PALETTERGB (245,245,220)},
1352 {"wheat" , PALETTERGB (245,222,179)},
1353 {"sandy brown" , PALETTERGB (244,164, 96)},
1354 {"SandyBrown" , PALETTERGB (244,164, 96)},
1355 {"tan" , PALETTERGB (210,180,140)},
1356 {"chocolate" , PALETTERGB (210,105, 30)},
1357 {"firebrick" , PALETTERGB (178,34, 34)},
1358 {"brown" , PALETTERGB (165,42, 42)},
1359 {"dark salmon" , PALETTERGB (233,150,122)},
1360 {"DarkSalmon" , PALETTERGB (233,150,122)},
1361 {"salmon" , PALETTERGB (250,128,114)},
1362 {"light salmon" , PALETTERGB (255,160,122)},
1363 {"LightSalmon" , PALETTERGB (255,160,122)},
1364 {"orange" , PALETTERGB (255,165, 0)},
1365 {"dark orange" , PALETTERGB (255,140, 0)},
1366 {"DarkOrange" , PALETTERGB (255,140, 0)},
1367 {"coral" , PALETTERGB (255,127, 80)},
1368 {"light coral" , PALETTERGB (240,128,128)},
1369 {"LightCoral" , PALETTERGB (240,128,128)},
1370 {"tomato" , PALETTERGB (255, 99, 71)},
1371 {"orange red" , PALETTERGB (255, 69, 0)},
1372 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1373 {"red" , PALETTERGB (255, 0, 0)},
1374 {"hot pink" , PALETTERGB (255,105,180)},
1375 {"HotPink" , PALETTERGB (255,105,180)},
1376 {"deep pink" , PALETTERGB (255, 20,147)},
1377 {"DeepPink" , PALETTERGB (255, 20,147)},
1378 {"pink" , PALETTERGB (255,192,203)},
1379 {"light pink" , PALETTERGB (255,182,193)},
1380 {"LightPink" , PALETTERGB (255,182,193)},
1381 {"pale violet red" , PALETTERGB (219,112,147)},
1382 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1383 {"maroon" , PALETTERGB (176, 48, 96)},
1384 {"medium violet red" , PALETTERGB (199, 21,133)},
1385 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1386 {"violet red" , PALETTERGB (208, 32,144)},
1387 {"VioletRed" , PALETTERGB (208, 32,144)},
1388 {"magenta" , PALETTERGB (255, 0,255)},
1389 {"violet" , PALETTERGB (238,130,238)},
1390 {"plum" , PALETTERGB (221,160,221)},
1391 {"orchid" , PALETTERGB (218,112,214)},
1392 {"medium orchid" , PALETTERGB (186, 85,211)},
1393 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1394 {"dark orchid" , PALETTERGB (153, 50,204)},
1395 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1396 {"dark violet" , PALETTERGB (148, 0,211)},
1397 {"DarkViolet" , PALETTERGB (148, 0,211)},
1398 {"blue violet" , PALETTERGB (138, 43,226)},
1399 {"BlueViolet" , PALETTERGB (138, 43,226)},
1400 {"purple" , PALETTERGB (160, 32,240)},
1401 {"medium purple" , PALETTERGB (147,112,219)},
1402 {"MediumPurple" , PALETTERGB (147,112,219)},
1403 {"thistle" , PALETTERGB (216,191,216)},
1404 {"gray0" , PALETTERGB ( 0, 0, 0)},
1405 {"grey0" , PALETTERGB ( 0, 0, 0)},
1406 {"dark grey" , PALETTERGB (169,169,169)},
1407 {"DarkGrey" , PALETTERGB (169,169,169)},
1408 {"dark gray" , PALETTERGB (169,169,169)},
1409 {"DarkGray" , PALETTERGB (169,169,169)},
1410 {"dark blue" , PALETTERGB ( 0, 0,139)},
1411 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1412 {"dark cyan" , PALETTERGB ( 0,139,139)},
1413 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1414 {"dark magenta" , PALETTERGB (139, 0,139)},
1415 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1416 {"dark red" , PALETTERGB (139, 0, 0)},
1417 {"DarkRed" , PALETTERGB (139, 0, 0)},
1418 {"light green" , PALETTERGB (144,238,144)},
1419 {"LightGreen" , PALETTERGB (144,238,144)},
1422 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
1423 0, 0, 0, "Return the default color map.")
1427 colormap_t
*pc
= w32_color_map
;
1434 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
1436 cmap
= Fcons (Fcons (build_string (pc
->name
),
1437 make_number (pc
->colorref
)),
1446 w32_to_x_color (rgb
)
1451 CHECK_NUMBER (rgb
, 0);
1455 color
= Frassq (rgb
, Vw32_color_map
);
1460 return (Fcar (color
));
1466 w32_color_map_lookup (colorname
)
1469 Lisp_Object tail
, ret
= Qnil
;
1473 for (tail
= Vw32_color_map
; !NILP (tail
); tail
= Fcdr (tail
))
1475 register Lisp_Object elt
, tem
;
1478 if (!CONSP (elt
)) continue;
1482 if (lstrcmpi (XSTRING (tem
)->data
, colorname
) == 0)
1484 ret
= XUINT (Fcdr (elt
));
1498 x_to_w32_color (colorname
)
1501 register Lisp_Object tail
, ret
= Qnil
;
1505 if (colorname
[0] == '#')
1507 /* Could be an old-style RGB Device specification. */
1510 color
= colorname
+ 1;
1512 size
= strlen(color
);
1513 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
1521 for (i
= 0; i
< 3; i
++)
1525 unsigned long value
;
1527 /* The check for 'x' in the following conditional takes into
1528 account the fact that strtol allows a "0x" in front of
1529 our numbers, and we don't. */
1530 if (!isxdigit(color
[0]) || color
[1] == 'x')
1534 value
= strtoul(color
, &end
, 16);
1536 if (errno
== ERANGE
|| end
- color
!= size
)
1541 value
= value
* 0x10;
1552 colorval
|= (value
<< pos
);
1563 else if (strnicmp(colorname
, "rgb:", 4) == 0)
1571 color
= colorname
+ 4;
1572 for (i
= 0; i
< 3; i
++)
1575 unsigned long value
;
1577 /* The check for 'x' in the following conditional takes into
1578 account the fact that strtol allows a "0x" in front of
1579 our numbers, and we don't. */
1580 if (!isxdigit(color
[0]) || color
[1] == 'x')
1582 value
= strtoul(color
, &end
, 16);
1583 if (errno
== ERANGE
)
1585 switch (end
- color
)
1588 value
= value
* 0x10 + value
;
1601 if (value
== ULONG_MAX
)
1603 colorval
|= (value
<< pos
);
1617 else if (strnicmp(colorname
, "rgbi:", 5) == 0)
1619 /* This is an RGB Intensity specification. */
1626 color
= colorname
+ 5;
1627 for (i
= 0; i
< 3; i
++)
1633 value
= strtod(color
, &end
);
1634 if (errno
== ERANGE
)
1636 if (value
< 0.0 || value
> 1.0)
1638 val
= (UINT
)(0x100 * value
);
1639 /* We used 0x100 instead of 0xFF to give an continuous
1640 range between 0.0 and 1.0 inclusive. The next statement
1641 fixes the 1.0 case. */
1644 colorval
|= (val
<< pos
);
1658 /* I am not going to attempt to handle any of the CIE color schemes
1659 or TekHVC, since I don't know the algorithms for conversion to
1662 /* If we fail to lookup the color name in w32_color_map, then check the
1663 colorname to see if it can be crudely approximated: If the X color
1664 ends in a number (e.g., "darkseagreen2"), strip the number and
1665 return the result of looking up the base color name. */
1666 ret
= w32_color_map_lookup (colorname
);
1669 int len
= strlen (colorname
);
1671 if (isdigit (colorname
[len
- 1]))
1673 char *ptr
, *approx
= alloca (len
);
1675 strcpy (approx
, colorname
);
1676 ptr
= &approx
[len
- 1];
1677 while (ptr
> approx
&& isdigit (*ptr
))
1680 ret
= w32_color_map_lookup (approx
);
1690 w32_regenerate_palette (FRAME_PTR f
)
1692 struct w32_palette_entry
* list
;
1693 LOGPALETTE
* log_palette
;
1694 HPALETTE new_palette
;
1697 /* don't bother trying to create palette if not supported */
1698 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
1701 log_palette
= (LOGPALETTE
*)
1702 alloca (sizeof (LOGPALETTE
) +
1703 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1704 log_palette
->palVersion
= 0x300;
1705 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1707 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1709 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1710 i
++, list
= list
->next
)
1711 log_palette
->palPalEntry
[i
] = list
->entry
;
1713 new_palette
= CreatePalette (log_palette
);
1717 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1718 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1719 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1721 /* Realize display palette and garbage all frames. */
1722 release_frame_dc (f
, get_frame_dc (f
));
1727 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1728 #define SET_W32_COLOR(pe, color) \
1731 pe.peRed = GetRValue (color); \
1732 pe.peGreen = GetGValue (color); \
1733 pe.peBlue = GetBValue (color); \
1738 /* Keep these around in case we ever want to track color usage. */
1740 w32_map_color (FRAME_PTR f
, COLORREF color
)
1742 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1744 if (NILP (Vw32_enable_palette
))
1747 /* check if color is already mapped */
1750 if (W32_COLOR (list
->entry
) == color
)
1758 /* not already mapped, so add to list and recreate Windows palette */
1759 list
= (struct w32_palette_entry
*)
1760 xmalloc (sizeof (struct w32_palette_entry
));
1761 SET_W32_COLOR (list
->entry
, color
);
1763 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1764 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1765 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1767 /* set flag that palette must be regenerated */
1768 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1772 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1774 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1775 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1777 if (NILP (Vw32_enable_palette
))
1780 /* check if color is already mapped */
1783 if (W32_COLOR (list
->entry
) == color
)
1785 if (--list
->refcount
== 0)
1789 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1799 /* set flag that palette must be regenerated */
1800 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1805 /* Gamma-correct COLOR on frame F. */
1808 gamma_correct (f
, color
)
1814 *color
= PALETTERGB (
1815 pow (GetRValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1816 pow (GetGValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1817 pow (GetBValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5);
1822 /* Decide if color named COLOR is valid for the display associated with
1823 the selected frame; if so, return the rgb values in COLOR_DEF.
1824 If ALLOC is nonzero, allocate a new colormap cell. */
1827 w32_defined_color (f
, color
, color_def
, alloc
)
1833 register Lisp_Object tem
;
1834 COLORREF w32_color_ref
;
1836 tem
= x_to_w32_color (color
);
1842 /* Apply gamma correction. */
1843 w32_color_ref
= XUINT (tem
);
1844 gamma_correct (f
, &w32_color_ref
);
1845 XSETINT (tem
, w32_color_ref
);
1848 /* Map this color to the palette if it is enabled. */
1849 if (!NILP (Vw32_enable_palette
))
1851 struct w32_palette_entry
* entry
=
1852 one_w32_display_info
.color_list
;
1853 struct w32_palette_entry
** prev
=
1854 &one_w32_display_info
.color_list
;
1856 /* check if color is already mapped */
1859 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1861 prev
= &entry
->next
;
1862 entry
= entry
->next
;
1865 if (entry
== NULL
&& alloc
)
1867 /* not already mapped, so add to list */
1868 entry
= (struct w32_palette_entry
*)
1869 xmalloc (sizeof (struct w32_palette_entry
));
1870 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1873 one_w32_display_info
.num_colors
++;
1875 /* set flag that palette must be regenerated */
1876 one_w32_display_info
.regen_palette
= TRUE
;
1879 /* Ensure COLORREF value is snapped to nearest color in (default)
1880 palette by simulating the PALETTERGB macro. This works whether
1881 or not the display device has a palette. */
1882 w32_color_ref
= XUINT (tem
) | 0x2000000;
1884 color_def
->pixel
= w32_color_ref
;
1885 color_def
->red
= GetRValue (w32_color_ref
);
1886 color_def
->green
= GetGValue (w32_color_ref
);
1887 color_def
->blue
= GetBValue (w32_color_ref
);
1897 /* Given a string ARG naming a color, compute a pixel value from it
1898 suitable for screen F.
1899 If F is not a color screen, return DEF (default) regardless of what
1903 x_decode_color (f
, arg
, def
)
1910 CHECK_STRING (arg
, 0);
1912 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1913 return BLACK_PIX_DEFAULT (f
);
1914 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1915 return WHITE_PIX_DEFAULT (f
);
1917 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1920 /* w32_defined_color is responsible for coping with failures
1921 by looking for a near-miss. */
1922 if (w32_defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1925 /* defined_color failed; return an ultimate default. */
1929 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1930 the previous value of that parameter, NEW_VALUE is the new value. */
1933 x_set_line_spacing (f
, new_value
, old_value
)
1935 Lisp_Object new_value
, old_value
;
1937 if (NILP (new_value
))
1938 f
->extra_line_spacing
= 0;
1939 else if (NATNUMP (new_value
))
1940 f
->extra_line_spacing
= XFASTINT (new_value
);
1942 Fsignal (Qerror
, Fcons (build_string ("Illegal line-spacing"),
1943 Fcons (new_value
, Qnil
)));
1944 if (FRAME_VISIBLE_P (f
))
1949 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1950 the previous value of that parameter, NEW_VALUE is the new value. */
1953 x_set_screen_gamma (f
, new_value
, old_value
)
1955 Lisp_Object new_value
, old_value
;
1957 if (NILP (new_value
))
1959 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1960 /* The value 0.4545 is the normal viewing gamma. */
1961 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1963 Fsignal (Qerror
, Fcons (build_string ("Illegal screen-gamma"),
1964 Fcons (new_value
, Qnil
)));
1966 clear_face_cache (0);
1970 /* Functions called only from `x_set_frame_param'
1971 to set individual parameters.
1973 If FRAME_W32_WINDOW (f) is 0,
1974 the frame is being created and its window does not exist yet.
1975 In that case, just record the parameter's new value
1976 in the standard place; do not attempt to change the window. */
1979 x_set_foreground_color (f
, arg
, oldval
)
1981 Lisp_Object arg
, oldval
;
1983 FRAME_FOREGROUND_PIXEL (f
)
1984 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1986 if (FRAME_W32_WINDOW (f
) != 0)
1988 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1989 if (FRAME_VISIBLE_P (f
))
1995 x_set_background_color (f
, arg
, oldval
)
1997 Lisp_Object arg
, oldval
;
1999 FRAME_BACKGROUND_PIXEL (f
)
2000 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
2002 if (FRAME_W32_WINDOW (f
) != 0)
2004 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
,
2005 FRAME_BACKGROUND_PIXEL (f
));
2007 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
2009 if (FRAME_VISIBLE_P (f
))
2015 x_set_mouse_color (f
, arg
, oldval
)
2017 Lisp_Object arg
, oldval
;
2020 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
2024 if (!EQ (Qnil
, arg
))
2025 f
->output_data
.w32
->mouse_pixel
2026 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2027 mask_color
= FRAME_BACKGROUND_PIXEL (f
);
2029 /* Don't let pointers be invisible. */
2030 if (mask_color
== f
->output_data
.w32
->mouse_pixel
2031 && mask_color
== FRAME_BACKGROUND_PIXEL (f
))
2032 f
->output_data
.w32
->mouse_pixel
= FRAME_FOREGROUND_PIXEL (f
);
2034 #if 0 /* NTEMACS_TODO : cursor changes */
2037 /* It's not okay to crash if the user selects a screwy cursor. */
2038 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
2040 if (!EQ (Qnil
, Vx_pointer_shape
))
2042 CHECK_NUMBER (Vx_pointer_shape
, 0);
2043 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
2046 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
2047 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
2049 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
2051 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
2052 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2053 XINT (Vx_nontext_pointer_shape
));
2056 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
2057 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
2059 if (!EQ (Qnil
, Vx_busy_pointer_shape
))
2061 CHECK_NUMBER (Vx_busy_pointer_shape
, 0);
2062 busy_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2063 XINT (Vx_busy_pointer_shape
));
2066 busy_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_watch
);
2067 x_check_errors (FRAME_W32_DISPLAY (f
), "bad busy pointer cursor: %s");
2069 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
2070 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
2072 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
2073 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2074 XINT (Vx_mode_pointer_shape
));
2077 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
2078 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
2080 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
2082 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
2084 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2085 XINT (Vx_sensitive_text_pointer_shape
));
2088 cross_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
2090 /* Check and report errors with the above calls. */
2091 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
2092 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
2095 XColor fore_color
, back_color
;
2097 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
2098 back_color
.pixel
= mask_color
;
2099 XQueryColor (FRAME_W32_DISPLAY (f
),
2100 DefaultColormap (FRAME_W32_DISPLAY (f
),
2101 DefaultScreen (FRAME_W32_DISPLAY (f
))),
2103 XQueryColor (FRAME_W32_DISPLAY (f
),
2104 DefaultColormap (FRAME_W32_DISPLAY (f
),
2105 DefaultScreen (FRAME_W32_DISPLAY (f
))),
2107 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
2108 &fore_color
, &back_color
);
2109 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
2110 &fore_color
, &back_color
);
2111 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
2112 &fore_color
, &back_color
);
2113 XRecolorCursor (FRAME_W32_DISPLAY (f
), cross_cursor
,
2114 &fore_color
, &back_color
);
2115 XRecolorCursor (FRAME_W32_DISPLAY (f
), busy_cursor
,
2116 &fore_color
, &back_color
);
2119 if (FRAME_W32_WINDOW (f
) != 0)
2120 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
2122 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
2123 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
2124 f
->output_data
.w32
->text_cursor
= cursor
;
2126 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
2127 && f
->output_data
.w32
->nontext_cursor
!= 0)
2128 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
2129 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
2131 if (busy_cursor
!= f
->output_data
.w32
->busy_cursor
2132 && f
->output_data
.w32
->busy_cursor
!= 0)
2133 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->busy_cursor
);
2134 f
->output_data
.w32
->busy_cursor
= busy_cursor
;
2136 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
2137 && f
->output_data
.w32
->modeline_cursor
!= 0)
2138 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
2139 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
2141 if (cross_cursor
!= f
->output_data
.w32
->cross_cursor
2142 && f
->output_data
.w32
->cross_cursor
!= 0)
2143 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->cross_cursor
);
2144 f
->output_data
.w32
->cross_cursor
= cross_cursor
;
2146 XFlush (FRAME_W32_DISPLAY (f
));
2149 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
2150 #endif /* NTEMACS_TODO */
2154 x_set_cursor_color (f
, arg
, oldval
)
2156 Lisp_Object arg
, oldval
;
2158 unsigned long fore_pixel
;
2160 if (!NILP (Vx_cursor_fore_pixel
))
2161 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
2162 WHITE_PIX_DEFAULT (f
));
2164 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
2165 f
->output_data
.w32
->cursor_pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2167 /* Make sure that the cursor color differs from the background color. */
2168 if (f
->output_data
.w32
->cursor_pixel
== FRAME_BACKGROUND_PIXEL (f
))
2170 f
->output_data
.w32
->cursor_pixel
= f
->output_data
.w32
->mouse_pixel
;
2171 if (f
->output_data
.w32
->cursor_pixel
== fore_pixel
)
2172 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
2174 FRAME_FOREGROUND_PIXEL (f
) = fore_pixel
;
2176 if (FRAME_W32_WINDOW (f
) != 0)
2178 if (FRAME_VISIBLE_P (f
))
2180 x_display_cursor (f
, 0);
2181 x_display_cursor (f
, 1);
2185 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
2188 /* Set the border-color of frame F to pixel value PIX.
2189 Note that this does not fully take effect if done before
2192 x_set_border_pixel (f
, pix
)
2196 f
->output_data
.w32
->border_pixel
= pix
;
2198 if (FRAME_W32_WINDOW (f
) != 0 && f
->output_data
.w32
->border_width
> 0)
2200 if (FRAME_VISIBLE_P (f
))
2205 /* Set the border-color of frame F to value described by ARG.
2206 ARG can be a string naming a color.
2207 The border-color is used for the border that is drawn by the server.
2208 Note that this does not fully take effect if done before
2209 F has a window; it must be redone when the window is created. */
2212 x_set_border_color (f
, arg
, oldval
)
2214 Lisp_Object arg
, oldval
;
2218 CHECK_STRING (arg
, 0);
2219 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2220 x_set_border_pixel (f
, pix
);
2221 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
2224 /* Value is the internal representation of the specified cursor type
2225 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
2226 of the bar cursor. */
2228 enum text_cursor_kinds
2229 x_specified_cursor_type (arg
, width
)
2233 enum text_cursor_kinds type
;
2240 else if (CONSP (arg
)
2241 && EQ (XCAR (arg
), Qbar
)
2242 && INTEGERP (XCDR (arg
))
2243 && XINT (XCDR (arg
)) >= 0)
2246 *width
= XINT (XCDR (arg
));
2248 else if (NILP (arg
))
2251 /* Treat anything unknown as "box cursor".
2252 It was bad to signal an error; people have trouble fixing
2253 .Xdefaults with Emacs, when it has something bad in it. */
2254 type
= FILLED_BOX_CURSOR
;
2260 x_set_cursor_type (f
, arg
, oldval
)
2262 Lisp_Object arg
, oldval
;
2266 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
2267 f
->output_data
.w32
->cursor_width
= width
;
2269 /* Make sure the cursor gets redrawn. This is overkill, but how
2270 often do people change cursor types? */
2271 update_mode_lines
++;
2275 x_set_icon_type (f
, arg
, oldval
)
2277 Lisp_Object arg
, oldval
;
2281 if (NILP (arg
) && NILP (oldval
))
2284 if (STRINGP (arg
) && STRINGP (oldval
)
2285 && EQ (Fstring_equal (oldval
, arg
), Qt
))
2288 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
2293 result
= x_bitmap_icon (f
, arg
);
2297 error ("No icon window available");
2303 /* Return non-nil if frame F wants a bitmap icon. */
2311 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
2319 x_set_icon_name (f
, arg
, oldval
)
2321 Lisp_Object arg
, oldval
;
2327 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
2330 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
2336 if (f
->output_data
.w32
->icon_bitmap
!= 0)
2341 result
= x_text_icon (f
,
2342 (char *) XSTRING ((!NILP (f
->icon_name
)
2351 error ("No icon window available");
2354 /* If the window was unmapped (and its icon was mapped),
2355 the new icon is not mapped, so map the window in its stead. */
2356 if (FRAME_VISIBLE_P (f
))
2358 #ifdef USE_X_TOOLKIT
2359 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
2361 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
2364 XFlush (FRAME_W32_DISPLAY (f
));
2369 extern Lisp_Object
x_new_font ();
2370 extern Lisp_Object
x_new_fontset();
2373 x_set_font (f
, arg
, oldval
)
2375 Lisp_Object arg
, oldval
;
2378 Lisp_Object fontset_name
;
2381 CHECK_STRING (arg
, 1);
2383 fontset_name
= Fquery_fontset (arg
, Qnil
);
2386 result
= (STRINGP (fontset_name
)
2387 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
2388 : x_new_font (f
, XSTRING (arg
)->data
));
2391 if (EQ (result
, Qnil
))
2392 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
2393 else if (EQ (result
, Qt
))
2394 error ("The characters of the given font have varying widths");
2395 else if (STRINGP (result
))
2397 store_frame_param (f
, Qfont
, result
);
2398 recompute_basic_faces (f
);
2403 do_pending_window_change (0);
2405 /* Don't call `face-set-after-frame-default' when faces haven't been
2406 initialized yet. This is the case when called from
2407 Fx_create_frame. In that case, the X widget or window doesn't
2408 exist either, and we can end up in x_report_frame_params with a
2409 null widget which gives a segfault. */
2410 if (FRAME_FACE_CACHE (f
))
2412 XSETFRAME (frame
, f
);
2413 call1 (Qface_set_after_frame_default
, frame
);
2418 x_set_border_width (f
, arg
, oldval
)
2420 Lisp_Object arg
, oldval
;
2422 CHECK_NUMBER (arg
, 0);
2424 if (XINT (arg
) == f
->output_data
.w32
->border_width
)
2427 if (FRAME_W32_WINDOW (f
) != 0)
2428 error ("Cannot change the border width of a window");
2430 f
->output_data
.w32
->border_width
= XINT (arg
);
2434 x_set_internal_border_width (f
, arg
, oldval
)
2436 Lisp_Object arg
, oldval
;
2438 int old
= f
->output_data
.w32
->internal_border_width
;
2440 CHECK_NUMBER (arg
, 0);
2441 f
->output_data
.w32
->internal_border_width
= XINT (arg
);
2442 if (f
->output_data
.w32
->internal_border_width
< 0)
2443 f
->output_data
.w32
->internal_border_width
= 0;
2445 if (f
->output_data
.w32
->internal_border_width
== old
)
2448 if (FRAME_W32_WINDOW (f
) != 0)
2450 x_set_window_size (f
, 0, f
->width
, f
->height
);
2451 SET_FRAME_GARBAGED (f
);
2452 do_pending_window_change (0);
2457 x_set_visibility (f
, value
, oldval
)
2459 Lisp_Object value
, oldval
;
2462 XSETFRAME (frame
, f
);
2465 Fmake_frame_invisible (frame
, Qt
);
2466 else if (EQ (value
, Qicon
))
2467 Ficonify_frame (frame
);
2469 Fmake_frame_visible (frame
);
2473 x_set_menu_bar_lines (f
, value
, oldval
)
2475 Lisp_Object value
, oldval
;
2478 int olines
= FRAME_MENU_BAR_LINES (f
);
2480 /* Right now, menu bars don't work properly in minibuf-only frames;
2481 most of the commands try to apply themselves to the minibuffer
2482 frame itself, and get an error because you can't switch buffers
2483 in or split the minibuffer window. */
2484 if (FRAME_MINIBUF_ONLY_P (f
))
2487 if (INTEGERP (value
))
2488 nlines
= XINT (value
);
2492 FRAME_MENU_BAR_LINES (f
) = 0;
2494 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2497 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2498 free_frame_menubar (f
);
2499 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2501 /* Adjust the frame size so that the client (text) dimensions
2502 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2504 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2505 do_pending_window_change (0);
2511 /* Set the number of lines used for the tool bar of frame F to VALUE.
2512 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2513 is the old number of tool bar lines. This function changes the
2514 height of all windows on frame F to match the new tool bar height.
2515 The frame's height doesn't change. */
2518 x_set_tool_bar_lines (f
, value
, oldval
)
2520 Lisp_Object value
, oldval
;
2524 /* Use VALUE only if an integer >= 0. */
2525 if (INTEGERP (value
) && XINT (value
) >= 0)
2526 nlines
= XFASTINT (value
);
2530 /* Make sure we redisplay all windows in this frame. */
2531 ++windows_or_buffers_changed
;
2533 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2534 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2535 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2536 do_pending_window_change (0);
2541 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2544 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2545 name; if NAME is a string, set F's name to NAME and set
2546 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2548 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2549 suggesting a new name, which lisp code should override; if
2550 F->explicit_name is set, ignore the new name; otherwise, set it. */
2553 x_set_name (f
, name
, explicit)
2558 /* Make sure that requests from lisp code override requests from
2559 Emacs redisplay code. */
2562 /* If we're switching from explicit to implicit, we had better
2563 update the mode lines and thereby update the title. */
2564 if (f
->explicit_name
&& NILP (name
))
2565 update_mode_lines
= 1;
2567 f
->explicit_name
= ! NILP (name
);
2569 else if (f
->explicit_name
)
2572 /* If NAME is nil, set the name to the w32_id_name. */
2575 /* Check for no change needed in this very common case
2576 before we do any consing. */
2577 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
2578 XSTRING (f
->name
)->data
))
2580 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
2583 CHECK_STRING (name
, 0);
2585 /* Don't change the name if it's already NAME. */
2586 if (! NILP (Fstring_equal (name
, f
->name
)))
2591 /* For setting the frame title, the title parameter should override
2592 the name parameter. */
2593 if (! NILP (f
->title
))
2596 if (FRAME_W32_WINDOW (f
))
2598 if (STRING_MULTIBYTE (name
))
2599 name
= ENCODE_SYSTEM (name
);
2602 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2607 /* This function should be called when the user's lisp code has
2608 specified a name for the frame; the name will override any set by the
2611 x_explicitly_set_name (f
, arg
, oldval
)
2613 Lisp_Object arg
, oldval
;
2615 x_set_name (f
, arg
, 1);
2618 /* This function should be called by Emacs redisplay code to set the
2619 name; names set this way will never override names set by the user's
2622 x_implicitly_set_name (f
, arg
, oldval
)
2624 Lisp_Object arg
, oldval
;
2626 x_set_name (f
, arg
, 0);
2629 /* Change the title of frame F to NAME.
2630 If NAME is nil, use the frame name as the title.
2632 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2633 name; if NAME is a string, set F's name to NAME and set
2634 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2636 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2637 suggesting a new name, which lisp code should override; if
2638 F->explicit_name is set, ignore the new name; otherwise, set it. */
2641 x_set_title (f
, name
, old_name
)
2643 Lisp_Object name
, old_name
;
2645 /* Don't change the title if it's already NAME. */
2646 if (EQ (name
, f
->title
))
2649 update_mode_lines
= 1;
2656 if (FRAME_W32_WINDOW (f
))
2658 if (STRING_MULTIBYTE (name
))
2659 name
= ENCODE_SYSTEM (name
);
2662 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2668 x_set_autoraise (f
, arg
, oldval
)
2670 Lisp_Object arg
, oldval
;
2672 f
->auto_raise
= !EQ (Qnil
, arg
);
2676 x_set_autolower (f
, arg
, oldval
)
2678 Lisp_Object arg
, oldval
;
2680 f
->auto_lower
= !EQ (Qnil
, arg
);
2684 x_set_unsplittable (f
, arg
, oldval
)
2686 Lisp_Object arg
, oldval
;
2688 f
->no_split
= !NILP (arg
);
2692 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2694 Lisp_Object arg
, oldval
;
2696 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2697 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2698 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2699 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2701 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = NILP (arg
) ?
2702 vertical_scroll_bar_none
:
2703 /* Put scroll bars on the right by default, as is conventional
2706 ? vertical_scroll_bar_left
2707 : vertical_scroll_bar_right
;
2709 /* We set this parameter before creating the window for the
2710 frame, so we can get the geometry right from the start.
2711 However, if the window hasn't been created yet, we shouldn't
2712 call x_set_window_size. */
2713 if (FRAME_W32_WINDOW (f
))
2714 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2715 do_pending_window_change (0);
2720 x_set_scroll_bar_width (f
, arg
, oldval
)
2722 Lisp_Object arg
, oldval
;
2724 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
2728 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
2729 FRAME_SCROLL_BAR_COLS (f
) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) +
2731 if (FRAME_W32_WINDOW (f
))
2732 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2733 do_pending_window_change (0);
2735 else if (INTEGERP (arg
) && XINT (arg
) > 0
2736 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2738 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2739 FRAME_SCROLL_BAR_COLS (f
) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2741 if (FRAME_W32_WINDOW (f
))
2742 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2743 do_pending_window_change (0);
2745 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2746 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2747 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2750 /* Subroutines of creating an frame. */
2752 /* Make sure that Vx_resource_name is set to a reasonable value.
2753 Fix it up, or set it to `emacs' if it is too hopeless. */
2756 validate_x_resource_name ()
2759 /* Number of valid characters in the resource name. */
2761 /* Number of invalid characters in the resource name. */
2766 if (STRINGP (Vx_resource_name
))
2768 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2771 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2773 /* Only letters, digits, - and _ are valid in resource names.
2774 Count the valid characters and count the invalid ones. */
2775 for (i
= 0; i
< len
; i
++)
2778 if (! ((c
>= 'a' && c
<= 'z')
2779 || (c
>= 'A' && c
<= 'Z')
2780 || (c
>= '0' && c
<= '9')
2781 || c
== '-' || c
== '_'))
2788 /* Not a string => completely invalid. */
2789 bad_count
= 5, good_count
= 0;
2791 /* If name is valid already, return. */
2795 /* If name is entirely invalid, or nearly so, use `emacs'. */
2797 || (good_count
== 1 && bad_count
> 0))
2799 Vx_resource_name
= build_string ("emacs");
2803 /* Name is partly valid. Copy it and replace the invalid characters
2804 with underscores. */
2806 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2808 for (i
= 0; i
< len
; i
++)
2810 int c
= XSTRING (new)->data
[i
];
2811 if (! ((c
>= 'a' && c
<= 'z')
2812 || (c
>= 'A' && c
<= 'Z')
2813 || (c
>= '0' && c
<= '9')
2814 || c
== '-' || c
== '_'))
2815 XSTRING (new)->data
[i
] = '_';
2820 extern char *x_get_string_resource ();
2822 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2823 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2824 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2825 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2826 the name specified by the `-name' or `-rn' command-line arguments.\n\
2828 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2829 class, respectively. You must specify both of them or neither.\n\
2830 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2831 and the class is `Emacs.CLASS.SUBCLASS'.")
2832 (attribute
, class, component
, subclass
)
2833 Lisp_Object attribute
, class, component
, subclass
;
2835 register char *value
;
2839 CHECK_STRING (attribute
, 0);
2840 CHECK_STRING (class, 0);
2842 if (!NILP (component
))
2843 CHECK_STRING (component
, 1);
2844 if (!NILP (subclass
))
2845 CHECK_STRING (subclass
, 2);
2846 if (NILP (component
) != NILP (subclass
))
2847 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2849 validate_x_resource_name ();
2851 /* Allocate space for the components, the dots which separate them,
2852 and the final '\0'. Make them big enough for the worst case. */
2853 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2854 + (STRINGP (component
)
2855 ? STRING_BYTES (XSTRING (component
)) : 0)
2856 + STRING_BYTES (XSTRING (attribute
))
2859 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2860 + STRING_BYTES (XSTRING (class))
2861 + (STRINGP (subclass
)
2862 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2865 /* Start with emacs.FRAMENAME for the name (the specific one)
2866 and with `Emacs' for the class key (the general one). */
2867 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2868 strcpy (class_key
, EMACS_CLASS
);
2870 strcat (class_key
, ".");
2871 strcat (class_key
, XSTRING (class)->data
);
2873 if (!NILP (component
))
2875 strcat (class_key
, ".");
2876 strcat (class_key
, XSTRING (subclass
)->data
);
2878 strcat (name_key
, ".");
2879 strcat (name_key
, XSTRING (component
)->data
);
2882 strcat (name_key
, ".");
2883 strcat (name_key
, XSTRING (attribute
)->data
);
2885 value
= x_get_string_resource (Qnil
,
2886 name_key
, class_key
);
2888 if (value
!= (char *) 0)
2889 return build_string (value
);
2894 /* Used when C code wants a resource value. */
2897 x_get_resource_string (attribute
, class)
2898 char *attribute
, *class;
2902 struct frame
*sf
= SELECTED_FRAME ();
2904 /* Allocate space for the components, the dots which separate them,
2905 and the final '\0'. */
2906 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2907 + strlen (attribute
) + 2);
2908 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2909 + strlen (class) + 2);
2911 sprintf (name_key
, "%s.%s",
2912 XSTRING (Vinvocation_name
)->data
,
2914 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2916 return x_get_string_resource (sf
, name_key
, class_key
);
2919 /* Types we might convert a resource string into. */
2929 /* Return the value of parameter PARAM.
2931 First search ALIST, then Vdefault_frame_alist, then the X defaults
2932 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2934 Convert the resource to the type specified by desired_type.
2936 If no default is specified, return Qunbound. If you call
2937 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
2938 and don't let it get stored in any Lisp-visible variables! */
2941 w32_get_arg (alist
, param
, attribute
, class, type
)
2942 Lisp_Object alist
, param
;
2945 enum resource_types type
;
2947 register Lisp_Object tem
;
2949 tem
= Fassq (param
, alist
);
2951 tem
= Fassq (param
, Vdefault_frame_alist
);
2957 tem
= Fx_get_resource (build_string (attribute
),
2958 build_string (class),
2966 case RES_TYPE_NUMBER
:
2967 return make_number (atoi (XSTRING (tem
)->data
));
2969 case RES_TYPE_FLOAT
:
2970 return make_float (atof (XSTRING (tem
)->data
));
2972 case RES_TYPE_BOOLEAN
:
2973 tem
= Fdowncase (tem
);
2974 if (!strcmp (XSTRING (tem
)->data
, "on")
2975 || !strcmp (XSTRING (tem
)->data
, "true"))
2980 case RES_TYPE_STRING
:
2983 case RES_TYPE_SYMBOL
:
2984 /* As a special case, we map the values `true' and `on'
2985 to Qt, and `false' and `off' to Qnil. */
2988 lower
= Fdowncase (tem
);
2989 if (!strcmp (XSTRING (lower
)->data
, "on")
2990 || !strcmp (XSTRING (lower
)->data
, "true"))
2992 else if (!strcmp (XSTRING (lower
)->data
, "off")
2993 || !strcmp (XSTRING (lower
)->data
, "false"))
2996 return Fintern (tem
, Qnil
);
3009 /* Record in frame F the specified or default value according to ALIST
3010 of the parameter named PROP (a Lisp symbol).
3011 If no value is specified for PROP, look for an X default for XPROP
3012 on the frame named NAME.
3013 If that is not found either, use the value DEFLT. */
3016 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3023 enum resource_types type
;
3027 tem
= w32_get_arg (alist
, prop
, xprop
, xclass
, type
);
3028 if (EQ (tem
, Qunbound
))
3030 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3034 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3035 "Parse an X-style geometry string STRING.\n\
3036 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
3037 The properties returned may include `top', `left', `height', and `width'.\n\
3038 The value of `left' or `top' may be an integer,\n\
3039 or a list (+ N) meaning N pixels relative to top/left corner,\n\
3040 or a list (- N) meaning -N pixels relative to bottom/right corner.")
3045 unsigned int width
, height
;
3048 CHECK_STRING (string
, 0);
3050 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
3051 &x
, &y
, &width
, &height
);
3054 if (geometry
& XValue
)
3056 Lisp_Object element
;
3058 if (x
>= 0 && (geometry
& XNegative
))
3059 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3060 else if (x
< 0 && ! (geometry
& XNegative
))
3061 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3063 element
= Fcons (Qleft
, make_number (x
));
3064 result
= Fcons (element
, result
);
3067 if (geometry
& YValue
)
3069 Lisp_Object element
;
3071 if (y
>= 0 && (geometry
& YNegative
))
3072 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3073 else if (y
< 0 && ! (geometry
& YNegative
))
3074 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3076 element
= Fcons (Qtop
, make_number (y
));
3077 result
= Fcons (element
, result
);
3080 if (geometry
& WidthValue
)
3081 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3082 if (geometry
& HeightValue
)
3083 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3088 /* Calculate the desired size and position of this window,
3089 and return the flags saying which aspects were specified.
3091 This function does not make the coordinates positive. */
3093 #define DEFAULT_ROWS 40
3094 #define DEFAULT_COLS 80
3097 x_figure_window_size (f
, parms
)
3101 register Lisp_Object tem0
, tem1
, tem2
;
3102 long window_prompting
= 0;
3104 /* Default values if we fall through.
3105 Actually, if that happens we should get
3106 window manager prompting. */
3107 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3108 f
->height
= DEFAULT_ROWS
;
3109 /* Window managers expect that if program-specified
3110 positions are not (0,0), they're intentional, not defaults. */
3111 f
->output_data
.w32
->top_pos
= 0;
3112 f
->output_data
.w32
->left_pos
= 0;
3114 tem0
= w32_get_arg (parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3115 tem1
= w32_get_arg (parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3116 tem2
= w32_get_arg (parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3117 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3119 if (!EQ (tem0
, Qunbound
))
3121 CHECK_NUMBER (tem0
, 0);
3122 f
->height
= XINT (tem0
);
3124 if (!EQ (tem1
, Qunbound
))
3126 CHECK_NUMBER (tem1
, 0);
3127 SET_FRAME_WIDTH (f
, XINT (tem1
));
3129 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3130 window_prompting
|= USSize
;
3132 window_prompting
|= PSize
;
3135 f
->output_data
.w32
->vertical_scroll_bar_extra
3136 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3138 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3139 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3140 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
3141 f
->output_data
.w32
->flags_areas_extra
3142 = FRAME_FLAGS_AREA_WIDTH (f
);
3143 f
->output_data
.w32
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3144 f
->output_data
.w32
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3146 tem0
= w32_get_arg (parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3147 tem1
= w32_get_arg (parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3148 tem2
= w32_get_arg (parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3149 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3151 if (EQ (tem0
, Qminus
))
3153 f
->output_data
.w32
->top_pos
= 0;
3154 window_prompting
|= YNegative
;
3156 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3157 && CONSP (XCDR (tem0
))
3158 && INTEGERP (XCAR (XCDR (tem0
))))
3160 f
->output_data
.w32
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3161 window_prompting
|= YNegative
;
3163 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3164 && CONSP (XCDR (tem0
))
3165 && INTEGERP (XCAR (XCDR (tem0
))))
3167 f
->output_data
.w32
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3169 else if (EQ (tem0
, Qunbound
))
3170 f
->output_data
.w32
->top_pos
= 0;
3173 CHECK_NUMBER (tem0
, 0);
3174 f
->output_data
.w32
->top_pos
= XINT (tem0
);
3175 if (f
->output_data
.w32
->top_pos
< 0)
3176 window_prompting
|= YNegative
;
3179 if (EQ (tem1
, Qminus
))
3181 f
->output_data
.w32
->left_pos
= 0;
3182 window_prompting
|= XNegative
;
3184 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3185 && CONSP (XCDR (tem1
))
3186 && INTEGERP (XCAR (XCDR (tem1
))))
3188 f
->output_data
.w32
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3189 window_prompting
|= XNegative
;
3191 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3192 && CONSP (XCDR (tem1
))
3193 && INTEGERP (XCAR (XCDR (tem1
))))
3195 f
->output_data
.w32
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3197 else if (EQ (tem1
, Qunbound
))
3198 f
->output_data
.w32
->left_pos
= 0;
3201 CHECK_NUMBER (tem1
, 0);
3202 f
->output_data
.w32
->left_pos
= XINT (tem1
);
3203 if (f
->output_data
.w32
->left_pos
< 0)
3204 window_prompting
|= XNegative
;
3207 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3208 window_prompting
|= USPosition
;
3210 window_prompting
|= PPosition
;
3213 return window_prompting
;
3218 extern LRESULT CALLBACK
w32_wnd_proc ();
3221 w32_init_class (hinst
)
3226 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
3227 wc
.lpfnWndProc
= (WNDPROC
) w32_wnd_proc
;
3229 wc
.cbWndExtra
= WND_EXTRA_BYTES
;
3230 wc
.hInstance
= hinst
;
3231 wc
.hIcon
= LoadIcon (hinst
, EMACS_CLASS
);
3232 wc
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
3233 wc
.hbrBackground
= NULL
; /* GetStockObject (WHITE_BRUSH); */
3234 wc
.lpszMenuName
= NULL
;
3235 wc
.lpszClassName
= EMACS_CLASS
;
3237 return (RegisterClass (&wc
));
3241 w32_createscrollbar (f
, bar
)
3243 struct scroll_bar
* bar
;
3245 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
3246 /* Position and size of scroll bar. */
3247 XINT(bar
->left
) + VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
3249 XINT(bar
->width
) - VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
3251 FRAME_W32_WINDOW (f
),
3258 w32_createwindow (f
)
3264 rect
.left
= rect
.top
= 0;
3265 rect
.right
= PIXEL_WIDTH (f
);
3266 rect
.bottom
= PIXEL_HEIGHT (f
);
3268 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
3269 FRAME_EXTERNAL_MENU_BAR (f
));
3271 /* Do first time app init */
3275 w32_init_class (hinst
);
3278 FRAME_W32_WINDOW (f
) = hwnd
3279 = CreateWindow (EMACS_CLASS
,
3281 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
3282 f
->output_data
.w32
->left_pos
,
3283 f
->output_data
.w32
->top_pos
,
3284 rect
.right
- rect
.left
,
3285 rect
.bottom
- rect
.top
,
3293 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
3294 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
3295 SetWindowLong (hwnd
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
3296 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
3297 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
3299 /* Enable drag-n-drop. */
3300 DragAcceptFiles (hwnd
, TRUE
);
3302 /* Do this to discard the default setting specified by our parent. */
3303 ShowWindow (hwnd
, SW_HIDE
);
3308 my_post_msg (wmsg
, hwnd
, msg
, wParam
, lParam
)
3315 wmsg
->msg
.hwnd
= hwnd
;
3316 wmsg
->msg
.message
= msg
;
3317 wmsg
->msg
.wParam
= wParam
;
3318 wmsg
->msg
.lParam
= lParam
;
3319 wmsg
->msg
.time
= GetMessageTime ();
3324 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
3325 between left and right keys as advertised. We test for this
3326 support dynamically, and set a flag when the support is absent. If
3327 absent, we keep track of the left and right control and alt keys
3328 ourselves. This is particularly necessary on keyboards that rely
3329 upon the AltGr key, which is represented as having the left control
3330 and right alt keys pressed. For these keyboards, we need to know
3331 when the left alt key has been pressed in addition to the AltGr key
3332 so that we can properly support M-AltGr-key sequences (such as M-@
3333 on Swedish keyboards). */
3335 #define EMACS_LCONTROL 0
3336 #define EMACS_RCONTROL 1
3337 #define EMACS_LMENU 2
3338 #define EMACS_RMENU 3
3340 static int modifiers
[4];
3341 static int modifiers_recorded
;
3342 static int modifier_key_support_tested
;
3345 test_modifier_support (unsigned int wparam
)
3349 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
3351 if (wparam
== VK_CONTROL
)
3361 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
3362 modifiers_recorded
= 1;
3364 modifiers_recorded
= 0;
3365 modifier_key_support_tested
= 1;
3369 record_keydown (unsigned int wparam
, unsigned int lparam
)
3373 if (!modifier_key_support_tested
)
3374 test_modifier_support (wparam
);
3376 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
3379 if (wparam
== VK_CONTROL
)
3380 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
3382 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
3388 record_keyup (unsigned int wparam
, unsigned int lparam
)
3392 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
3395 if (wparam
== VK_CONTROL
)
3396 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
3398 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
3403 /* Emacs can lose focus while a modifier key has been pressed. When
3404 it regains focus, be conservative and clear all modifiers since
3405 we cannot reconstruct the left and right modifier state. */
3411 if (GetFocus () == NULL
)
3412 /* Emacs doesn't have keyboard focus. Do nothing. */
3415 ctrl
= GetAsyncKeyState (VK_CONTROL
);
3416 alt
= GetAsyncKeyState (VK_MENU
);
3418 if (!(ctrl
& 0x08000))
3419 /* Clear any recorded control modifier state. */
3420 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3422 if (!(alt
& 0x08000))
3423 /* Clear any recorded alt modifier state. */
3424 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3426 /* Update the state of all modifier keys, because modifiers used in
3427 hot-key combinations can get stuck on if Emacs loses focus as a
3428 result of a hot-key being pressed. */
3432 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
3434 GetKeyboardState (keystate
);
3435 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
3436 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
3437 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
3438 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
3439 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
3440 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
3441 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
3442 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
3443 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
3444 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
3445 SetKeyboardState (keystate
);
3449 /* Synchronize modifier state with what is reported with the current
3450 keystroke. Even if we cannot distinguish between left and right
3451 modifier keys, we know that, if no modifiers are set, then neither
3452 the left or right modifier should be set. */
3456 if (!modifiers_recorded
)
3459 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
3460 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3462 if (!(GetKeyState (VK_MENU
) & 0x8000))
3463 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3467 modifier_set (int vkey
)
3469 if (vkey
== VK_CAPITAL
|| vkey
== VK_SCROLL
)
3470 return (GetKeyState (vkey
) & 0x1);
3471 if (!modifiers_recorded
)
3472 return (GetKeyState (vkey
) & 0x8000);
3477 return modifiers
[EMACS_LCONTROL
];
3479 return modifiers
[EMACS_RCONTROL
];
3481 return modifiers
[EMACS_LMENU
];
3483 return modifiers
[EMACS_RMENU
];
3485 return (GetKeyState (vkey
) & 0x8000);
3488 /* Convert between the modifier bits W32 uses and the modifier bits
3492 w32_key_to_modifier (int key
)
3494 Lisp_Object key_mapping
;
3499 key_mapping
= Vw32_lwindow_modifier
;
3502 key_mapping
= Vw32_rwindow_modifier
;
3505 key_mapping
= Vw32_apps_modifier
;
3508 key_mapping
= Vw32_scroll_lock_modifier
;
3514 /* NB. This code runs in the input thread, asychronously to the lisp
3515 thread, so we must be careful to ensure access to lisp data is
3516 thread-safe. The following code is safe because the modifier
3517 variable values are updated atomically from lisp and symbols are
3518 not relocated by GC. Also, we don't have to worry about seeing GC
3520 if (EQ (key_mapping
, Qhyper
))
3521 return hyper_modifier
;
3522 if (EQ (key_mapping
, Qsuper
))
3523 return super_modifier
;
3524 if (EQ (key_mapping
, Qmeta
))
3525 return meta_modifier
;
3526 if (EQ (key_mapping
, Qalt
))
3527 return alt_modifier
;
3528 if (EQ (key_mapping
, Qctrl
))
3529 return ctrl_modifier
;
3530 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
3531 return ctrl_modifier
;
3532 if (EQ (key_mapping
, Qshift
))
3533 return shift_modifier
;
3535 /* Don't generate any modifier if not explicitly requested. */
3540 w32_get_modifiers ()
3542 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
3543 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
3544 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
3545 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
3546 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
3547 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
3548 (modifier_set (VK_MENU
) ?
3549 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
3552 /* We map the VK_* modifiers into console modifier constants
3553 so that we can use the same routines to handle both console
3554 and window input. */
3557 construct_console_modifiers ()
3562 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
3563 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
3564 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
3565 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
3566 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
3567 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
3568 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
3569 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
3570 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
3571 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
3572 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
3578 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
3582 /* Convert to emacs modifiers. */
3583 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
3589 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
3591 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
3594 if (virt_key
== VK_RETURN
)
3595 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
3597 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
3598 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
3600 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
3601 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
3603 if (virt_key
== VK_CLEAR
)
3604 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
3609 /* List of special key combinations which w32 would normally capture,
3610 but emacs should grab instead. Not directly visible to lisp, to
3611 simplify synchronization. Each item is an integer encoding a virtual
3612 key code and modifier combination to capture. */
3613 Lisp_Object w32_grabbed_keys
;
3615 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
3616 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
3617 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
3618 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
3620 /* Register hot-keys for reserved key combinations when Emacs has
3621 keyboard focus, since this is the only way Emacs can receive key
3622 combinations like Alt-Tab which are used by the system. */
3625 register_hot_keys (hwnd
)
3628 Lisp_Object keylist
;
3630 /* Use GC_CONSP, since we are called asynchronously. */
3631 for (keylist
= w32_grabbed_keys
; GC_CONSP (keylist
); keylist
= XCDR (keylist
))
3633 Lisp_Object key
= XCAR (keylist
);
3635 /* Deleted entries get set to nil. */
3636 if (!INTEGERP (key
))
3639 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
3640 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
3645 unregister_hot_keys (hwnd
)
3648 Lisp_Object keylist
;
3650 /* Use GC_CONSP, since we are called asynchronously. */
3651 for (keylist
= w32_grabbed_keys
; GC_CONSP (keylist
); keylist
= XCDR (keylist
))
3653 Lisp_Object key
= XCAR (keylist
);
3655 if (!INTEGERP (key
))
3658 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
3662 /* Main message dispatch loop. */
3665 w32_msg_pump (deferred_msg
* msg_buf
)
3671 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
3673 while (GetMessage (&msg
, NULL
, 0, 0))
3675 if (msg
.hwnd
== NULL
)
3677 switch (msg
.message
)
3680 /* Produced by complete_deferred_msg; just ignore. */
3682 case WM_EMACS_CREATEWINDOW
:
3683 w32_createwindow ((struct frame
*) msg
.wParam
);
3684 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3687 case WM_EMACS_SETLOCALE
:
3688 SetThreadLocale (msg
.wParam
);
3689 /* Reply is not expected. */
3691 case WM_EMACS_SETKEYBOARDLAYOUT
:
3692 result
= (int) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
3693 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
3697 case WM_EMACS_REGISTER_HOT_KEY
:
3698 focus_window
= GetFocus ();
3699 if (focus_window
!= NULL
)
3700 RegisterHotKey (focus_window
,
3701 HOTKEY_ID (msg
.wParam
),
3702 HOTKEY_MODIFIERS (msg
.wParam
),
3703 HOTKEY_VK_CODE (msg
.wParam
));
3704 /* Reply is not expected. */
3706 case WM_EMACS_UNREGISTER_HOT_KEY
:
3707 focus_window
= GetFocus ();
3708 if (focus_window
!= NULL
)
3709 UnregisterHotKey (focus_window
, HOTKEY_ID (msg
.wParam
));
3710 /* Mark item as erased. NB: this code must be
3711 thread-safe. The next line is okay because the cons
3712 cell is never made into garbage and is not relocated by
3714 XCAR ((Lisp_Object
) msg
.lParam
) = Qnil
;
3715 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3718 case WM_EMACS_TOGGLE_LOCK_KEY
:
3720 int vk_code
= (int) msg
.wParam
;
3721 int cur_state
= (GetKeyState (vk_code
) & 1);
3722 Lisp_Object new_state
= (Lisp_Object
) msg
.lParam
;
3724 /* NB: This code must be thread-safe. It is safe to
3725 call NILP because symbols are not relocated by GC,
3726 and pointer here is not touched by GC (so the markbit
3727 can't be set). Numbers are safe because they are
3728 immediate values. */
3729 if (NILP (new_state
)
3730 || (NUMBERP (new_state
)
3731 && (XUINT (new_state
)) & 1 != cur_state
))
3733 one_w32_display_info
.faked_key
= vk_code
;
3735 keybd_event ((BYTE
) vk_code
,
3736 (BYTE
) MapVirtualKey (vk_code
, 0),
3737 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3738 keybd_event ((BYTE
) vk_code
,
3739 (BYTE
) MapVirtualKey (vk_code
, 0),
3740 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3741 keybd_event ((BYTE
) vk_code
,
3742 (BYTE
) MapVirtualKey (vk_code
, 0),
3743 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3744 cur_state
= !cur_state
;
3746 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
3752 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
3757 DispatchMessage (&msg
);
3760 /* Exit nested loop when our deferred message has completed. */
3761 if (msg_buf
->completed
)
3766 deferred_msg
* deferred_msg_head
;
3768 static deferred_msg
*
3769 find_deferred_msg (HWND hwnd
, UINT msg
)
3771 deferred_msg
* item
;
3773 /* Don't actually need synchronization for read access, since
3774 modification of single pointer is always atomic. */
3775 /* enter_crit (); */
3777 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
3778 if (item
->w32msg
.msg
.hwnd
== hwnd
3779 && item
->w32msg
.msg
.message
== msg
)
3782 /* leave_crit (); */
3788 send_deferred_msg (deferred_msg
* msg_buf
,
3794 /* Only input thread can send deferred messages. */
3795 if (GetCurrentThreadId () != dwWindowsThreadId
)
3798 /* It is an error to send a message that is already deferred. */
3799 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3802 /* Enforced synchronization is not needed because this is the only
3803 function that alters deferred_msg_head, and the following critical
3804 section is guaranteed to only be serially reentered (since only the
3805 input thread can call us). */
3807 /* enter_crit (); */
3809 msg_buf
->completed
= 0;
3810 msg_buf
->next
= deferred_msg_head
;
3811 deferred_msg_head
= msg_buf
;
3812 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
3814 /* leave_crit (); */
3816 /* Start a new nested message loop to process other messages until
3817 this one is completed. */
3818 w32_msg_pump (msg_buf
);
3820 deferred_msg_head
= msg_buf
->next
;
3822 return msg_buf
->result
;
3826 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
3828 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
3830 if (msg_buf
== NULL
)
3831 /* Message may have been cancelled, so don't abort(). */
3834 msg_buf
->result
= result
;
3835 msg_buf
->completed
= 1;
3837 /* Ensure input thread is woken so it notices the completion. */
3838 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
3842 cancel_all_deferred_msgs ()
3844 deferred_msg
* item
;
3846 /* Don't actually need synchronization for read access, since
3847 modification of single pointer is always atomic. */
3848 /* enter_crit (); */
3850 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
3853 item
->completed
= 1;
3856 /* leave_crit (); */
3858 /* Ensure input thread is woken so it notices the completion. */
3859 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
3867 deferred_msg dummy_buf
;
3869 /* Ensure our message queue is created */
3871 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3873 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3876 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
3877 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
3878 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
3880 /* This is the inital message loop which should only exit when the
3881 application quits. */
3882 w32_msg_pump (&dummy_buf
);
3888 post_character_message (hwnd
, msg
, wParam
, lParam
, modifiers
)
3898 wmsg
.dwModifiers
= modifiers
;
3900 /* Detect quit_char and set quit-flag directly. Note that we
3901 still need to post a message to ensure the main thread will be
3902 woken up if blocked in sys_select(), but we do NOT want to post
3903 the quit_char message itself (because it will usually be as if
3904 the user had typed quit_char twice). Instead, we post a dummy
3905 message that has no particular effect. */
3908 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
3909 c
= make_ctrl_char (c
) & 0377;
3911 || (wmsg
.dwModifiers
== 0 &&
3912 XFASTINT (Vw32_quit_key
) && wParam
== XFASTINT (Vw32_quit_key
)))
3916 /* The choice of message is somewhat arbitrary, as long as
3917 the main thread handler just ignores it. */
3920 /* Interrupt any blocking system calls. */
3923 /* As a safety precaution, forcibly complete any deferred
3924 messages. This is a kludge, but I don't see any particularly
3925 clean way to handle the situation where a deferred message is
3926 "dropped" in the lisp thread, and will thus never be
3927 completed, eg. by the user trying to activate the menubar
3928 when the lisp thread is busy, and then typing C-g when the
3929 menubar doesn't open promptly (with the result that the
3930 menubar never responds at all because the deferred
3931 WM_INITMENU message is never completed). Another problem
3932 situation is when the lisp thread calls SendMessage (to send
3933 a window manager command) when a message has been deferred;
3934 the lisp thread gets blocked indefinitely waiting for the
3935 deferred message to be completed, which itself is waiting for
3936 the lisp thread to respond.
3938 Note that we don't want to block the input thread waiting for
3939 a reponse from the lisp thread (although that would at least
3940 solve the deadlock problem above), because we want to be able
3941 to receive C-g to interrupt the lisp thread. */
3942 cancel_all_deferred_msgs ();
3946 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3949 /* Main window procedure */
3952 w32_wnd_proc (hwnd
, msg
, wParam
, lParam
)
3959 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3961 int windows_translate
;
3964 /* Note that it is okay to call x_window_to_frame, even though we are
3965 not running in the main lisp thread, because frame deletion
3966 requires the lisp thread to synchronize with this thread. Thus, if
3967 a frame struct is returned, it can be used without concern that the
3968 lisp thread might make it disappear while we are using it.
3970 NB. Walking the frame list in this thread is safe (as long as
3971 writes of Lisp_Object slots are atomic, which they are on Windows).
3972 Although delete-frame can destructively modify the frame list while
3973 we are walking it, a garbage collection cannot occur until after
3974 delete-frame has synchronized with this thread.
3976 It is also safe to use functions that make GDI calls, such as
3977 w32_clear_rect, because these functions must obtain a DC handle
3978 from the frame struct using get_frame_dc which is thread-aware. */
3983 f
= x_window_to_frame (dpyinfo
, hwnd
);
3986 HDC hdc
= get_frame_dc (f
);
3987 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
3988 w32_clear_rect (f
, hdc
, &wmsg
.rect
);
3989 release_frame_dc (f
, hdc
);
3991 #if defined (W32_DEBUG_DISPLAY)
3992 DebPrint (("WM_ERASEBKGND: erasing %d,%d-%d,%d\n",
3993 wmsg
.rect
.left
, wmsg
.rect
.top
, wmsg
.rect
.right
,
3995 #endif /* W32_DEBUG_DISPLAY */
3998 case WM_PALETTECHANGED
:
3999 /* ignore our own changes */
4000 if ((HWND
)wParam
!= hwnd
)
4002 f
= x_window_to_frame (dpyinfo
, hwnd
);
4004 /* get_frame_dc will realize our palette and force all
4005 frames to be redrawn if needed. */
4006 release_frame_dc (f
, get_frame_dc (f
));
4011 PAINTSTRUCT paintStruct
;
4014 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
4015 fails. Apparently this can happen under some
4017 if (!w32_strict_painting
|| GetUpdateRect (hwnd
, &update_rect
, FALSE
))
4020 BeginPaint (hwnd
, &paintStruct
);
4022 if (w32_strict_painting
)
4023 /* The rectangles returned by GetUpdateRect and BeginPaint
4024 do not always match. GetUpdateRect seems to be the
4025 more reliable of the two. */
4026 wmsg
.rect
= update_rect
;
4028 wmsg
.rect
= paintStruct
.rcPaint
;
4030 #if defined (W32_DEBUG_DISPLAY)
4031 DebPrint (("WM_PAINT: painting %d,%d-%d,%d\n", wmsg
.rect
.left
,
4032 wmsg
.rect
.top
, wmsg
.rect
.right
, wmsg
.rect
.bottom
));
4033 DebPrint (("WM_PAINT: update region is %d,%d-%d,%d\n",
4034 update_rect
.left
, update_rect
.top
,
4035 update_rect
.right
, update_rect
.bottom
));
4037 EndPaint (hwnd
, &paintStruct
);
4040 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4045 /* If GetUpdateRect returns 0 (meaning there is no update
4046 region), assume the whole window needs to be repainted. */
4047 GetClientRect(hwnd
, &wmsg
.rect
);
4048 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4052 case WM_INPUTLANGCHANGE
:
4053 /* Inform lisp thread of keyboard layout changes. */
4054 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4056 /* Clear dead keys in the keyboard state; for simplicity only
4057 preserve modifier key states. */
4062 GetKeyboardState (keystate
);
4063 for (i
= 0; i
< 256; i
++)
4080 SetKeyboardState (keystate
);
4085 /* Synchronize hot keys with normal input. */
4086 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
4091 record_keyup (wParam
, lParam
);
4096 /* Ignore keystrokes we fake ourself; see below. */
4097 if (dpyinfo
->faked_key
== wParam
)
4099 dpyinfo
->faked_key
= 0;
4100 /* Make sure TranslateMessage sees them though (as long as
4101 they don't produce WM_CHAR messages). This ensures that
4102 indicator lights are toggled promptly on Windows 9x, for
4104 if (lispy_function_keys
[wParam
] != 0)
4106 windows_translate
= 1;
4112 /* Synchronize modifiers with current keystroke. */
4114 record_keydown (wParam
, lParam
);
4115 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
4117 windows_translate
= 0;
4122 if (NILP (Vw32_pass_lwindow_to_system
))
4124 /* Prevent system from acting on keyup (which opens the
4125 Start menu if no other key was pressed) by simulating a
4126 press of Space which we will ignore. */
4127 if (GetAsyncKeyState (wParam
) & 1)
4129 if (NUMBERP (Vw32_phantom_key_code
))
4130 key
= XUINT (Vw32_phantom_key_code
) & 255;
4133 dpyinfo
->faked_key
= key
;
4134 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
4137 if (!NILP (Vw32_lwindow_modifier
))
4141 if (NILP (Vw32_pass_rwindow_to_system
))
4143 if (GetAsyncKeyState (wParam
) & 1)
4145 if (NUMBERP (Vw32_phantom_key_code
))
4146 key
= XUINT (Vw32_phantom_key_code
) & 255;
4149 dpyinfo
->faked_key
= key
;
4150 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
4153 if (!NILP (Vw32_rwindow_modifier
))
4157 if (!NILP (Vw32_apps_modifier
))
4161 if (NILP (Vw32_pass_alt_to_system
))
4162 /* Prevent DefWindowProc from activating the menu bar if an
4163 Alt key is pressed and released by itself. */
4165 windows_translate
= 1;
4168 /* Decide whether to treat as modifier or function key. */
4169 if (NILP (Vw32_enable_caps_lock
))
4170 goto disable_lock_key
;
4171 windows_translate
= 1;
4174 /* Decide whether to treat as modifier or function key. */
4175 if (NILP (Vw32_enable_num_lock
))
4176 goto disable_lock_key
;
4177 windows_translate
= 1;
4180 /* Decide whether to treat as modifier or function key. */
4181 if (NILP (Vw32_scroll_lock_modifier
))
4182 goto disable_lock_key
;
4183 windows_translate
= 1;
4186 /* Ensure the appropriate lock key state (and indicator light)
4187 remains in the same state. We do this by faking another
4188 press of the relevant key. Apparently, this really is the
4189 only way to toggle the state of the indicator lights. */
4190 dpyinfo
->faked_key
= wParam
;
4191 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
4192 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
4193 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
4194 KEYEVENTF_EXTENDEDKEY
| 0, 0);
4195 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
4196 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
4197 /* Ensure indicator lights are updated promptly on Windows 9x
4198 (TranslateMessage apparently does this), after forwarding
4200 post_character_message (hwnd
, msg
, wParam
, lParam
,
4201 w32_get_key_modifiers (wParam
, lParam
));
4202 windows_translate
= 1;
4206 case VK_PROCESSKEY
: /* Generated by IME. */
4207 windows_translate
= 1;
4210 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
4211 which is confusing for purposes of key binding; convert
4212 VK_CANCEL events into VK_PAUSE events. */
4216 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
4217 for purposes of key binding; convert these back into
4218 VK_NUMLOCK events, at least when we want to see NumLock key
4219 presses. (Note that there is never any possibility that
4220 VK_PAUSE with Ctrl really is C-Pause as per above.) */
4221 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
4222 wParam
= VK_NUMLOCK
;
4225 /* If not defined as a function key, change it to a WM_CHAR message. */
4226 if (lispy_function_keys
[wParam
] == 0)
4228 DWORD modifiers
= construct_console_modifiers ();
4230 if (!NILP (Vw32_recognize_altgr
)
4231 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
4233 /* Always let TranslateMessage handle AltGr key chords;
4234 for some reason, ToAscii doesn't always process AltGr
4235 chords correctly. */
4236 windows_translate
= 1;
4238 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
4240 /* Handle key chords including any modifiers other
4241 than shift directly, in order to preserve as much
4242 modifier information as possible. */
4243 if ('A' <= wParam
&& wParam
<= 'Z')
4245 /* Don't translate modified alphabetic keystrokes,
4246 so the user doesn't need to constantly switch
4247 layout to type control or meta keystrokes when
4248 the normal layout translates alphabetic
4249 characters to non-ascii characters. */
4250 if (!modifier_set (VK_SHIFT
))
4251 wParam
+= ('a' - 'A');
4256 /* Try to handle other keystrokes by determining the
4257 base character (ie. translating the base key plus
4261 KEY_EVENT_RECORD key
;
4263 key
.bKeyDown
= TRUE
;
4264 key
.wRepeatCount
= 1;
4265 key
.wVirtualKeyCode
= wParam
;
4266 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
4267 key
.uChar
.AsciiChar
= 0;
4268 key
.dwControlKeyState
= modifiers
;
4270 add
= w32_kbd_patch_key (&key
);
4271 /* 0 means an unrecognised keycode, negative means
4272 dead key. Ignore both. */
4275 /* Forward asciified character sequence. */
4276 post_character_message
4277 (hwnd
, WM_CHAR
, key
.uChar
.AsciiChar
, lParam
,
4278 w32_get_key_modifiers (wParam
, lParam
));
4279 w32_kbd_patch_key (&key
);
4286 /* Let TranslateMessage handle everything else. */
4287 windows_translate
= 1;
4293 if (windows_translate
)
4295 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
4297 windows_msg
.time
= GetMessageTime ();
4298 TranslateMessage (&windows_msg
);
4306 post_character_message (hwnd
, msg
, wParam
, lParam
,
4307 w32_get_key_modifiers (wParam
, lParam
));
4310 /* Simulate middle mouse button events when left and right buttons
4311 are used together, but only if user has two button mouse. */
4312 case WM_LBUTTONDOWN
:
4313 case WM_RBUTTONDOWN
:
4314 if (XINT (Vw32_num_mouse_buttons
) > 2)
4315 goto handle_plain_button
;
4318 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
4319 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
4321 if (button_state
& this)
4324 if (button_state
== 0)
4327 button_state
|= this;
4329 if (button_state
& other
)
4331 if (mouse_button_timer
)
4333 KillTimer (hwnd
, mouse_button_timer
);
4334 mouse_button_timer
= 0;
4336 /* Generate middle mouse event instead. */
4337 msg
= WM_MBUTTONDOWN
;
4338 button_state
|= MMOUSE
;
4340 else if (button_state
& MMOUSE
)
4342 /* Ignore button event if we've already generated a
4343 middle mouse down event. This happens if the
4344 user releases and press one of the two buttons
4345 after we've faked a middle mouse event. */
4350 /* Flush out saved message. */
4351 post_msg (&saved_mouse_button_msg
);
4353 wmsg
.dwModifiers
= w32_get_modifiers ();
4354 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4356 /* Clear message buffer. */
4357 saved_mouse_button_msg
.msg
.hwnd
= 0;
4361 /* Hold onto message for now. */
4362 mouse_button_timer
=
4363 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
4364 XINT (Vw32_mouse_button_tolerance
), NULL
);
4365 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
4366 saved_mouse_button_msg
.msg
.message
= msg
;
4367 saved_mouse_button_msg
.msg
.wParam
= wParam
;
4368 saved_mouse_button_msg
.msg
.lParam
= lParam
;
4369 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
4370 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
4377 if (XINT (Vw32_num_mouse_buttons
) > 2)
4378 goto handle_plain_button
;
4381 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
4382 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
4384 if ((button_state
& this) == 0)
4387 button_state
&= ~this;
4389 if (button_state
& MMOUSE
)
4391 /* Only generate event when second button is released. */
4392 if ((button_state
& other
) == 0)
4395 button_state
&= ~MMOUSE
;
4397 if (button_state
) abort ();
4404 /* Flush out saved message if necessary. */
4405 if (saved_mouse_button_msg
.msg
.hwnd
)
4407 post_msg (&saved_mouse_button_msg
);
4410 wmsg
.dwModifiers
= w32_get_modifiers ();
4411 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4413 /* Always clear message buffer and cancel timer. */
4414 saved_mouse_button_msg
.msg
.hwnd
= 0;
4415 KillTimer (hwnd
, mouse_button_timer
);
4416 mouse_button_timer
= 0;
4418 if (button_state
== 0)
4423 case WM_MBUTTONDOWN
:
4425 handle_plain_button
:
4430 if (parse_button (msg
, &button
, &up
))
4432 if (up
) ReleaseCapture ();
4433 else SetCapture (hwnd
);
4434 button
= (button
== 0) ? LMOUSE
:
4435 ((button
== 1) ? MMOUSE
: RMOUSE
);
4437 button_state
&= ~button
;
4439 button_state
|= button
;
4443 wmsg
.dwModifiers
= w32_get_modifiers ();
4444 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4449 if (XINT (Vw32_mouse_move_interval
) <= 0
4450 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
4452 wmsg
.dwModifiers
= w32_get_modifiers ();
4453 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4457 /* Hang onto mouse move and scroll messages for a bit, to avoid
4458 sending such events to Emacs faster than it can process them.
4459 If we get more events before the timer from the first message
4460 expires, we just replace the first message. */
4462 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
4464 SetTimer (hwnd
, MOUSE_MOVE_ID
,
4465 XINT (Vw32_mouse_move_interval
), NULL
);
4467 /* Hold onto message for now. */
4468 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
4469 saved_mouse_move_msg
.msg
.message
= msg
;
4470 saved_mouse_move_msg
.msg
.wParam
= wParam
;
4471 saved_mouse_move_msg
.msg
.lParam
= lParam
;
4472 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
4473 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
4478 wmsg
.dwModifiers
= w32_get_modifiers ();
4479 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4483 wmsg
.dwModifiers
= w32_get_modifiers ();
4484 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4488 /* Flush out saved messages if necessary. */
4489 if (wParam
== mouse_button_timer
)
4491 if (saved_mouse_button_msg
.msg
.hwnd
)
4493 post_msg (&saved_mouse_button_msg
);
4494 saved_mouse_button_msg
.msg
.hwnd
= 0;
4496 KillTimer (hwnd
, mouse_button_timer
);
4497 mouse_button_timer
= 0;
4499 else if (wParam
== mouse_move_timer
)
4501 if (saved_mouse_move_msg
.msg
.hwnd
)
4503 post_msg (&saved_mouse_move_msg
);
4504 saved_mouse_move_msg
.msg
.hwnd
= 0;
4506 KillTimer (hwnd
, mouse_move_timer
);
4507 mouse_move_timer
= 0;
4512 /* Windows doesn't send us focus messages when putting up and
4513 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
4514 The only indication we get that something happened is receiving
4515 this message afterwards. So this is a good time to reset our
4516 keyboard modifiers' state. */
4523 /* We must ensure menu bar is fully constructed and up to date
4524 before allowing user interaction with it. To achieve this
4525 we send this message to the lisp thread and wait for a
4526 reply (whose value is not actually needed) to indicate that
4527 the menu bar is now ready for use, so we can now return.
4529 To remain responsive in the meantime, we enter a nested message
4530 loop that can process all other messages.
4532 However, we skip all this if the message results from calling
4533 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
4534 thread a message because it is blocked on us at this point. We
4535 set menubar_active before calling TrackPopupMenu to indicate
4536 this (there is no possibility of confusion with real menubar
4539 f
= x_window_to_frame (dpyinfo
, hwnd
);
4541 && (f
->output_data
.w32
->menubar_active
4542 /* We can receive this message even in the absence of a
4543 menubar (ie. when the system menu is activated) - in this
4544 case we do NOT want to forward the message, otherwise it
4545 will cause the menubar to suddenly appear when the user
4546 had requested it to be turned off! */
4547 || f
->output_data
.w32
->menubar_widget
== NULL
))
4551 deferred_msg msg_buf
;
4553 /* Detect if message has already been deferred; in this case
4554 we cannot return any sensible value to ignore this. */
4555 if (find_deferred_msg (hwnd
, msg
) != NULL
)
4558 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
4561 case WM_EXITMENULOOP
:
4562 f
= x_window_to_frame (dpyinfo
, hwnd
);
4564 /* Indicate that menubar can be modified again. */
4566 f
->output_data
.w32
->menubar_active
= 0;
4570 wmsg
.dwModifiers
= w32_get_modifiers ();
4571 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4574 case WM_MEASUREITEM
:
4575 f
= x_window_to_frame (dpyinfo
, hwnd
);
4578 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
4580 if (pMis
->CtlType
== ODT_MENU
)
4582 /* Work out dimensions for popup menu titles. */
4583 char * title
= (char *) pMis
->itemData
;
4584 HDC hdc
= GetDC (hwnd
);
4585 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
4586 LOGFONT menu_logfont
;
4590 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
4591 menu_logfont
.lfWeight
= FW_BOLD
;
4592 menu_font
= CreateFontIndirect (&menu_logfont
);
4593 old_font
= SelectObject (hdc
, menu_font
);
4595 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
4598 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
4599 pMis
->itemWidth
= size
.cx
;
4600 if (pMis
->itemHeight
< size
.cy
)
4601 pMis
->itemHeight
= size
.cy
;
4604 pMis
->itemWidth
= 0;
4606 SelectObject (hdc
, old_font
);
4607 DeleteObject (menu_font
);
4608 ReleaseDC (hwnd
, hdc
);
4615 f
= x_window_to_frame (dpyinfo
, hwnd
);
4618 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
4620 if (pDis
->CtlType
== ODT_MENU
)
4622 /* Draw popup menu title. */
4623 char * title
= (char *) pDis
->itemData
;
4624 HDC hdc
= pDis
->hDC
;
4625 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
4626 LOGFONT menu_logfont
;
4629 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
4630 menu_logfont
.lfWeight
= FW_BOLD
;
4631 menu_font
= CreateFontIndirect (&menu_logfont
);
4632 old_font
= SelectObject (hdc
, menu_font
);
4634 /* Always draw title as if not selected. */
4636 pDis
->rcItem
.left
+ GetSystemMetrics (SM_CXMENUCHECK
),
4638 ETO_OPAQUE
, &pDis
->rcItem
,
4639 title
, strlen (title
), NULL
);
4641 SelectObject (hdc
, old_font
);
4642 DeleteObject (menu_font
);
4649 /* Still not right - can't distinguish between clicks in the
4650 client area of the frame from clicks forwarded from the scroll
4651 bars - may have to hook WM_NCHITTEST to remember the mouse
4652 position and then check if it is in the client area ourselves. */
4653 case WM_MOUSEACTIVATE
:
4654 /* Discard the mouse click that activates a frame, allowing the
4655 user to click anywhere without changing point (or worse!).
4656 Don't eat mouse clicks on scrollbars though!! */
4657 if (LOWORD (lParam
) == HTCLIENT
)
4658 return MA_ACTIVATEANDEAT
;
4662 case WM_ACTIVATEAPP
:
4664 case WM_WINDOWPOSCHANGED
:
4666 /* Inform lisp thread that a frame might have just been obscured
4667 or exposed, so should recheck visibility of all frames. */
4668 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4672 dpyinfo
->faked_key
= 0;
4674 register_hot_keys (hwnd
);
4677 unregister_hot_keys (hwnd
);
4684 wmsg
.dwModifiers
= w32_get_modifiers ();
4685 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4689 wmsg
.dwModifiers
= w32_get_modifiers ();
4690 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4693 case WM_WINDOWPOSCHANGING
:
4696 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
4698 wp
.length
= sizeof (WINDOWPLACEMENT
);
4699 GetWindowPlacement (hwnd
, &wp
);
4701 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
4708 DWORD internal_border
;
4709 DWORD scrollbar_extra
;
4712 wp
.length
= sizeof(wp
);
4713 GetWindowRect (hwnd
, &wr
);
4717 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
4718 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
4719 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
4720 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
4724 memset (&rect
, 0, sizeof (rect
));
4725 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
4726 GetMenu (hwnd
) != NULL
);
4728 /* Force width and height of client area to be exact
4729 multiples of the character cell dimensions. */
4730 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
4731 - 2 * internal_border
- scrollbar_extra
)
4733 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
4734 - 2 * internal_border
)
4739 /* For right/bottom sizing we can just fix the sizes.
4740 However for top/left sizing we will need to fix the X
4741 and Y positions as well. */
4746 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
4747 && (lppos
->flags
& SWP_NOMOVE
) == 0)
4749 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
4756 lppos
->flags
|= SWP_NOMOVE
;
4767 case WM_GETMINMAXINFO
:
4768 /* Hack to correct bug that allows Emacs frames to be resized
4769 below the Minimum Tracking Size. */
4770 ((LPMINMAXINFO
) lParam
)->ptMinTrackSize
.y
++;
4773 case WM_EMACS_CREATESCROLLBAR
:
4774 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
4775 (struct scroll_bar
*) lParam
);
4777 case WM_EMACS_SHOWWINDOW
:
4778 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
4780 case WM_EMACS_SETFOREGROUND
:
4782 HWND foreground_window
;
4783 DWORD foreground_thread
, retval
;
4785 /* On NT 5.0, and apparently Windows 98, it is necessary to
4786 attach to the thread that currently has focus in order to
4787 pull the focus away from it. */
4788 foreground_window
= GetForegroundWindow ();
4789 foreground_thread
= GetWindowThreadProcessId (foreground_window
, NULL
);
4790 if (!foreground_window
4791 || foreground_thread
== GetCurrentThreadId ()
4792 || !AttachThreadInput (GetCurrentThreadId (),
4793 foreground_thread
, TRUE
))
4794 foreground_thread
= 0;
4796 retval
= SetForegroundWindow ((HWND
) wParam
);
4798 /* Detach from the previous foreground thread. */
4799 if (foreground_thread
)
4800 AttachThreadInput (GetCurrentThreadId (),
4801 foreground_thread
, FALSE
);
4806 case WM_EMACS_SETWINDOWPOS
:
4808 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
4809 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
4810 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
4813 case WM_EMACS_DESTROYWINDOW
:
4814 DragAcceptFiles ((HWND
) wParam
, FALSE
);
4815 return DestroyWindow ((HWND
) wParam
);
4817 case WM_EMACS_TRACKPOPUPMENU
:
4822 pos
= (POINT
*)lParam
;
4823 flags
= TPM_CENTERALIGN
;
4824 if (button_state
& LMOUSE
)
4825 flags
|= TPM_LEFTBUTTON
;
4826 else if (button_state
& RMOUSE
)
4827 flags
|= TPM_RIGHTBUTTON
;
4829 /* Remember we did a SetCapture on the initial mouse down event,
4830 so for safety, we make sure the capture is cancelled now. */
4834 /* Use menubar_active to indicate that WM_INITMENU is from
4835 TrackPopupMenu below, and should be ignored. */
4836 f
= x_window_to_frame (dpyinfo
, hwnd
);
4838 f
->output_data
.w32
->menubar_active
= 1;
4840 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
4844 /* Eat any mouse messages during popupmenu */
4845 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
4847 /* Get the menu selection, if any */
4848 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
4850 retval
= LOWORD (amsg
.wParam
);
4866 /* Check for messages registered at runtime. */
4867 if (msg
== msh_mousewheel
)
4869 wmsg
.dwModifiers
= w32_get_modifiers ();
4870 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4875 return DefWindowProc (hwnd
, msg
, wParam
, lParam
);
4879 /* The most common default return code for handled messages is 0. */
4884 my_create_window (f
)
4889 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
4891 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4894 /* Create and set up the w32 window for frame F. */
4897 w32_window (f
, window_prompting
, minibuffer_only
)
4899 long window_prompting
;
4900 int minibuffer_only
;
4904 /* Use the resource name as the top-level window name
4905 for looking up resources. Make a non-Lisp copy
4906 for the window manager, so GC relocation won't bother it.
4908 Elsewhere we specify the window name for the window manager. */
4911 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
4912 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
4913 strcpy (f
->namebuf
, str
);
4916 my_create_window (f
);
4918 validate_x_resource_name ();
4920 /* x_set_name normally ignores requests to set the name if the
4921 requested name is the same as the current name. This is the one
4922 place where that assumption isn't correct; f->name is set, but
4923 the server hasn't been told. */
4926 int explicit = f
->explicit_name
;
4928 f
->explicit_name
= 0;
4931 x_set_name (f
, name
, explicit);
4936 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4937 initialize_frame_menubar (f
);
4939 if (FRAME_W32_WINDOW (f
) == 0)
4940 error ("Unable to create window");
4943 /* Handle the icon stuff for this window. Perhaps later we might
4944 want an x_set_icon_position which can be called interactively as
4952 Lisp_Object icon_x
, icon_y
;
4954 /* Set the position of the icon. Note that Windows 95 groups all
4955 icons in the tray. */
4956 icon_x
= w32_get_arg (parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4957 icon_y
= w32_get_arg (parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4958 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4960 CHECK_NUMBER (icon_x
, 0);
4961 CHECK_NUMBER (icon_y
, 0);
4963 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4964 error ("Both left and top icon corners of icon must be specified");
4968 if (! EQ (icon_x
, Qunbound
))
4969 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4972 /* Start up iconic or window? */
4973 x_wm_set_window_state
4974 (f
, (EQ (w32_get_arg (parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
), Qicon
)
4978 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
4991 XGCValues gc_values
;
4995 /* Create the GC's of this frame.
4996 Note that many default values are used. */
4999 gc_values
.font
= f
->output_data
.w32
->font
;
5001 /* Cursor has cursor-color background, background-color foreground. */
5002 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
5003 gc_values
.background
= f
->output_data
.w32
->cursor_pixel
;
5004 f
->output_data
.w32
->cursor_gc
5005 = XCreateGC (NULL
, FRAME_W32_WINDOW (f
),
5006 (GCFont
| GCForeground
| GCBackground
),
5010 f
->output_data
.w32
->white_relief
.gc
= 0;
5011 f
->output_data
.w32
->black_relief
.gc
= 0;
5017 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
5019 "Make a new window, which is called a \"frame\" in Emacs terms.\n\
5020 Returns an Emacs frame object.\n\
5021 ALIST is an alist of frame parameters.\n\
5022 If the parameters specify that the frame should not have a minibuffer,\n\
5023 and do not specify a specific minibuffer window to use,\n\
5024 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
5025 be shared by the new frame.\n\
5027 This function is an internal primitive--use `make-frame' instead.")
5032 Lisp_Object frame
, tem
;
5034 int minibuffer_only
= 0;
5035 long window_prompting
= 0;
5037 int count
= specpdl_ptr
- specpdl
;
5038 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
5039 Lisp_Object display
;
5040 struct w32_display_info
*dpyinfo
= NULL
;
5046 /* Use this general default value to start with
5047 until we know if this frame has a specified name. */
5048 Vx_resource_name
= Vinvocation_name
;
5050 display
= w32_get_arg (parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
5051 if (EQ (display
, Qunbound
))
5053 dpyinfo
= check_x_display_info (display
);
5055 kb
= dpyinfo
->kboard
;
5057 kb
= &the_only_kboard
;
5060 name
= w32_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
5062 && ! EQ (name
, Qunbound
)
5064 error ("Invalid frame name--not a string or nil");
5067 Vx_resource_name
= name
;
5069 /* See if parent window is specified. */
5070 parent
= w32_get_arg (parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
5071 if (EQ (parent
, Qunbound
))
5073 if (! NILP (parent
))
5074 CHECK_NUMBER (parent
, 0);
5076 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
5077 /* No need to protect DISPLAY because that's not used after passing
5078 it to make_frame_without_minibuffer. */
5080 GCPRO4 (parms
, parent
, name
, frame
);
5081 tem
= w32_get_arg (parms
, Qminibuffer
, 0, 0, RES_TYPE_SYMBOL
);
5082 if (EQ (tem
, Qnone
) || NILP (tem
))
5083 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
5084 else if (EQ (tem
, Qonly
))
5086 f
= make_minibuffer_frame ();
5087 minibuffer_only
= 1;
5089 else if (WINDOWP (tem
))
5090 f
= make_frame_without_minibuffer (tem
, kb
, display
);
5094 XSETFRAME (frame
, f
);
5096 /* Note that Windows does support scroll bars. */
5097 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
5098 /* By default, make scrollbars the system standard width. */
5099 f
->scroll_bar_pixel_width
= GetSystemMetrics (SM_CXVSCROLL
);
5101 f
->output_method
= output_w32
;
5102 f
->output_data
.w32
=
5103 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
5104 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
5106 FRAME_FONTSET (f
) = -1;
5109 = w32_get_arg (parms
, Qicon_name
, "iconName", "Title", RES_TYPE_STRING
);
5110 if (! STRINGP (f
->icon_name
))
5111 f
->icon_name
= Qnil
;
5113 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
5115 FRAME_KBOARD (f
) = kb
;
5118 /* Specify the parent under which to make this window. */
5122 f
->output_data
.w32
->parent_desc
= (Window
) parent
;
5123 f
->output_data
.w32
->explicit_parent
= 1;
5127 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
5128 f
->output_data
.w32
->explicit_parent
= 0;
5131 /* Set the name; the functions to which we pass f expect the name to
5133 if (EQ (name
, Qunbound
) || NILP (name
))
5135 f
->name
= build_string (dpyinfo
->w32_id_name
);
5136 f
->explicit_name
= 0;
5141 f
->explicit_name
= 1;
5142 /* use the frame's title when getting resources for this frame. */
5143 specbind (Qx_resource_name
, name
);
5146 /* Extract the window parameters from the supplied values
5147 that are needed to determine window geometry. */
5151 font
= w32_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
5154 /* First, try whatever font the caller has specified. */
5157 tem
= Fquery_fontset (font
, Qnil
);
5159 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
5161 font
= x_new_font (f
, XSTRING (font
)->data
);
5163 /* Try out a font which we hope has bold and italic variations. */
5164 if (!STRINGP (font
))
5165 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
5166 if (! STRINGP (font
))
5167 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
5168 /* If those didn't work, look for something which will at least work. */
5169 if (! STRINGP (font
))
5170 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
5172 if (! STRINGP (font
))
5173 font
= build_string ("Fixedsys");
5175 x_default_parameter (f
, parms
, Qfont
, font
,
5176 "font", "Font", RES_TYPE_STRING
);
5179 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
5180 "borderwidth", "BorderWidth", RES_TYPE_NUMBER
);
5181 /* This defaults to 2 in order to match xterm. We recognize either
5182 internalBorderWidth or internalBorder (which is what xterm calls
5184 if (NILP (Fassq (Qinternal_border_width
, parms
)))
5188 value
= w32_get_arg (parms
, Qinternal_border_width
,
5189 "internalBorder", "BorderWidth", RES_TYPE_NUMBER
);
5190 if (! EQ (value
, Qunbound
))
5191 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
5194 /* Default internalBorderWidth to 0 on Windows to match other programs. */
5195 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (0),
5196 "internalBorderWidth", "BorderWidth", RES_TYPE_NUMBER
);
5197 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qt
,
5198 "verticalScrollBars", "ScrollBars", RES_TYPE_BOOLEAN
);
5200 /* Also do the stuff which must be set before the window exists. */
5201 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
5202 "foreground", "Foreground", RES_TYPE_STRING
);
5203 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
5204 "background", "Background", RES_TYPE_STRING
);
5205 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
5206 "pointerColor", "Foreground", RES_TYPE_STRING
);
5207 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
5208 "cursorColor", "Foreground", RES_TYPE_STRING
);
5209 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
5210 "borderColor", "BorderColor", RES_TYPE_STRING
);
5211 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
5212 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
5213 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
5214 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
5217 /* Init faces before x_default_parameter is called for scroll-bar
5218 parameters because that function calls x_set_scroll_bar_width,
5219 which calls change_frame_size, which calls Fset_window_buffer,
5220 which runs hooks, which call Fvertical_motion. At the end, we
5221 end up in init_iterator with a null face cache, which should not
5223 init_frame_faces (f
);
5225 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
5226 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
5227 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (0),
5228 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
5229 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
5230 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL
);
5231 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
5232 "title", "Title", RES_TYPE_STRING
);
5234 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
5235 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
5236 window_prompting
= x_figure_window_size (f
, parms
);
5238 if (window_prompting
& XNegative
)
5240 if (window_prompting
& YNegative
)
5241 f
->output_data
.w32
->win_gravity
= SouthEastGravity
;
5243 f
->output_data
.w32
->win_gravity
= NorthEastGravity
;
5247 if (window_prompting
& YNegative
)
5248 f
->output_data
.w32
->win_gravity
= SouthWestGravity
;
5250 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
5253 f
->output_data
.w32
->size_hint_flags
= window_prompting
;
5255 tem
= w32_get_arg (parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
5256 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
5258 /* Create the window. Add the tool-bar height to the initial frame
5259 height so that the user gets a text display area of the size he
5260 specified with -g or via the registry. Later changes of the
5261 tool-bar height don't change the frame size. This is done so that
5262 users can create tall Emacs frames without having to guess how
5263 tall the tool-bar will get. */
5264 f
->height
+= FRAME_TOOL_BAR_LINES (f
);
5265 w32_window (f
, window_prompting
, minibuffer_only
);
5270 /* Now consider the frame official. */
5271 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
5272 Vframe_list
= Fcons (frame
, Vframe_list
);
5274 /* We need to do this after creating the window, so that the
5275 icon-creation functions can say whose icon they're describing. */
5276 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
5277 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
5279 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
5280 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5281 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
5282 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5283 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
5284 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
5285 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
5286 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER
);
5288 /* Dimensions, especially f->height, must be done via change_frame_size.
5289 Change will not be effected unless different from the current
5294 SET_FRAME_WIDTH (f
, 0);
5295 change_frame_size (f
, height
, width
, 1, 0, 0);
5297 /* Set up faces after all frame parameters are known. */
5298 call1 (Qface_set_after_frame_default
, frame
);
5300 /* Tell the server what size and position, etc, we want, and how
5301 badly we want them. This should be done after we have the menu
5302 bar so that its size can be taken into account. */
5304 x_wm_set_size_hint (f
, window_prompting
, 0);
5307 /* Make the window appear on the frame and enable display, unless
5308 the caller says not to. However, with explicit parent, Emacs
5309 cannot control visibility, so don't try. */
5310 if (! f
->output_data
.w32
->explicit_parent
)
5312 Lisp_Object visibility
;
5314 visibility
= w32_get_arg (parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
);
5315 if (EQ (visibility
, Qunbound
))
5318 if (EQ (visibility
, Qicon
))
5319 x_iconify_frame (f
);
5320 else if (! NILP (visibility
))
5321 x_make_frame_visible (f
);
5323 /* Must have been Qnil. */
5327 return unbind_to (count
, frame
);
5330 /* FRAME is used only to get a handle on the X display. We don't pass the
5331 display info directly because we're called from frame.c, which doesn't
5332 know about that structure. */
5334 x_get_focus_frame (frame
)
5335 struct frame
*frame
;
5337 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
5339 if (! dpyinfo
->w32_focus_frame
)
5342 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
5346 DEFUN ("w32-focus-frame", Fw32_focus_frame
, Sw32_focus_frame
, 1, 1, 0,
5347 "Give FRAME input focus, raising to foreground if necessary.")
5351 x_focus_on_frame (check_x_frame (frame
));
5356 struct font_info
*w32_load_bdf_font (struct frame
*f
, char *fontname
,
5357 int size
, char* filename
);
5360 w32_load_system_font (f
,fontname
,size
)
5365 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
5366 Lisp_Object font_names
;
5368 /* Get a list of all the fonts that match this name. Once we
5369 have a list of matching fonts, we compare them against the fonts
5370 we already have loaded by comparing names. */
5371 font_names
= w32_list_fonts (f
, build_string (fontname
), size
, 100);
5373 if (!NILP (font_names
))
5378 /* First check if any are already loaded, as that is cheaper
5379 than loading another one. */
5380 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5381 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
5382 if (dpyinfo
->font_table
[i
].name
5383 && (!strcmp (dpyinfo
->font_table
[i
].name
,
5384 XSTRING (XCAR (tail
))->data
)
5385 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
5386 XSTRING (XCAR (tail
))->data
)))
5387 return (dpyinfo
->font_table
+ i
);
5389 fontname
= (char *) XSTRING (XCAR (font_names
))->data
;
5391 else if (w32_strict_fontnames
)
5393 /* If EnumFontFamiliesEx was available, we got a full list of
5394 fonts back so stop now to avoid the possibility of loading a
5395 random font. If we had to fall back to EnumFontFamilies, the
5396 list is incomplete, so continue whether the font we want was
5398 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
5399 FARPROC enum_font_families_ex
5400 = GetProcAddress (gdi32
, "EnumFontFamiliesExA");
5401 if (enum_font_families_ex
)
5405 /* Load the font and add it to the table. */
5407 char *full_name
, *encoding
;
5409 struct font_info
*fontp
;
5414 if (!fontname
|| !x_to_w32_font (fontname
, &lf
))
5417 if (!*lf
.lfFaceName
)
5418 /* If no name was specified for the font, we get a random font
5419 from CreateFontIndirect - this is not particularly
5420 desirable, especially since CreateFontIndirect does not
5421 fill out the missing name in lf, so we never know what we
5425 font
= (XFontStruct
*) xmalloc (sizeof (XFontStruct
));
5427 /* Set bdf to NULL to indicate that this is a Windows font. */
5432 font
->hfont
= CreateFontIndirect (&lf
);
5434 if (font
->hfont
== NULL
)
5443 hdc
= GetDC (dpyinfo
->root_window
);
5444 oldobj
= SelectObject (hdc
, font
->hfont
);
5445 ok
= GetTextMetrics (hdc
, &font
->tm
);
5446 font
->double_byte_p
= GetFontLanguageInfo(hdc
) & GCP_DBCS
;
5447 SelectObject (hdc
, oldobj
);
5448 ReleaseDC (dpyinfo
->root_window
, hdc
);
5449 /* Fill out details in lf according to the font that was
5451 lf
.lfHeight
= font
->tm
.tmInternalLeading
- font
->tm
.tmHeight
;
5452 lf
.lfWidth
= font
->tm
.tmAveCharWidth
;
5453 lf
.lfWeight
= font
->tm
.tmWeight
;
5454 lf
.lfItalic
= font
->tm
.tmItalic
;
5455 lf
.lfCharSet
= font
->tm
.tmCharSet
;
5456 lf
.lfPitchAndFamily
= ((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
)
5457 ? VARIABLE_PITCH
: FIXED_PITCH
);
5458 lf
.lfOutPrecision
= ((font
->tm
.tmPitchAndFamily
& TMPF_VECTOR
)
5459 ? OUT_STROKE_PRECIS
: OUT_STRING_PRECIS
);
5466 w32_unload_font (dpyinfo
, font
);
5470 /* Find a free slot in the font table. */
5471 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
5472 if (dpyinfo
->font_table
[i
].name
== NULL
)
5475 /* If no free slot found, maybe enlarge the font table. */
5476 if (i
== dpyinfo
->n_fonts
5477 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
5480 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
5481 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
5483 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
5486 fontp
= dpyinfo
->font_table
+ i
;
5487 if (i
== dpyinfo
->n_fonts
)
5490 /* Now fill in the slots of *FONTP. */
5493 fontp
->font_idx
= i
;
5494 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
5495 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
5497 /* Work out the font's full name. */
5498 full_name
= (char *)xmalloc (100);
5499 if (full_name
&& w32_to_x_font (&lf
, full_name
, 100))
5500 fontp
->full_name
= full_name
;
5503 /* If all else fails - just use the name we used to load it. */
5505 fontp
->full_name
= fontp
->name
;
5508 fontp
->size
= FONT_WIDTH (font
);
5509 fontp
->height
= FONT_HEIGHT (font
);
5511 /* The slot `encoding' specifies how to map a character
5512 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
5513 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
5514 (0:0x20..0x7F, 1:0xA0..0xFF,
5515 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
5516 2:0xA020..0xFF7F). For the moment, we don't know which charset
5517 uses this font. So, we set information in fontp->encoding[1]
5518 which is never used by any charset. If mapping can't be
5519 decided, set FONT_ENCODING_NOT_DECIDED. */
5521 /* SJIS fonts need to be set to type 4, all others seem to work as
5522 type FONT_ENCODING_NOT_DECIDED. */
5523 encoding
= strrchr (fontp
->name
, '-');
5524 if (encoding
&& stricmp (encoding
+1, "sjis") == 0)
5525 fontp
->encoding
[1] = 4;
5527 fontp
->encoding
[1] = FONT_ENCODING_NOT_DECIDED
;
5529 /* The following three values are set to 0 under W32, which is
5530 what they get set to if XGetFontProperty fails under X. */
5531 fontp
->baseline_offset
= 0;
5532 fontp
->relative_compose
= 0;
5533 fontp
->default_ascent
= 0;
5535 /* Set global flag fonts_changed_p to non-zero if the font loaded
5536 has a character with a smaller width than any other character
5537 before, or if the font loaded has a smalle>r height than any
5538 other font loaded before. If this happens, it will make a
5539 glyph matrix reallocation necessary. */
5540 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
5546 /* Load font named FONTNAME of size SIZE for frame F, and return a
5547 pointer to the structure font_info while allocating it dynamically.
5548 If loading fails, return NULL. */
5550 w32_load_font (f
,fontname
,size
)
5555 Lisp_Object bdf_fonts
;
5556 struct font_info
*retval
= NULL
;
5558 bdf_fonts
= w32_list_bdf_fonts (build_string (fontname
));
5560 while (!retval
&& CONSP (bdf_fonts
))
5562 char *bdf_name
, *bdf_file
;
5563 Lisp_Object bdf_pair
;
5565 bdf_name
= XSTRING (XCAR (bdf_fonts
))->data
;
5566 bdf_pair
= Fassoc (XCAR (bdf_fonts
), Vw32_bdf_filename_alist
);
5567 bdf_file
= XSTRING (XCDR (bdf_pair
))->data
;
5569 retval
= w32_load_bdf_font (f
, bdf_name
, size
, bdf_file
);
5571 bdf_fonts
= XCDR (bdf_fonts
);
5577 return w32_load_system_font(f
, fontname
, size
);
5582 w32_unload_font (dpyinfo
, font
)
5583 struct w32_display_info
*dpyinfo
;
5588 if (font
->bdf
) w32_free_bdf_font (font
->bdf
);
5590 if (font
->hfont
) DeleteObject(font
->hfont
);
5595 /* The font conversion stuff between x and w32 */
5597 /* X font string is as follows (from faces.el)
5601 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
5602 * (weight\? "\\([^-]*\\)") ; 1
5603 * (slant "\\([ior]\\)") ; 2
5604 * (slant\? "\\([^-]?\\)") ; 2
5605 * (swidth "\\([^-]*\\)") ; 3
5606 * (adstyle "[^-]*") ; 4
5607 * (pixelsize "[0-9]+")
5608 * (pointsize "[0-9][0-9]+")
5609 * (resx "[0-9][0-9]+")
5610 * (resy "[0-9][0-9]+")
5611 * (spacing "[cmp?*]")
5612 * (avgwidth "[0-9]+")
5613 * (registry "[^-]+")
5614 * (encoding "[^-]+")
5616 * (setq x-font-regexp
5617 * (concat "\\`\\*?[-?*]"
5618 * foundry - family - weight\? - slant\? - swidth - adstyle -
5619 * pixelsize - pointsize - resx - resy - spacing - registry -
5620 * encoding "[-?*]\\*?\\'"
5622 * (setq x-font-regexp-head
5623 * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
5624 * "\\([-*?]\\|\\'\\)"))
5625 * (setq x-font-regexp-slant (concat - slant -))
5626 * (setq x-font-regexp-weight (concat - weight -))
5630 #define FONT_START "[-?]"
5631 #define FONT_FOUNDRY "[^-]+"
5632 #define FONT_FAMILY "\\([^-]+\\)" /* 1 */
5633 #define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
5634 #define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
5635 #define FONT_SLANT "\\([ior]\\)" /* 3 */
5636 #define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
5637 #define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
5638 #define FONT_ADSTYLE "[^-]*"
5639 #define FONT_PIXELSIZE "[^-]*"
5640 #define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
5641 #define FONT_RESX "[0-9][0-9]+"
5642 #define FONT_RESY "[0-9][0-9]+"
5643 #define FONT_SPACING "[cmp?*]"
5644 #define FONT_AVGWIDTH "[0-9]+"
5645 #define FONT_REGISTRY "[^-]+"
5646 #define FONT_ENCODING "[^-]+"
5648 #define FONT_REGEXP ("\\`\\*?[-?*]" \
5655 FONT_PIXELSIZE "-" \
5656 FONT_POINTSIZE "-" \
5659 #define FONT_REGEXP_HEAD ("\\`[-?*]" \
5664 "\\([-*?]\\|\\'\\)")
5666 #define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
5667 #define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
5670 x_to_w32_weight (lpw
)
5673 if (!lpw
) return (FW_DONTCARE
);
5675 if (stricmp (lpw
,"heavy") == 0) return FW_HEAVY
;
5676 else if (stricmp (lpw
,"extrabold") == 0) return FW_EXTRABOLD
;
5677 else if (stricmp (lpw
,"bold") == 0) return FW_BOLD
;
5678 else if (stricmp (lpw
,"demibold") == 0) return FW_SEMIBOLD
;
5679 else if (stricmp (lpw
,"semibold") == 0) return FW_SEMIBOLD
;
5680 else if (stricmp (lpw
,"medium") == 0) return FW_MEDIUM
;
5681 else if (stricmp (lpw
,"normal") == 0) return FW_NORMAL
;
5682 else if (stricmp (lpw
,"light") == 0) return FW_LIGHT
;
5683 else if (stricmp (lpw
,"extralight") == 0) return FW_EXTRALIGHT
;
5684 else if (stricmp (lpw
,"thin") == 0) return FW_THIN
;
5691 w32_to_x_weight (fnweight
)
5694 if (fnweight
>= FW_HEAVY
) return "heavy";
5695 if (fnweight
>= FW_EXTRABOLD
) return "extrabold";
5696 if (fnweight
>= FW_BOLD
) return "bold";
5697 if (fnweight
>= FW_SEMIBOLD
) return "demibold";
5698 if (fnweight
>= FW_MEDIUM
) return "medium";
5699 if (fnweight
>= FW_NORMAL
) return "normal";
5700 if (fnweight
>= FW_LIGHT
) return "light";
5701 if (fnweight
>= FW_EXTRALIGHT
) return "extralight";
5702 if (fnweight
>= FW_THIN
) return "thin";
5708 x_to_w32_charset (lpcs
)
5713 /* Look through w32-charset-info-alist for the character set.
5714 Format of each entry is
5715 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5717 for (rest
= Vw32_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
5719 Lisp_Object this_entry
= XCAR (rest
);
5720 char * x_charset
= XSTRING (XCAR (this_entry
))->data
;
5722 if (strnicmp (lpcs
, x_charset
, strlen(x_charset
)) == 0)
5724 Lisp_Object w32_charset
= XCAR (XCDR (this_entry
));
5725 // Translate Lisp symbol to number.
5726 if (w32_charset
== Qw32_charset_ansi
)
5727 return ANSI_CHARSET
;
5728 if (w32_charset
== Qw32_charset_symbol
)
5729 return SYMBOL_CHARSET
;
5730 if (w32_charset
== Qw32_charset_shiftjis
)
5731 return SHIFTJIS_CHARSET
;
5732 if (w32_charset
== Qw32_charset_hangul
)
5733 return HANGEUL_CHARSET
;
5734 if (w32_charset
== Qw32_charset_chinesebig5
)
5735 return CHINESEBIG5_CHARSET
;
5736 if (w32_charset
== Qw32_charset_gb2312
)
5737 return GB2312_CHARSET
;
5738 if (w32_charset
== Qw32_charset_oem
)
5740 #ifdef JOHAB_CHARSET
5741 if (w32_charset
== Qw32_charset_johab
)
5742 return JOHAB_CHARSET
;
5743 if (w32_charset
== Qw32_charset_easteurope
)
5744 return EASTEUROPE_CHARSET
;
5745 if (w32_charset
== Qw32_charset_turkish
)
5746 return TURKISH_CHARSET
;
5747 if (w32_charset
== Qw32_charset_baltic
)
5748 return BALTIC_CHARSET
;
5749 if (w32_charset
== Qw32_charset_russian
)
5750 return RUSSIAN_CHARSET
;
5751 if (w32_charset
== Qw32_charset_arabic
)
5752 return ARABIC_CHARSET
;
5753 if (w32_charset
== Qw32_charset_greek
)
5754 return GREEK_CHARSET
;
5755 if (w32_charset
== Qw32_charset_hebrew
)
5756 return HEBREW_CHARSET
;
5757 if (w32_charset
== Qw32_charset_thai
)
5758 return THAI_CHARSET
;
5759 if (w32_charset
== Qw32_charset_mac
)
5761 #endif /* JOHAB_CHARSET */
5762 #ifdef UNICODE_CHARSET
5763 if (w32_charset
== Qw32_charset_unicode
)
5764 return UNICODE_CHARSET
;
5769 return DEFAULT_CHARSET
;
5774 w32_to_x_charset (fncharset
)
5777 static char buf
[16];
5779 /* NTEMACS_TODO: use w32-charset-info-alist. Multiple matches
5780 are possible, so this will require more than just a rewrite of
5781 this function. w32_to_x_font is the only user of this function,
5782 and that will require rewriting too, and its users. */
5785 /* ansi is considered iso8859-1, as most modern ansi fonts are. */
5786 case ANSI_CHARSET
: return "iso8859-1";
5787 case DEFAULT_CHARSET
: return "ascii-*";
5788 case SYMBOL_CHARSET
: return "ms-symbol";
5789 case SHIFTJIS_CHARSET
: return "jisx0208-sjis";
5790 case HANGEUL_CHARSET
: return "ksc5601.1987-*";
5791 case GB2312_CHARSET
: return "gb2312-*";
5792 case CHINESEBIG5_CHARSET
: return "big5-*";
5793 case OEM_CHARSET
: return "ms-oem";
5795 /* More recent versions of Windows (95 and NT4.0) define more
5797 #ifdef EASTEUROPE_CHARSET
5798 case EASTEUROPE_CHARSET
: return "iso8859-2";
5799 case TURKISH_CHARSET
: return "iso8859-9";
5800 case BALTIC_CHARSET
: return "iso8859-4";
5802 /* W95 with international support but not IE4 often has the
5803 KOI8-R codepage but not ISO8859-5. */
5804 case RUSSIAN_CHARSET
:
5805 if (!IsValidCodePage(28595) && IsValidCodePage(20886))
5809 case ARABIC_CHARSET
: return "iso8859-6";
5810 case GREEK_CHARSET
: return "iso8859-7";
5811 case HEBREW_CHARSET
: return "iso8859-8";
5812 case VIETNAMESE_CHARSET
: return "viscii1.1-*";
5813 case THAI_CHARSET
: return "tis620-*";
5814 case MAC_CHARSET
: return "mac-*";
5815 case JOHAB_CHARSET
: return "ksc5601.1992-*";
5819 #ifdef UNICODE_CHARSET
5820 case UNICODE_CHARSET
: return "iso10646-unicode";
5823 /* Encode numerical value of unknown charset. */
5824 sprintf (buf
, "*-#%u", fncharset
);
5829 /* Get the Windows codepage corresponding to the specified font. The
5830 charset info in the font name is used to look up
5831 w32-charset-to-codepage-alist. */
5833 w32_codepage_for_font (char *fontname
)
5835 Lisp_Object codepage
;
5836 char charset_str
[20], *charset
, *end
;
5838 /* Extract charset part of font string. */
5839 if (sscanf (fontname
,
5840 "-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%19s",
5841 charset_str
) == EOF
)
5844 /* Remove leading "*-". */
5845 if (strncmp ("*-", charset_str
, 2) == 0)
5846 charset
= charset_str
+ 2;
5848 charset
= charset_str
;
5850 /* Stop match at wildcard (including preceding '-'). */
5851 if (end
= strchr (charset
, '*'))
5853 if (end
> charset
&& *(end
-1) == '-')
5858 codepage
= Fcdr (Fcdr (Fassoc (build_string(charset
),
5859 Vw32_charset_info_alist
)));
5860 if (INTEGERP (codepage
))
5861 return XINT (codepage
);
5868 w32_to_x_font (lplogfont
, lpxstr
, len
)
5869 LOGFONT
* lplogfont
;
5875 char height_pixels
[8];
5877 char width_pixels
[8];
5878 char *fontname_dash
;
5879 int display_resy
= one_w32_display_info
.resy
;
5880 int display_resx
= one_w32_display_info
.resx
;
5882 struct coding_system coding
;
5884 if (!lpxstr
) abort ();
5889 if (lplogfont
->lfOutPrecision
== OUT_STRING_PRECIS
)
5890 fonttype
= "raster";
5891 else if (lplogfont
->lfOutPrecision
== OUT_STROKE_PRECIS
)
5892 fonttype
= "outline";
5894 fonttype
= "unknown";
5896 setup_coding_system (Fcheck_coding_system (Vw32_system_coding_system
),
5898 coding
.src_multibyte
= 0;
5899 coding
.dst_multibyte
= 1;
5900 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5901 bufsz
= decoding_buffer_size (&coding
, LF_FACESIZE
);
5903 fontname
= alloca(sizeof(*fontname
) * bufsz
);
5904 decode_coding (&coding
, lplogfont
->lfFaceName
, fontname
,
5905 strlen(lplogfont
->lfFaceName
), bufsz
- 1);
5906 *(fontname
+ coding
.produced
) = '\0';
5908 /* Replace dashes with underscores so the dashes are not
5910 fontname_dash
= fontname
;
5911 while (fontname_dash
= strchr (fontname_dash
, '-'))
5912 *fontname_dash
= '_';
5914 if (lplogfont
->lfHeight
)
5916 sprintf (height_pixels
, "%u", abs (lplogfont
->lfHeight
));
5917 sprintf (height_dpi
, "%u",
5918 abs (lplogfont
->lfHeight
) * 720 / display_resy
);
5922 strcpy (height_pixels
, "*");
5923 strcpy (height_dpi
, "*");
5925 if (lplogfont
->lfWidth
)
5926 sprintf (width_pixels
, "%u", lplogfont
->lfWidth
* 10);
5928 strcpy (width_pixels
, "*");
5930 _snprintf (lpxstr
, len
- 1,
5931 "-%s-%s-%s-%c-normal-normal-%s-%s-%d-%d-%c-%s-%s",
5932 fonttype
, /* foundry */
5933 fontname
, /* family */
5934 w32_to_x_weight (lplogfont
->lfWeight
), /* weight */
5935 lplogfont
->lfItalic
?'i':'r', /* slant */
5937 /* add style name */
5938 height_pixels
, /* pixel size */
5939 height_dpi
, /* point size */
5940 display_resx
, /* resx */
5941 display_resy
, /* resy */
5942 ((lplogfont
->lfPitchAndFamily
& 0x3) == VARIABLE_PITCH
)
5943 ? 'p' : 'c', /* spacing */
5944 width_pixels
, /* avg width */
5945 w32_to_x_charset (lplogfont
->lfCharSet
) /* charset registry
5949 lpxstr
[len
- 1] = 0; /* just to be sure */
5954 x_to_w32_font (lpxstr
, lplogfont
)
5956 LOGFONT
* lplogfont
;
5958 struct coding_system coding
;
5960 if (!lplogfont
) return (FALSE
);
5962 memset (lplogfont
, 0, sizeof (*lplogfont
));
5964 /* Set default value for each field. */
5966 lplogfont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
5967 lplogfont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
5968 lplogfont
->lfQuality
= DEFAULT_QUALITY
;
5970 /* go for maximum quality */
5971 lplogfont
->lfOutPrecision
= OUT_STROKE_PRECIS
;
5972 lplogfont
->lfClipPrecision
= CLIP_STROKE_PRECIS
;
5973 lplogfont
->lfQuality
= PROOF_QUALITY
;
5976 lplogfont
->lfCharSet
= DEFAULT_CHARSET
;
5977 lplogfont
->lfWeight
= FW_DONTCARE
;
5978 lplogfont
->lfPitchAndFamily
= DEFAULT_PITCH
| FF_DONTCARE
;
5983 /* Provide a simple escape mechanism for specifying Windows font names
5984 * directly -- if font spec does not beginning with '-', assume this
5986 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
5992 char name
[50], weight
[20], slant
, pitch
, pixels
[10], height
[10],
5993 width
[10], resy
[10], remainder
[20];
5995 int dpi
= one_w32_display_info
.height_in
;
5997 fields
= sscanf (lpxstr
,
5998 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%19s",
5999 name
, weight
, &slant
, pixels
, height
, resy
, &pitch
, width
, remainder
);
6000 if (fields
== EOF
) return (FALSE
);
6002 /* If wildcards cover more than one field, we don't know which
6003 field is which, so don't fill any in. */
6008 if (fields
> 0 && name
[0] != '*')
6014 (Fcheck_coding_system (Vw32_system_coding_system
), &coding
);
6015 coding
.src_multibyte
= 1;
6016 coding
.dst_multibyte
= 1;
6017 bufsize
= encoding_buffer_size (&coding
, strlen (name
));
6018 buf
= (unsigned char *) alloca (bufsize
);
6019 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6020 encode_coding (&coding
, name
, buf
, strlen (name
), bufsize
);
6021 if (coding
.produced
>= LF_FACESIZE
)
6022 coding
.produced
= LF_FACESIZE
- 1;
6023 buf
[coding
.produced
] = 0;
6024 strcpy (lplogfont
->lfFaceName
, buf
);
6028 lplogfont
->lfFaceName
[0] = '\0';
6033 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
6037 if (!NILP (Vw32_enable_synthesized_fonts
))
6038 lplogfont
->lfItalic
= (fields
> 0 && slant
== 'i');
6042 if (fields
> 0 && pixels
[0] != '*')
6043 lplogfont
->lfHeight
= atoi (pixels
);
6047 if (fields
> 0 && resy
[0] != '*')
6050 if (tem
> 0) dpi
= tem
;
6053 if (fields
> -1 && lplogfont
->lfHeight
== 0 && height
[0] != '*')
6054 lplogfont
->lfHeight
= atoi (height
) * dpi
/ 720;
6057 lplogfont
->lfPitchAndFamily
=
6058 (fields
> 0 && pitch
== 'p') ? VARIABLE_PITCH
: FIXED_PITCH
;
6062 if (fields
> 0 && width
[0] != '*')
6063 lplogfont
->lfWidth
= atoi (width
) / 10;
6067 /* Strip the trailing '-' if present. (it shouldn't be, as it
6068 fails the test against xlfd-tight-regexp in fontset.el). */
6070 int len
= strlen (remainder
);
6071 if (len
> 0 && remainder
[len
-1] == '-')
6072 remainder
[len
-1] = 0;
6074 encoding
= remainder
;
6075 if (strncmp (encoding
, "*-", 2) == 0)
6077 lplogfont
->lfCharSet
= x_to_w32_charset (fields
> 0 ? encoding
: "");
6082 char name
[100], height
[10], width
[10], weight
[20];
6084 fields
= sscanf (lpxstr
,
6085 "%99[^:]:%9[^:]:%9[^:]:%19s",
6086 name
, height
, width
, weight
);
6088 if (fields
== EOF
) return (FALSE
);
6092 strncpy (lplogfont
->lfFaceName
,name
, LF_FACESIZE
);
6093 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
6097 lplogfont
->lfFaceName
[0] = 0;
6103 lplogfont
->lfHeight
= atoi (height
);
6108 lplogfont
->lfWidth
= atoi (width
);
6112 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
6115 /* This makes TrueType fonts work better. */
6116 lplogfont
->lfHeight
= - abs (lplogfont
->lfHeight
);
6121 /* Strip the pixel height and point height from the given xlfd, and
6122 return the pixel height. If no pixel height is specified, calculate
6123 one from the point height, or if that isn't defined either, return
6124 0 (which usually signifies a scalable font).
6126 int xlfd_strip_height (char *fontname
)
6128 int pixel_height
, point_height
, dpi
, field_number
;
6129 char *read_from
, *write_to
;
6133 pixel_height
= field_number
= 0;
6136 /* Look for height fields. */
6137 for (read_from
= fontname
; *read_from
; read_from
++)
6139 if (*read_from
== '-')
6142 if (field_number
== 7) /* Pixel height. */
6145 write_to
= read_from
;
6147 /* Find end of field. */
6148 for (;*read_from
&& *read_from
!= '-'; read_from
++)
6151 /* Split the fontname at end of field. */
6157 pixel_height
= atoi (write_to
);
6158 /* Blank out field. */
6159 if (read_from
> write_to
)
6164 /* If the pixel height field is at the end (partial xfld),
6167 return pixel_height
;
6169 /* If we got a pixel height, the point height can be
6170 ignored. Just blank it out and break now. */
6173 /* Find end of point size field. */
6174 for (; *read_from
&& *read_from
!= '-'; read_from
++)
6180 /* Blank out the point size field. */
6181 if (read_from
> write_to
)
6187 return pixel_height
;
6191 /* If the point height is already blank, break now. */
6192 if (*read_from
== '-')
6198 else if (field_number
== 8)
6200 /* If we didn't get a pixel height, try to get the point
6201 height and convert that. */
6203 char *point_size_start
= read_from
++;
6205 /* Find end of field. */
6206 for (; *read_from
&& *read_from
!= '-'; read_from
++)
6215 point_size
= atoi (point_size_start
);
6217 /* Convert to pixel height. */
6218 pixel_height
= point_size
6219 * one_w32_display_info
.height_in
/ 720;
6221 /* Blank out this field and break. */
6229 /* Shift the rest of the font spec into place. */
6230 if (write_to
&& read_from
> write_to
)
6232 for (; *read_from
; read_from
++, write_to
++)
6233 *write_to
= *read_from
;
6237 return pixel_height
;
6240 /* Assume parameter 1 is fully qualified, no wildcards. */
6242 w32_font_match (fontname
, pattern
)
6246 char *regex
= alloca (strlen (pattern
) * 2);
6247 char *font_name_copy
= alloca (strlen (fontname
) + 1);
6250 /* Copy fontname so we can modify it during comparison. */
6251 strcpy (font_name_copy
, fontname
);
6256 /* Turn pattern into a regexp and do a regexp match. */
6257 for (; *pattern
; pattern
++)
6259 if (*pattern
== '?')
6261 else if (*pattern
== '*')
6272 /* Strip out font heights and compare them seperately, since
6273 rounding error can cause mismatches. This also allows a
6274 comparison between a font that declares only a pixel height and a
6275 pattern that declares the point height.
6278 int font_height
, pattern_height
;
6280 font_height
= xlfd_strip_height (font_name_copy
);
6281 pattern_height
= xlfd_strip_height (regex
);
6283 /* Compare now, and don't bother doing expensive regexp matching
6284 if the heights differ. */
6285 if (font_height
&& pattern_height
&& (font_height
!= pattern_height
))
6289 return (fast_c_string_match_ignore_case (build_string (regex
),
6290 font_name_copy
) >= 0);
6293 /* Callback functions, and a structure holding info they need, for
6294 listing system fonts on W32. We need one set of functions to do the
6295 job properly, but these don't work on NT 3.51 and earlier, so we
6296 have a second set which don't handle character sets properly to
6299 In both cases, there are two passes made. The first pass gets one
6300 font from each family, the second pass lists all the fonts from
6303 typedef struct enumfont_t
6308 XFontStruct
*size_ref
;
6309 Lisp_Object
*pattern
;
6314 enum_font_cb2 (lplf
, lptm
, FontType
, lpef
)
6316 NEWTEXTMETRIC
* lptm
;
6320 if (lplf
->elfLogFont
.lfStrikeOut
|| lplf
->elfLogFont
.lfUnderline
)
6323 /* Check that the character set matches if it was specified */
6324 if (lpef
->logfont
.lfCharSet
!= DEFAULT_CHARSET
&&
6325 lplf
->elfLogFont
.lfCharSet
!= lpef
->logfont
.lfCharSet
)
6330 Lisp_Object width
= Qnil
;
6332 /* Truetype fonts do not report their true metrics until loaded */
6333 if (FontType
!= RASTER_FONTTYPE
)
6335 if (!NILP (*(lpef
->pattern
)))
6337 /* Scalable fonts are as big as you want them to be. */
6338 lplf
->elfLogFont
.lfHeight
= lpef
->logfont
.lfHeight
;
6339 lplf
->elfLogFont
.lfWidth
= lpef
->logfont
.lfWidth
;
6340 width
= make_number (lpef
->logfont
.lfWidth
);
6344 lplf
->elfLogFont
.lfHeight
= 0;
6345 lplf
->elfLogFont
.lfWidth
= 0;
6349 /* Make sure the height used here is the same as everywhere
6350 else (ie character height, not cell height). */
6351 if (lplf
->elfLogFont
.lfHeight
> 0)
6353 /* lptm can be trusted for RASTER fonts, but not scalable ones. */
6354 if (FontType
== RASTER_FONTTYPE
)
6355 lplf
->elfLogFont
.lfHeight
= lptm
->tmInternalLeading
- lptm
->tmHeight
;
6357 lplf
->elfLogFont
.lfHeight
= -lplf
->elfLogFont
.lfHeight
;
6360 if (!w32_to_x_font (&(lplf
->elfLogFont
), buf
, 100))
6363 if (NILP (*(lpef
->pattern
))
6364 || w32_font_match (buf
, XSTRING (*(lpef
->pattern
))->data
))
6366 *lpef
->tail
= Fcons (Fcons (build_string (buf
), width
), Qnil
);
6367 lpef
->tail
= &(XCDR (*lpef
->tail
));
6376 enum_font_cb1 (lplf
, lptm
, FontType
, lpef
)
6378 NEWTEXTMETRIC
* lptm
;
6382 return EnumFontFamilies (lpef
->hdc
,
6383 lplf
->elfLogFont
.lfFaceName
,
6384 (FONTENUMPROC
) enum_font_cb2
,
6390 enum_fontex_cb2 (lplf
, lptm
, font_type
, lpef
)
6391 ENUMLOGFONTEX
* lplf
;
6392 NEWTEXTMETRICEX
* lptm
;
6396 /* We are not interested in the extra info we get back from the 'Ex
6397 version - only the fact that we get character set variations
6398 enumerated seperately. */
6399 return enum_font_cb2 ((ENUMLOGFONT
*) lplf
, (NEWTEXTMETRIC
*) lptm
,
6404 enum_fontex_cb1 (lplf
, lptm
, font_type
, lpef
)
6405 ENUMLOGFONTEX
* lplf
;
6406 NEWTEXTMETRICEX
* lptm
;
6410 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
6411 FARPROC enum_font_families_ex
6412 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
6413 /* We don't really expect EnumFontFamiliesEx to disappear once we
6414 get here, so don't bother handling it gracefully. */
6415 if (enum_font_families_ex
== NULL
)
6416 error ("gdi32.dll has disappeared!");
6417 return enum_font_families_ex (lpef
->hdc
,
6419 (FONTENUMPROC
) enum_fontex_cb2
,
6423 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
6424 and xterm.c in Emacs 20.3) */
6426 Lisp_Object
w32_list_bdf_fonts (Lisp_Object pattern
, int max_names
)
6428 char *fontname
, *ptnstr
;
6429 Lisp_Object list
, tem
, newlist
= Qnil
;
6432 list
= Vw32_bdf_filename_alist
;
6433 ptnstr
= XSTRING (pattern
)->data
;
6435 for ( ; CONSP (list
); list
= XCDR (list
))
6439 fontname
= XSTRING (XCAR (tem
))->data
;
6440 else if (STRINGP (tem
))
6441 fontname
= XSTRING (tem
)->data
;
6445 if (w32_font_match (fontname
, ptnstr
))
6447 newlist
= Fcons (XCAR (tem
), newlist
);
6449 if (n_fonts
>= max_names
)
6457 Lisp_Object
w32_list_synthesized_fonts (FRAME_PTR f
, Lisp_Object pattern
,
6458 int size
, int max_names
);
6460 /* Return a list of names of available fonts matching PATTERN on frame
6461 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6462 to be listed. Frame F NULL means we have not yet created any
6463 frame, which means we can't get proper size info, as we don't have
6464 a device context to use for GetTextMetrics.
6465 MAXNAMES sets a limit on how many fonts to match. */
6468 w32_list_fonts (FRAME_PTR f
, Lisp_Object pattern
, int size
, int maxnames
)
6470 Lisp_Object patterns
, key
= Qnil
, tem
, tpat
;
6471 Lisp_Object list
= Qnil
, newlist
= Qnil
, second_best
= Qnil
;
6472 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6475 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6476 if (NILP (patterns
))
6477 patterns
= Fcons (pattern
, Qnil
);
6479 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6483 tpat
= XCAR (patterns
);
6485 /* See if we cached the result for this particular query.
6486 The cache is an alist of the form:
6487 ((PATTERN (FONTNAME . WIDTH) ...) ...)
6489 if (tem
= XCDR (dpyinfo
->name_list_element
),
6490 !NILP (list
= Fassoc (tpat
, tem
)))
6492 list
= Fcdr_safe (list
);
6493 /* We have a cached list. Don't have to get the list again. */
6498 /* At first, put PATTERN in the cache. */
6504 /* Use EnumFontFamiliesEx where it is available, as it knows
6505 about character sets. Fall back to EnumFontFamilies for
6506 older versions of NT that don't support the 'Ex function. */
6507 x_to_w32_font (STRINGP (tpat
) ? XSTRING (tpat
)->data
:
6510 LOGFONT font_match_pattern
;
6511 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
6512 FARPROC enum_font_families_ex
6513 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
6515 /* We do our own pattern matching so we can handle wildcards. */
6516 font_match_pattern
.lfFaceName
[0] = 0;
6517 font_match_pattern
.lfPitchAndFamily
= 0;
6518 /* We can use the charset, because if it is a wildcard it will
6519 be DEFAULT_CHARSET anyway. */
6520 font_match_pattern
.lfCharSet
= ef
.logfont
.lfCharSet
;
6522 ef
.hdc
= GetDC (dpyinfo
->root_window
);
6524 if (enum_font_families_ex
)
6525 enum_font_families_ex (ef
.hdc
,
6526 &font_match_pattern
,
6527 (FONTENUMPROC
) enum_fontex_cb1
,
6530 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
,
6533 ReleaseDC (dpyinfo
->root_window
, ef
.hdc
);
6538 /* Make a list of the fonts we got back.
6539 Store that in the font cache for the display. */
6540 XCDR (dpyinfo
->name_list_element
)
6541 = Fcons (Fcons (tpat
, list
),
6542 XCDR (dpyinfo
->name_list_element
));
6545 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6547 newlist
= second_best
= Qnil
;
6549 /* Make a list of the fonts that have the right width. */
6550 for (; CONSP (list
); list
= XCDR (list
))
6557 if (NILP (XCAR (tem
)))
6561 newlist
= Fcons (XCAR (tem
), newlist
);
6563 if (n_fonts
>= maxnames
)
6568 if (!INTEGERP (XCDR (tem
)))
6570 /* Since we don't yet know the size of the font, we must
6571 load it and try GetTextMetrics. */
6572 W32FontStruct thisinfo
;
6577 if (!x_to_w32_font (XSTRING (XCAR (tem
))->data
, &lf
))
6581 thisinfo
.bdf
= NULL
;
6582 thisinfo
.hfont
= CreateFontIndirect (&lf
);
6583 if (thisinfo
.hfont
== NULL
)
6586 hdc
= GetDC (dpyinfo
->root_window
);
6587 oldobj
= SelectObject (hdc
, thisinfo
.hfont
);
6588 if (GetTextMetrics (hdc
, &thisinfo
.tm
))
6589 XCDR (tem
) = make_number (FONT_WIDTH (&thisinfo
));
6591 XCDR (tem
) = make_number (0);
6592 SelectObject (hdc
, oldobj
);
6593 ReleaseDC (dpyinfo
->root_window
, hdc
);
6594 DeleteObject(thisinfo
.hfont
);
6597 found_size
= XINT (XCDR (tem
));
6598 if (found_size
== size
)
6600 newlist
= Fcons (XCAR (tem
), newlist
);
6602 if (n_fonts
>= maxnames
)
6605 /* keep track of the closest matching size in case
6606 no exact match is found. */
6607 else if (found_size
> 0)
6609 if (NILP (second_best
))
6612 else if (found_size
< size
)
6614 if (XINT (XCDR (second_best
)) > size
6615 || XINT (XCDR (second_best
)) < found_size
)
6620 if (XINT (XCDR (second_best
)) > size
6621 && XINT (XCDR (second_best
)) >
6628 if (!NILP (newlist
))
6630 else if (!NILP (second_best
))
6632 newlist
= Fcons (XCAR (second_best
), Qnil
);
6637 /* Include any bdf fonts. */
6638 if (n_fonts
< maxnames
)
6640 Lisp_Object combined
[2];
6641 combined
[0] = w32_list_bdf_fonts (pattern
, maxnames
- n_fonts
);
6642 combined
[1] = newlist
;
6643 newlist
= Fnconc(2, combined
);
6646 /* If we can't find a font that matches, check if Windows would be
6647 able to synthesize it from a different style. */
6648 if (NILP (newlist
) && !NILP (Vw32_enable_synthesized_fonts
))
6649 newlist
= w32_list_synthesized_fonts (f
, pattern
, size
, maxnames
);
6655 w32_list_synthesized_fonts (f
, pattern
, size
, max_names
)
6657 Lisp_Object pattern
;
6662 char *full_pattn
, *new_pattn
, foundary
[50], family
[50], *pattn_part2
;
6663 char style
[20], slant
;
6664 Lisp_Object matches
, match
, tem
, synthed_matches
= Qnil
;
6666 full_pattn
= XSTRING (pattern
)->data
;
6668 pattn_part2
= alloca (XSTRING (pattern
)->size
);
6669 /* Allow some space for wildcard expansion. */
6670 new_pattn
= alloca (XSTRING (pattern
)->size
+ 100);
6672 fields
= sscanf (full_pattn
, "-%49[^-]-%49[^-]-%19[^-]-%c-%s",
6673 foundary
, family
, style
, &slant
, pattn_part2
);
6674 if (fields
== EOF
|| fields
< 5)
6677 /* If the style and slant are wildcards already there is no point
6678 checking again (and we don't want to keep recursing). */
6679 if (*style
== '*' && slant
== '*')
6682 sprintf (new_pattn
, "-%s-%s-*-*-%s", foundary
, family
, pattn_part2
);
6684 matches
= w32_list_fonts (f
, build_string (new_pattn
), size
, max_names
);
6686 for ( ; CONSP (matches
); matches
= XCDR (matches
))
6688 tem
= XCAR (matches
);
6692 full_pattn
= XSTRING (tem
)->data
;
6693 fields
= sscanf (full_pattn
, "-%49[^-]-%49[^-]-%*[^-]-%*c-%s",
6694 foundary
, family
, pattn_part2
);
6695 if (fields
== EOF
|| fields
< 3)
6698 sprintf (new_pattn
, "-%s-%s-%s-%c-%s", foundary
, family
, style
,
6699 slant
, pattn_part2
);
6701 synthed_matches
= Fcons (build_string (new_pattn
),
6705 return synthed_matches
;
6709 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6711 w32_get_font_info (f
, font_idx
)
6715 return (FRAME_W32_FONT_TABLE (f
) + font_idx
);
6720 w32_query_font (struct frame
*f
, char *fontname
)
6723 struct font_info
*pfi
;
6725 pfi
= FRAME_W32_FONT_TABLE (f
);
6727 for (i
= 0; i
< one_w32_display_info
.n_fonts
;i
++, pfi
++)
6729 if (strcmp(pfi
->name
, fontname
) == 0) return pfi
;
6735 /* Find a CCL program for a font specified by FONTP, and set the member
6736 `encoder' of the structure. */
6739 w32_find_ccl_program (fontp
)
6740 struct font_info
*fontp
;
6742 Lisp_Object list
, elt
;
6744 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
6748 && STRINGP (XCAR (elt
))
6749 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
6755 struct ccl_program
*ccl
6756 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6758 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
6761 fontp
->font_encoder
= ccl
;
6766 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts
, Sw32_find_bdf_fonts
,
6768 "Return a list of BDF fonts in DIR, suitable for appending to\n\
6769 w32-bdf-filename-alist. Fonts which do not contain an xfld description\n\
6770 will not be included in the list. DIR may be a list of directories.")
6772 Lisp_Object directory
;
6774 Lisp_Object list
= Qnil
;
6775 struct gcpro gcpro1
, gcpro2
;
6777 if (!CONSP (directory
))
6778 return w32_find_bdf_fonts_in_dir (directory
);
6780 for ( ; CONSP (directory
); directory
= XCDR (directory
))
6782 Lisp_Object pair
[2];
6785 GCPRO2 (directory
, list
);
6786 pair
[1] = w32_find_bdf_fonts_in_dir( XCAR (directory
) );
6787 list
= Fnconc( 2, pair
);
6793 /* Find BDF files in a specified directory. (use GCPRO when calling,
6794 as this calls lisp to get a directory listing). */
6795 Lisp_Object
w32_find_bdf_fonts_in_dir( Lisp_Object directory
)
6797 Lisp_Object filelist
, list
= Qnil
;
6800 if (!STRINGP(directory
))
6803 filelist
= Fdirectory_files (directory
, Qt
,
6804 build_string (".*\\.[bB][dD][fF]"), Qt
);
6806 for ( ; CONSP(filelist
); filelist
= XCDR (filelist
))
6808 Lisp_Object filename
= XCAR (filelist
);
6809 if (w32_BDF_to_x_font (XSTRING (filename
)->data
, fontname
, 100))
6810 store_in_alist (&list
, build_string (fontname
), filename
);
6816 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
6817 "Internal function called by `color-defined-p', which see.")
6819 Lisp_Object color
, frame
;
6822 FRAME_PTR f
= check_x_frame (frame
);
6824 CHECK_STRING (color
, 1);
6826 if (w32_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
6832 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
6833 "Internal function called by `color-values', which see.")
6835 Lisp_Object color
, frame
;
6838 FRAME_PTR f
= check_x_frame (frame
);
6840 CHECK_STRING (color
, 1);
6842 if (w32_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
6846 rgb
[0] = make_number ((GetRValue (foo
.pixel
) << 8)
6847 | GetRValue (foo
.pixel
));
6848 rgb
[1] = make_number ((GetGValue (foo
.pixel
) << 8)
6849 | GetGValue (foo
.pixel
));
6850 rgb
[2] = make_number ((GetBValue (foo
.pixel
) << 8)
6851 | GetBValue (foo
.pixel
));
6852 return Flist (3, rgb
);
6858 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
6859 "Internal function called by `display-color-p', which see.")
6861 Lisp_Object display
;
6863 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6865 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
6871 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
6873 "Return t if the X display supports shades of gray.\n\
6874 Note that color displays do support shades of gray.\n\
6875 The optional argument DISPLAY specifies which display to ask about.\n\
6876 DISPLAY should be either a frame or a display name (a string).\n\
6877 If omitted or nil, that stands for the selected frame's display.")
6879 Lisp_Object display
;
6881 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6883 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
6889 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
6891 "Returns the width in pixels of the X display DISPLAY.\n\
6892 The optional argument DISPLAY specifies which display to ask about.\n\
6893 DISPLAY should be either a frame or a display name (a string).\n\
6894 If omitted or nil, that stands for the selected frame's display.")
6896 Lisp_Object display
;
6898 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6900 return make_number (dpyinfo
->width
);
6903 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
6904 Sx_display_pixel_height
, 0, 1, 0,
6905 "Returns the height in pixels of the X display DISPLAY.\n\
6906 The optional argument DISPLAY specifies which display to ask about.\n\
6907 DISPLAY should be either a frame or a display name (a string).\n\
6908 If omitted or nil, that stands for the selected frame's display.")
6910 Lisp_Object display
;
6912 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6914 return make_number (dpyinfo
->height
);
6917 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
6919 "Returns the number of bitplanes of the display DISPLAY.\n\
6920 The optional argument DISPLAY specifies which display to ask about.\n\
6921 DISPLAY should be either a frame or a display name (a string).\n\
6922 If omitted or nil, that stands for the selected frame's display.")
6924 Lisp_Object display
;
6926 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6928 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
6931 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
6933 "Returns the number of color cells of the display DISPLAY.\n\
6934 The optional argument DISPLAY specifies which display to ask about.\n\
6935 DISPLAY should be either a frame or a display name (a string).\n\
6936 If omitted or nil, that stands for the selected frame's display.")
6938 Lisp_Object display
;
6940 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6944 hdc
= GetDC (dpyinfo
->root_window
);
6945 if (dpyinfo
->has_palette
)
6946 cap
= GetDeviceCaps (hdc
,SIZEPALETTE
);
6948 cap
= GetDeviceCaps (hdc
,NUMCOLORS
);
6950 ReleaseDC (dpyinfo
->root_window
, hdc
);
6952 return make_number (cap
);
6955 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
6956 Sx_server_max_request_size
,
6958 "Returns the maximum request size of the server of display DISPLAY.\n\
6959 The optional argument DISPLAY specifies which display to ask about.\n\
6960 DISPLAY should be either a frame or a display name (a string).\n\
6961 If omitted or nil, that stands for the selected frame's display.")
6963 Lisp_Object display
;
6965 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6967 return make_number (1);
6970 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
6971 "Returns the vendor ID string of the W32 system (Microsoft).\n\
6972 The optional argument DISPLAY specifies which display to ask about.\n\
6973 DISPLAY should be either a frame or a display name (a string).\n\
6974 If omitted or nil, that stands for the selected frame's display.")
6976 Lisp_Object display
;
6978 return build_string ("Microsoft Corp.");
6981 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
6982 "Returns the version numbers of the server of display DISPLAY.\n\
6983 The value is a list of three integers: the major and minor\n\
6984 version numbers, and the vendor-specific release\n\
6985 number. See also the function `x-server-vendor'.\n\n\
6986 The optional argument DISPLAY specifies which display to ask about.\n\
6987 DISPLAY should be either a frame or a display name (a string).\n\
6988 If omitted or nil, that stands for the selected frame's display.")
6990 Lisp_Object display
;
6992 return Fcons (make_number (w32_major_version
),
6993 Fcons (make_number (w32_minor_version
), Qnil
));
6996 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
6997 "Returns the number of screens on the server of display DISPLAY.\n\
6998 The optional argument DISPLAY specifies which display to ask about.\n\
6999 DISPLAY should be either a frame or a display name (a string).\n\
7000 If omitted or nil, that stands for the selected frame's display.")
7002 Lisp_Object display
;
7004 return make_number (1);
7007 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
7008 "Returns the height in millimeters of the X display DISPLAY.\n\
7009 The optional argument DISPLAY specifies which display to ask about.\n\
7010 DISPLAY should be either a frame or a display name (a string).\n\
7011 If omitted or nil, that stands for the selected frame's display.")
7013 Lisp_Object display
;
7015 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
7019 hdc
= GetDC (dpyinfo
->root_window
);
7021 cap
= GetDeviceCaps (hdc
, VERTSIZE
);
7023 ReleaseDC (dpyinfo
->root_window
, hdc
);
7025 return make_number (cap
);
7028 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
7029 "Returns the width in millimeters of the X display DISPLAY.\n\
7030 The optional argument DISPLAY specifies which display to ask about.\n\
7031 DISPLAY should be either a frame or a display name (a string).\n\
7032 If omitted or nil, that stands for the selected frame's display.")
7034 Lisp_Object display
;
7036 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
7041 hdc
= GetDC (dpyinfo
->root_window
);
7043 cap
= GetDeviceCaps (hdc
, HORZSIZE
);
7045 ReleaseDC (dpyinfo
->root_window
, hdc
);
7047 return make_number (cap
);
7050 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
7051 Sx_display_backing_store
, 0, 1, 0,
7052 "Returns an indication of whether display DISPLAY does backing store.\n\
7053 The value may be `always', `when-mapped', or `not-useful'.\n\
7054 The optional argument DISPLAY specifies which display to ask about.\n\
7055 DISPLAY should be either a frame or a display name (a string).\n\
7056 If omitted or nil, that stands for the selected frame's display.")
7058 Lisp_Object display
;
7060 return intern ("not-useful");
7063 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
7064 Sx_display_visual_class
, 0, 1, 0,
7065 "Returns the visual class of the display DISPLAY.\n\
7066 The value is one of the symbols `static-gray', `gray-scale',\n\
7067 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
7068 The optional argument DISPLAY specifies which display to ask about.\n\
7069 DISPLAY should be either a frame or a display name (a string).\n\
7070 If omitted or nil, that stands for the selected frame's display.")
7072 Lisp_Object display
;
7074 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
7077 switch (dpyinfo
->visual
->class)
7079 case StaticGray
: return (intern ("static-gray"));
7080 case GrayScale
: return (intern ("gray-scale"));
7081 case StaticColor
: return (intern ("static-color"));
7082 case PseudoColor
: return (intern ("pseudo-color"));
7083 case TrueColor
: return (intern ("true-color"));
7084 case DirectColor
: return (intern ("direct-color"));
7086 error ("Display has an unknown visual class");
7090 error ("Display has an unknown visual class");
7093 DEFUN ("x-display-save-under", Fx_display_save_under
,
7094 Sx_display_save_under
, 0, 1, 0,
7095 "Returns t if the display DISPLAY supports the save-under feature.\n\
7096 The optional argument DISPLAY specifies which display to ask about.\n\
7097 DISPLAY should be either a frame or a display name (a string).\n\
7098 If omitted or nil, that stands for the selected frame's display.")
7100 Lisp_Object display
;
7107 register struct frame
*f
;
7109 return PIXEL_WIDTH (f
);
7114 register struct frame
*f
;
7116 return PIXEL_HEIGHT (f
);
7121 register struct frame
*f
;
7123 return FONT_WIDTH (f
->output_data
.w32
->font
);
7128 register struct frame
*f
;
7130 return f
->output_data
.w32
->line_height
;
7135 register struct frame
*f
;
7137 return FRAME_W32_DISPLAY_INFO (f
)->n_planes
;
7140 /* Return the display structure for the display named NAME.
7141 Open a new connection if necessary. */
7143 struct w32_display_info
*
7144 x_display_info_for_name (name
)
7148 struct w32_display_info
*dpyinfo
;
7150 CHECK_STRING (name
, 0);
7152 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
7154 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
7157 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
7162 /* Use this general default value to start with. */
7163 Vx_resource_name
= Vinvocation_name
;
7165 validate_x_resource_name ();
7167 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
7168 (char *) XSTRING (Vx_resource_name
)->data
);
7171 error ("Cannot connect to server %s", XSTRING (name
)->data
);
7174 XSETFASTINT (Vwindow_system_version
, 3);
7179 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
7180 1, 3, 0, "Open a connection to a server.\n\
7181 DISPLAY is the name of the display to connect to.\n\
7182 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
7183 If the optional third arg MUST-SUCCEED is non-nil,\n\
7184 terminate Emacs if we can't open the connection.")
7185 (display
, xrm_string
, must_succeed
)
7186 Lisp_Object display
, xrm_string
, must_succeed
;
7188 unsigned char *xrm_option
;
7189 struct w32_display_info
*dpyinfo
;
7191 CHECK_STRING (display
, 0);
7192 if (! NILP (xrm_string
))
7193 CHECK_STRING (xrm_string
, 1);
7195 if (! EQ (Vwindow_system
, intern ("w32")))
7196 error ("Not using Microsoft Windows");
7198 /* Allow color mapping to be defined externally; first look in user's
7199 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
7201 Lisp_Object color_file
;
7202 struct gcpro gcpro1
;
7204 color_file
= build_string("~/rgb.txt");
7206 GCPRO1 (color_file
);
7208 if (NILP (Ffile_readable_p (color_file
)))
7210 Fexpand_file_name (build_string ("rgb.txt"),
7211 Fsymbol_value (intern ("data-directory")));
7213 Vw32_color_map
= Fw32_load_color_file (color_file
);
7217 if (NILP (Vw32_color_map
))
7218 Vw32_color_map
= Fw32_default_color_map ();
7220 if (! NILP (xrm_string
))
7221 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
7223 xrm_option
= (unsigned char *) 0;
7225 /* Use this general default value to start with. */
7226 /* First remove .exe suffix from invocation-name - it looks ugly. */
7228 char basename
[ MAX_PATH
], *str
;
7230 strcpy (basename
, XSTRING (Vinvocation_name
)->data
);
7231 str
= strrchr (basename
, '.');
7233 Vinvocation_name
= build_string (basename
);
7235 Vx_resource_name
= Vinvocation_name
;
7237 validate_x_resource_name ();
7239 /* This is what opens the connection and sets x_current_display.
7240 This also initializes many symbols, such as those used for input. */
7241 dpyinfo
= w32_term_init (display
, xrm_option
,
7242 (char *) XSTRING (Vx_resource_name
)->data
);
7246 if (!NILP (must_succeed
))
7247 fatal ("Cannot connect to server %s.\n",
7248 XSTRING (display
)->data
);
7250 error ("Cannot connect to server %s", XSTRING (display
)->data
);
7255 XSETFASTINT (Vwindow_system_version
, 3);
7259 DEFUN ("x-close-connection", Fx_close_connection
,
7260 Sx_close_connection
, 1, 1, 0,
7261 "Close the connection to DISPLAY's server.\n\
7262 For DISPLAY, specify either a frame or a display name (a string).\n\
7263 If DISPLAY is nil, that stands for the selected frame's display.")
7265 Lisp_Object display
;
7267 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
7270 if (dpyinfo
->reference_count
> 0)
7271 error ("Display still has frames on it");
7274 /* Free the fonts in the font table. */
7275 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7276 if (dpyinfo
->font_table
[i
].name
)
7278 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
7279 xfree (dpyinfo
->font_table
[i
].full_name
);
7280 xfree (dpyinfo
->font_table
[i
].name
);
7281 w32_unload_font (dpyinfo
, dpyinfo
->font_table
[i
].font
);
7283 x_destroy_all_bitmaps (dpyinfo
);
7285 x_delete_display (dpyinfo
);
7291 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
7292 "Return the list of display names that Emacs has connections to.")
7295 Lisp_Object tail
, result
;
7298 for (tail
= w32_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
7299 result
= Fcons (XCAR (XCAR (tail
)), result
);
7304 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
7305 "If ON is non-nil, report errors as soon as the erring request is made.\n\
7306 If ON is nil, allow buffering of requests.\n\
7307 This is a noop on W32 systems.\n\
7308 The optional second argument DISPLAY specifies which display to act on.\n\
7309 DISPLAY should be either a frame or a display name (a string).\n\
7310 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
7312 Lisp_Object display
, on
;
7319 /***********************************************************************
7321 ***********************************************************************/
7323 /* Value is the number of elements of vector VECTOR. */
7325 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
7327 /* List of supported image types. Use define_image_type to add new
7328 types. Use lookup_image_type to find a type for a given symbol. */
7330 static struct image_type
*image_types
;
7332 /* The symbol `image' which is the car of the lists used to represent
7335 extern Lisp_Object Qimage
;
7337 /* The symbol `xbm' which is used as the type symbol for XBM images. */
7343 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
7344 extern Lisp_Object QCdata
;
7345 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
7346 Lisp_Object QCalgorithm
, QCcolor_symbols
, QCheuristic_mask
;
7347 Lisp_Object QCindex
;
7349 /* Other symbols. */
7351 Lisp_Object Qlaplace
;
7353 /* Time in seconds after which images should be removed from the cache
7354 if not displayed. */
7356 Lisp_Object Vimage_cache_eviction_delay
;
7358 /* Function prototypes. */
7360 static void define_image_type
P_ ((struct image_type
*type
));
7361 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
7362 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
7363 static void x_laplace
P_ ((struct frame
*, struct image
*));
7364 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
7368 /* Define a new image type from TYPE. This adds a copy of TYPE to
7369 image_types and adds the symbol *TYPE->type to Vimage_types. */
7372 define_image_type (type
)
7373 struct image_type
*type
;
7375 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
7376 The initialized data segment is read-only. */
7377 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
7378 bcopy (type
, p
, sizeof *p
);
7379 p
->next
= image_types
;
7381 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
7385 /* Look up image type SYMBOL, and return a pointer to its image_type
7386 structure. Value is null if SYMBOL is not a known image type. */
7388 static INLINE
struct image_type
*
7389 lookup_image_type (symbol
)
7392 struct image_type
*type
;
7394 for (type
= image_types
; type
; type
= type
->next
)
7395 if (EQ (symbol
, *type
->type
))
7402 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
7403 valid image specification is a list whose car is the symbol
7404 `image', and whose rest is a property list. The property list must
7405 contain a value for key `:type'. That value must be the name of a
7406 supported image type. The rest of the property list depends on the
7410 valid_image_p (object
)
7415 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
7417 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
7418 struct image_type
*type
= lookup_image_type (symbol
);
7421 valid_p
= type
->valid_p (object
);
7428 /* Log error message with format string FORMAT and argument ARG.
7429 Signaling an error, e.g. when an image cannot be loaded, is not a
7430 good idea because this would interrupt redisplay, and the error
7431 message display would lead to another redisplay. This function
7432 therefore simply displays a message. */
7435 image_error (format
, arg1
, arg2
)
7437 Lisp_Object arg1
, arg2
;
7439 add_to_log (format
, arg1
, arg2
);
7444 /***********************************************************************
7445 Image specifications
7446 ***********************************************************************/
7448 enum image_value_type
7450 IMAGE_DONT_CHECK_VALUE_TYPE
,
7453 IMAGE_POSITIVE_INTEGER_VALUE
,
7454 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
7456 IMAGE_INTEGER_VALUE
,
7457 IMAGE_FUNCTION_VALUE
,
7462 /* Structure used when parsing image specifications. */
7464 struct image_keyword
7466 /* Name of keyword. */
7469 /* The type of value allowed. */
7470 enum image_value_type type
;
7472 /* Non-zero means key must be present. */
7475 /* Used to recognize duplicate keywords in a property list. */
7478 /* The value that was found. */
7483 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
7485 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
7488 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
7489 has the format (image KEYWORD VALUE ...). One of the keyword/
7490 value pairs must be `:type TYPE'. KEYWORDS is a vector of
7491 image_keywords structures of size NKEYWORDS describing other
7492 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
7495 parse_image_spec (spec
, keywords
, nkeywords
, type
)
7497 struct image_keyword
*keywords
;
7504 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
7507 plist
= XCDR (spec
);
7508 while (CONSP (plist
))
7510 Lisp_Object key
, value
;
7512 /* First element of a pair must be a symbol. */
7514 plist
= XCDR (plist
);
7518 /* There must follow a value. */
7521 value
= XCAR (plist
);
7522 plist
= XCDR (plist
);
7524 /* Find key in KEYWORDS. Error if not found. */
7525 for (i
= 0; i
< nkeywords
; ++i
)
7526 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
7532 /* Record that we recognized the keyword. If a keywords
7533 was found more than once, it's an error. */
7534 keywords
[i
].value
= value
;
7535 ++keywords
[i
].count
;
7537 if (keywords
[i
].count
> 1)
7540 /* Check type of value against allowed type. */
7541 switch (keywords
[i
].type
)
7543 case IMAGE_STRING_VALUE
:
7544 if (!STRINGP (value
))
7548 case IMAGE_SYMBOL_VALUE
:
7549 if (!SYMBOLP (value
))
7553 case IMAGE_POSITIVE_INTEGER_VALUE
:
7554 if (!INTEGERP (value
) || XINT (value
) <= 0)
7558 case IMAGE_ASCENT_VALUE
:
7559 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
7561 else if (INTEGERP (value
)
7562 && XINT (value
) >= 0
7563 && XINT (value
) <= 100)
7567 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
7568 if (!INTEGERP (value
) || XINT (value
) < 0)
7572 case IMAGE_DONT_CHECK_VALUE_TYPE
:
7575 case IMAGE_FUNCTION_VALUE
:
7576 value
= indirect_function (value
);
7578 || COMPILEDP (value
)
7579 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
7583 case IMAGE_NUMBER_VALUE
:
7584 if (!INTEGERP (value
) && !FLOATP (value
))
7588 case IMAGE_INTEGER_VALUE
:
7589 if (!INTEGERP (value
))
7593 case IMAGE_BOOL_VALUE
:
7594 if (!NILP (value
) && !EQ (value
, Qt
))
7603 if (EQ (key
, QCtype
) && !EQ (type
, value
))
7607 /* Check that all mandatory fields are present. */
7608 for (i
= 0; i
< nkeywords
; ++i
)
7609 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
7612 return NILP (plist
);
7616 /* Return the value of KEY in image specification SPEC. Value is nil
7617 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
7618 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
7621 image_spec_value (spec
, key
, found
)
7622 Lisp_Object spec
, key
;
7627 xassert (valid_image_p (spec
));
7629 for (tail
= XCDR (spec
);
7630 CONSP (tail
) && CONSP (XCDR (tail
));
7631 tail
= XCDR (XCDR (tail
)))
7633 if (EQ (XCAR (tail
), key
))
7637 return XCAR (XCDR (tail
));
7649 /***********************************************************************
7650 Image type independent image structures
7651 ***********************************************************************/
7653 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
7654 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
7657 /* Allocate and return a new image structure for image specification
7658 SPEC. SPEC has a hash value of HASH. */
7660 static struct image
*
7661 make_image (spec
, hash
)
7665 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
7667 xassert (valid_image_p (spec
));
7668 bzero (img
, sizeof *img
);
7669 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
7670 xassert (img
->type
!= NULL
);
7672 img
->data
.lisp_val
= Qnil
;
7673 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
7679 /* Free image IMG which was used on frame F, including its resources. */
7688 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7690 /* Remove IMG from the hash table of its cache. */
7692 img
->prev
->next
= img
->next
;
7694 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
7697 img
->next
->prev
= img
->prev
;
7699 c
->images
[img
->id
] = NULL
;
7701 /* Free resources, then free IMG. */
7702 img
->type
->free (f
, img
);
7708 /* Prepare image IMG for display on frame F. Must be called before
7709 drawing an image. */
7712 prepare_image_for_display (f
, img
)
7718 /* We're about to display IMG, so set its timestamp to `now'. */
7720 img
->timestamp
= EMACS_SECS (t
);
7722 /* If IMG doesn't have a pixmap yet, load it now, using the image
7723 type dependent loader function. */
7724 if (img
->pixmap
== 0 && !img
->load_failed_p
)
7725 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
7729 /* Value is the number of pixels for the ascent of image IMG when
7730 drawn in face FACE. */
7733 image_ascent (img
, face
)
7737 int height
= img
->height
+ img
->margin
;
7740 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
7743 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
7744 - FONT_BASE(face
->font
)) / 2;
7746 ascent
= height
/ 2;
7749 ascent
= height
* img
->ascent
/ 100.0;
7756 /***********************************************************************
7757 Helper functions for X image types
7758 ***********************************************************************/
7760 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7761 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
7763 Lisp_Object color_name
,
7764 unsigned long dflt
));
7766 /* Free X resources of image IMG which is used on frame F. */
7769 x_clear_image (f
, img
)
7773 #if 0 /* NTEMACS_TODO: W32 image support */
7778 XFreePixmap (NULL
, img
->pixmap
);
7785 int class = FRAME_W32_DISPLAY_INFO (f
)->visual
->class;
7787 /* If display has an immutable color map, freeing colors is not
7788 necessary and some servers don't allow it. So don't do it. */
7789 if (class != StaticColor
7790 && class != StaticGray
7791 && class != TrueColor
)
7795 cmap
= DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f
)->screen
);
7796 XFreeColors (FRAME_W32_DISPLAY (f
), cmap
, img
->colors
,
7801 xfree (img
->colors
);
7809 /* Allocate color COLOR_NAME for image IMG on frame F. If color
7810 cannot be allocated, use DFLT. Add a newly allocated color to
7811 IMG->colors, so that it can be freed again. Value is the pixel
7814 static unsigned long
7815 x_alloc_image_color (f
, img
, color_name
, dflt
)
7818 Lisp_Object color_name
;
7821 #if 0 /* NTEMACS_TODO: allocing colors. */
7823 unsigned long result
;
7825 xassert (STRINGP (color_name
));
7827 if (w32_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
7829 /* This isn't called frequently so we get away with simply
7830 reallocating the color vector to the needed size, here. */
7833 (unsigned long *) xrealloc (img
->colors
,
7834 img
->ncolors
* sizeof *img
->colors
);
7835 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
7836 result
= color
.pixel
;
7847 /***********************************************************************
7849 ***********************************************************************/
7851 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
7854 /* Return a new, initialized image cache that is allocated from the
7855 heap. Call free_image_cache to free an image cache. */
7857 struct image_cache
*
7860 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
7863 bzero (c
, sizeof *c
);
7865 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
7866 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
7867 c
->buckets
= (struct image
**) xmalloc (size
);
7868 bzero (c
->buckets
, size
);
7873 /* Free image cache of frame F. Be aware that X frames share images
7877 free_image_cache (f
)
7880 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7885 /* Cache should not be referenced by any frame when freed. */
7886 xassert (c
->refcount
== 0);
7888 for (i
= 0; i
< c
->used
; ++i
)
7889 free_image (f
, c
->images
[i
]);
7893 FRAME_X_IMAGE_CACHE (f
) = NULL
;
7898 /* Clear image cache of frame F. FORCE_P non-zero means free all
7899 images. FORCE_P zero means clear only images that haven't been
7900 displayed for some time. Should be called from time to time to
7901 reduce the number of loaded images. If image-eviction-seconds is
7902 non-nil, this frees images in the cache which weren't displayed for
7903 at least that many seconds. */
7906 clear_image_cache (f
, force_p
)
7910 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7912 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
7916 int i
, any_freed_p
= 0;
7919 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
7921 for (i
= 0; i
< c
->used
; ++i
)
7923 struct image
*img
= c
->images
[i
];
7926 || (img
->timestamp
> old
)))
7928 free_image (f
, img
);
7933 /* We may be clearing the image cache because, for example,
7934 Emacs was iconified for a longer period of time. In that
7935 case, current matrices may still contain references to
7936 images freed above. So, clear these matrices. */
7939 clear_current_matrices (f
);
7940 ++windows_or_buffers_changed
;
7946 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
7948 "Clear the image cache of FRAME.\n\
7949 FRAME nil or omitted means use the selected frame.\n\
7950 FRAME t means clear the image caches of all frames.")
7958 FOR_EACH_FRAME (tail
, frame
)
7959 if (FRAME_W32_P (XFRAME (frame
)))
7960 clear_image_cache (XFRAME (frame
), 1);
7963 clear_image_cache (check_x_frame (frame
), 1);
7969 /* Return the id of image with Lisp specification SPEC on frame F.
7970 SPEC must be a valid Lisp image specification (see valid_image_p). */
7973 lookup_image (f
, spec
)
7977 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7981 struct gcpro gcpro1
;
7984 /* F must be a window-system frame, and SPEC must be a valid image
7986 xassert (FRAME_WINDOW_P (f
));
7987 xassert (valid_image_p (spec
));
7991 /* Look up SPEC in the hash table of the image cache. */
7992 hash
= sxhash (spec
, 0);
7993 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
7995 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
7996 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
7999 /* If not found, create a new image and cache it. */
8002 img
= make_image (spec
, hash
);
8003 cache_image (f
, img
);
8004 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
8005 xassert (!interrupt_input_blocked
);
8007 /* If we can't load the image, and we don't have a width and
8008 height, use some arbitrary width and height so that we can
8009 draw a rectangle for it. */
8010 if (img
->load_failed_p
)
8014 value
= image_spec_value (spec
, QCwidth
, NULL
);
8015 img
->width
= (INTEGERP (value
)
8016 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
8017 value
= image_spec_value (spec
, QCheight
, NULL
);
8018 img
->height
= (INTEGERP (value
)
8019 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
8023 /* Handle image type independent image attributes
8024 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
8025 Lisp_Object ascent
, margin
, relief
, algorithm
, heuristic_mask
;
8028 ascent
= image_spec_value (spec
, QCascent
, NULL
);
8029 if (INTEGERP (ascent
))
8030 img
->ascent
= XFASTINT (ascent
);
8031 else if (EQ (ascent
, Qcenter
))
8032 img
->ascent
= CENTERED_IMAGE_ASCENT
;
8034 margin
= image_spec_value (spec
, QCmargin
, NULL
);
8035 if (INTEGERP (margin
) && XINT (margin
) >= 0)
8036 img
->margin
= XFASTINT (margin
);
8038 relief
= image_spec_value (spec
, QCrelief
, NULL
);
8039 if (INTEGERP (relief
))
8041 img
->relief
= XINT (relief
);
8042 img
->margin
+= abs (img
->relief
);
8045 /* Should we apply a Laplace edge-detection algorithm? */
8046 algorithm
= image_spec_value (spec
, QCalgorithm
, NULL
);
8047 if (img
->pixmap
&& EQ (algorithm
, Qlaplace
))
8050 /* Should we built a mask heuristically? */
8051 heuristic_mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
8052 if (img
->pixmap
&& !img
->mask
&& !NILP (heuristic_mask
))
8053 x_build_heuristic_mask (f
, img
, heuristic_mask
);
8057 /* We're using IMG, so set its timestamp to `now'. */
8058 EMACS_GET_TIME (now
);
8059 img
->timestamp
= EMACS_SECS (now
);
8063 /* Value is the image id. */
8068 /* Cache image IMG in the image cache of frame F. */
8071 cache_image (f
, img
)
8075 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8078 /* Find a free slot in c->images. */
8079 for (i
= 0; i
< c
->used
; ++i
)
8080 if (c
->images
[i
] == NULL
)
8083 /* If no free slot found, maybe enlarge c->images. */
8084 if (i
== c
->used
&& c
->used
== c
->size
)
8087 c
->images
= (struct image
**) xrealloc (c
->images
,
8088 c
->size
* sizeof *c
->images
);
8091 /* Add IMG to c->images, and assign IMG an id. */
8097 /* Add IMG to the cache's hash table. */
8098 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
8099 img
->next
= c
->buckets
[i
];
8101 img
->next
->prev
= img
;
8103 c
->buckets
[i
] = img
;
8107 /* Call FN on every image in the image cache of frame F. Used to mark
8108 Lisp Objects in the image cache. */
8111 forall_images_in_image_cache (f
, fn
)
8113 void (*fn
) P_ ((struct image
*img
));
8115 if (FRAME_LIVE_P (f
) && FRAME_W32_P (f
))
8117 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8121 for (i
= 0; i
< c
->used
; ++i
)
8130 /***********************************************************************
8132 ***********************************************************************/
8134 #if 0 /* NTEMACS_TODO: W32 specific image code. */
8136 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
8137 XImage
**, Pixmap
*));
8138 static void x_destroy_x_image
P_ ((XImage
*));
8139 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
8142 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
8143 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
8144 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
8145 via xmalloc. Print error messages via image_error if an error
8146 occurs. Value is non-zero if successful. */
8149 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
8151 int width
, height
, depth
;
8155 #if 0 /* NTEMACS_TODO: Image support for W32 */
8156 Display
*display
= FRAME_W32_DISPLAY (f
);
8157 Screen
*screen
= FRAME_X_SCREEN (f
);
8158 Window window
= FRAME_W32_WINDOW (f
);
8160 xassert (interrupt_input_blocked
);
8163 depth
= DefaultDepthOfScreen (screen
);
8164 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
8165 depth
, ZPixmap
, 0, NULL
, width
, height
,
8166 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
8169 image_error ("Unable to allocate X image", Qnil
, Qnil
);
8173 /* Allocate image raster. */
8174 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
8176 /* Allocate a pixmap of the same size. */
8177 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
8180 x_destroy_x_image (*ximg
);
8182 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
8190 /* Destroy XImage XIMG. Free XIMG->data. */
8193 x_destroy_x_image (ximg
)
8196 xassert (interrupt_input_blocked
);
8201 XDestroyImage (ximg
);
8206 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
8207 are width and height of both the image and pixmap. */
8210 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
8217 xassert (interrupt_input_blocked
);
8218 gc
= XCreateGC (NULL
, pixmap
, 0, NULL
);
8219 XPutImage (NULL
, pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
8226 /***********************************************************************
8228 ***********************************************************************/
8230 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
8232 /* Find image file FILE. Look in data-directory, then
8233 x-bitmap-file-path. Value is the full name of the file found, or
8234 nil if not found. */
8237 x_find_image_file (file
)
8240 Lisp_Object file_found
, search_path
;
8241 struct gcpro gcpro1
, gcpro2
;
8245 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
8246 GCPRO2 (file_found
, search_path
);
8248 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
8249 fd
= openp (search_path
, file
, "", &file_found
, 0);
8262 /***********************************************************************
8264 ***********************************************************************/
8266 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
8267 static int xbm_load_image_from_file
P_ ((struct frame
*f
, struct image
*img
,
8269 static int xbm_image_p
P_ ((Lisp_Object object
));
8270 static int xbm_read_bitmap_file_data
P_ ((char *, int *, int *,
8274 /* Indices of image specification fields in xbm_format, below. */
8276 enum xbm_keyword_index
8293 /* Vector of image_keyword structures describing the format
8294 of valid XBM image specifications. */
8296 static struct image_keyword xbm_format
[XBM_LAST
] =
8298 {":type", IMAGE_SYMBOL_VALUE
, 1},
8299 {":file", IMAGE_STRING_VALUE
, 0},
8300 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8301 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8302 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8303 {":foreground", IMAGE_STRING_VALUE
, 0},
8304 {":background", IMAGE_STRING_VALUE
, 0},
8305 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8306 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8307 {":relief", IMAGE_INTEGER_VALUE
, 0},
8308 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8309 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8312 /* Structure describing the image type XBM. */
8314 static struct image_type xbm_type
=
8323 /* Tokens returned from xbm_scan. */
8332 /* Return non-zero if OBJECT is a valid XBM-type image specification.
8333 A valid specification is a list starting with the symbol `image'
8334 The rest of the list is a property list which must contain an
8337 If the specification specifies a file to load, it must contain
8338 an entry `:file FILENAME' where FILENAME is a string.
8340 If the specification is for a bitmap loaded from memory it must
8341 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
8342 WIDTH and HEIGHT are integers > 0. DATA may be:
8344 1. a string large enough to hold the bitmap data, i.e. it must
8345 have a size >= (WIDTH + 7) / 8 * HEIGHT
8347 2. a bool-vector of size >= WIDTH * HEIGHT
8349 3. a vector of strings or bool-vectors, one for each line of the
8352 Both the file and data forms may contain the additional entries
8353 `:background COLOR' and `:foreground COLOR'. If not present,
8354 foreground and background of the frame on which the image is
8355 displayed, is used. */
8358 xbm_image_p (object
)
8361 struct image_keyword kw
[XBM_LAST
];
8363 bcopy (xbm_format
, kw
, sizeof kw
);
8364 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
8367 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
8369 if (kw
[XBM_FILE
].count
)
8371 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
8379 /* Entries for `:width', `:height' and `:data' must be present. */
8380 if (!kw
[XBM_WIDTH
].count
8381 || !kw
[XBM_HEIGHT
].count
8382 || !kw
[XBM_DATA
].count
)
8385 data
= kw
[XBM_DATA
].value
;
8386 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
8387 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
8389 /* Check type of data, and width and height against contents of
8395 /* Number of elements of the vector must be >= height. */
8396 if (XVECTOR (data
)->size
< height
)
8399 /* Each string or bool-vector in data must be large enough
8400 for one line of the image. */
8401 for (i
= 0; i
< height
; ++i
)
8403 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
8407 if (XSTRING (elt
)->size
8408 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
8411 else if (BOOL_VECTOR_P (elt
))
8413 if (XBOOL_VECTOR (elt
)->size
< width
)
8420 else if (STRINGP (data
))
8422 if (XSTRING (data
)->size
8423 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
8426 else if (BOOL_VECTOR_P (data
))
8428 if (XBOOL_VECTOR (data
)->size
< width
* height
)
8435 /* Baseline must be a value between 0 and 100 (a percentage). */
8436 if (kw
[XBM_ASCENT
].count
8437 && XFASTINT (kw
[XBM_ASCENT
].value
) > 100)
8444 /* Scan a bitmap file. FP is the stream to read from. Value is
8445 either an enumerator from enum xbm_token, or a character for a
8446 single-character token, or 0 at end of file. If scanning an
8447 identifier, store the lexeme of the identifier in SVAL. If
8448 scanning a number, store its value in *IVAL. */
8451 xbm_scan (fp
, sval
, ival
)
8458 /* Skip white space. */
8459 while ((c
= fgetc (fp
)) != EOF
&& isspace (c
))
8464 else if (isdigit (c
))
8466 int value
= 0, digit
;
8471 if (c
== 'x' || c
== 'X')
8473 while ((c
= fgetc (fp
)) != EOF
)
8477 else if (c
>= 'a' && c
<= 'f')
8478 digit
= c
- 'a' + 10;
8479 else if (c
>= 'A' && c
<= 'F')
8480 digit
= c
- 'A' + 10;
8483 value
= 16 * value
+ digit
;
8486 else if (isdigit (c
))
8489 while ((c
= fgetc (fp
)) != EOF
8491 value
= 8 * value
+ c
- '0';
8497 while ((c
= fgetc (fp
)) != EOF
8499 value
= 10 * value
+ c
- '0';
8507 else if (isalpha (c
) || c
== '_')
8510 while ((c
= fgetc (fp
)) != EOF
8511 && (isalnum (c
) || c
== '_'))
8523 /* Replacement for XReadBitmapFileData which isn't available under old
8524 X versions. FILE is the name of the bitmap file to read. Set
8525 *WIDTH and *HEIGHT to the width and height of the image. Return in
8526 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
8530 xbm_read_bitmap_file_data (file
, width
, height
, data
)
8532 int *width
, *height
;
8533 unsigned char **data
;
8536 char buffer
[BUFSIZ
];
8539 int bytes_per_line
, i
, nbytes
;
8545 LA1 = xbm_scan (fp, buffer, &value)
8547 #define expect(TOKEN) \
8548 if (LA1 != (TOKEN)) \
8553 #define expect_ident(IDENT) \
8554 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
8559 fp
= fopen (file
, "r");
8563 *width
= *height
= -1;
8565 LA1
= xbm_scan (fp
, buffer
, &value
);
8567 /* Parse defines for width, height and hot-spots. */
8571 expect_ident ("define");
8572 expect (XBM_TK_IDENT
);
8574 if (LA1
== XBM_TK_NUMBER
);
8576 char *p
= strrchr (buffer
, '_');
8577 p
= p
? p
+ 1 : buffer
;
8578 if (strcmp (p
, "width") == 0)
8580 else if (strcmp (p
, "height") == 0)
8583 expect (XBM_TK_NUMBER
);
8586 if (*width
< 0 || *height
< 0)
8589 /* Parse bits. Must start with `static'. */
8590 expect_ident ("static");
8591 if (LA1
== XBM_TK_IDENT
)
8593 if (strcmp (buffer
, "unsigned") == 0)
8596 expect_ident ("char");
8598 else if (strcmp (buffer
, "short") == 0)
8602 if (*width
% 16 && *width
% 16 < 9)
8605 else if (strcmp (buffer
, "char") == 0)
8613 expect (XBM_TK_IDENT
);
8619 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
8620 nbytes
= bytes_per_line
* *height
;
8621 p
= *data
= (char *) xmalloc (nbytes
);
8626 for (i
= 0; i
< nbytes
; i
+= 2)
8629 expect (XBM_TK_NUMBER
);
8632 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
8635 if (LA1
== ',' || LA1
== '}')
8643 for (i
= 0; i
< nbytes
; ++i
)
8646 expect (XBM_TK_NUMBER
);
8650 if (LA1
== ',' || LA1
== '}')
8676 /* Load XBM image IMG which will be displayed on frame F from file
8677 SPECIFIED_FILE. Value is non-zero if successful. */
8680 xbm_load_image_from_file (f
, img
, specified_file
)
8683 Lisp_Object specified_file
;
8686 unsigned char *data
;
8689 struct gcpro gcpro1
;
8691 xassert (STRINGP (specified_file
));
8695 file
= x_find_image_file (specified_file
);
8696 if (!STRINGP (file
))
8698 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8703 rc
= xbm_read_bitmap_file_data (XSTRING (file
)->data
, &img
->width
,
8704 &img
->height
, &data
);
8707 int depth
= one_w32_display_info
.n_cbits
;
8708 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
8709 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
8712 xassert (img
->width
> 0 && img
->height
> 0);
8714 /* Get foreground and background colors, maybe allocate colors. */
8715 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
8717 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
8719 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8721 background
= x_alloc_image_color (f
, img
, value
, background
);
8723 #if 0 /* NTEMACS_TODO : Port image display to W32 */
8726 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f
),
8727 FRAME_W32_WINDOW (f
),
8729 img
->width
, img
->height
,
8730 foreground
, background
,
8734 if (img
->pixmap
== 0)
8736 x_clear_image (f
, img
);
8737 image_error ("Unable to create X pixmap for `%s'", file
, Qnil
);
8746 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
8753 /* Fill image IMG which is used on frame F with pixmap data. Value is
8754 non-zero if successful. */
8762 Lisp_Object file_name
;
8764 xassert (xbm_image_p (img
->spec
));
8766 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8767 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
8768 if (STRINGP (file_name
))
8769 success_p
= xbm_load_image_from_file (f
, img
, file_name
);
8772 struct image_keyword fmt
[XBM_LAST
];
8775 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
8776 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
8780 /* Parse the list specification. */
8781 bcopy (xbm_format
, fmt
, sizeof fmt
);
8782 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
8785 /* Get specified width, and height. */
8786 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
8787 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
8788 xassert (img
->width
> 0 && img
->height
> 0);
8792 if (fmt
[XBM_ASCENT
].count
)
8793 img
->ascent
= XFASTINT (fmt
[XBM_ASCENT
].value
);
8795 /* Get foreground and background colors, maybe allocate colors. */
8796 if (fmt
[XBM_FOREGROUND
].count
)
8797 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
8799 if (fmt
[XBM_BACKGROUND
].count
)
8800 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
8803 /* Set bits to the bitmap image data. */
8804 data
= fmt
[XBM_DATA
].value
;
8809 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
8811 p
= bits
= (char *) alloca (nbytes
* img
->height
);
8812 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
8814 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
8816 bcopy (XSTRING (line
)->data
, p
, nbytes
);
8818 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
8821 else if (STRINGP (data
))
8822 bits
= XSTRING (data
)->data
;
8824 bits
= XBOOL_VECTOR (data
)->data
;
8826 #if 0 /* NTEMACS_TODO : W32 XPM code */
8827 /* Create the pixmap. */
8828 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
8830 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f
),
8831 FRAME_W32_WINDOW (f
),
8833 img
->width
, img
->height
,
8834 foreground
, background
,
8836 #endif /* NTEMACS_TODO */
8842 image_error ("Unable to create pixmap for XBM image `%s'",
8844 x_clear_image (f
, img
);
8855 /***********************************************************************
8857 ***********************************************************************/
8861 static int xpm_image_p
P_ ((Lisp_Object object
));
8862 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
8863 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
8865 #include "X11/xpm.h"
8867 /* The symbol `xpm' identifying XPM-format images. */
8871 /* Indices of image specification fields in xpm_format, below. */
8873 enum xpm_keyword_index
8887 /* Vector of image_keyword structures describing the format
8888 of valid XPM image specifications. */
8890 static struct image_keyword xpm_format
[XPM_LAST
] =
8892 {":type", IMAGE_SYMBOL_VALUE
, 1},
8893 {":file", IMAGE_STRING_VALUE
, 0},
8894 {":data", IMAGE_STRING_VALUE
, 0},
8895 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8896 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8897 {":relief", IMAGE_INTEGER_VALUE
, 0},
8898 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8899 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8900 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8903 /* Structure describing the image type XBM. */
8905 static struct image_type xpm_type
=
8915 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
8916 for XPM images. Such a list must consist of conses whose car and
8920 xpm_valid_color_symbols_p (color_symbols
)
8921 Lisp_Object color_symbols
;
8923 while (CONSP (color_symbols
))
8925 Lisp_Object sym
= XCAR (color_symbols
);
8927 || !STRINGP (XCAR (sym
))
8928 || !STRINGP (XCDR (sym
)))
8930 color_symbols
= XCDR (color_symbols
);
8933 return NILP (color_symbols
);
8937 /* Value is non-zero if OBJECT is a valid XPM image specification. */
8940 xpm_image_p (object
)
8943 struct image_keyword fmt
[XPM_LAST
];
8944 bcopy (xpm_format
, fmt
, sizeof fmt
);
8945 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
8946 /* Either `:file' or `:data' must be present. */
8947 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
8948 /* Either no `:color-symbols' or it's a list of conses
8949 whose car and cdr are strings. */
8950 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
8951 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
))
8952 && (fmt
[XPM_ASCENT
].count
== 0
8953 || XFASTINT (fmt
[XPM_ASCENT
].value
) < 100));
8957 /* Load image IMG which will be displayed on frame F. Value is
8958 non-zero if successful. */
8966 XpmAttributes attrs
;
8967 Lisp_Object specified_file
, color_symbols
;
8969 /* Configure the XPM lib. Use the visual of frame F. Allocate
8970 close colors. Return colors allocated. */
8971 bzero (&attrs
, sizeof attrs
);
8972 attrs
.visual
= FRAME_X_VISUAL (f
);
8973 attrs
.colormap
= FRAME_X_COLORMAP (f
);
8974 attrs
.valuemask
|= XpmVisual
;
8975 attrs
.valuemask
|= XpmColormap
;
8976 attrs
.valuemask
|= XpmReturnAllocPixels
;
8977 #ifdef XpmAllocCloseColors
8978 attrs
.alloc_close_colors
= 1;
8979 attrs
.valuemask
|= XpmAllocCloseColors
;
8981 attrs
.closeness
= 600;
8982 attrs
.valuemask
|= XpmCloseness
;
8985 /* If image specification contains symbolic color definitions, add
8986 these to `attrs'. */
8987 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
8988 if (CONSP (color_symbols
))
8991 XpmColorSymbol
*xpm_syms
;
8994 attrs
.valuemask
|= XpmColorSymbols
;
8996 /* Count number of symbols. */
8997 attrs
.numsymbols
= 0;
8998 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
9001 /* Allocate an XpmColorSymbol array. */
9002 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
9003 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
9004 bzero (xpm_syms
, size
);
9005 attrs
.colorsymbols
= xpm_syms
;
9007 /* Fill the color symbol array. */
9008 for (tail
= color_symbols
, i
= 0;
9010 ++i
, tail
= XCDR (tail
))
9012 Lisp_Object name
= XCAR (XCAR (tail
));
9013 Lisp_Object color
= XCDR (XCAR (tail
));
9014 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
9015 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
9016 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
9017 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
9021 /* Create a pixmap for the image, either from a file, or from a
9022 string buffer containing data in the same format as an XPM file. */
9024 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9025 if (STRINGP (specified_file
))
9027 Lisp_Object file
= x_find_image_file (specified_file
);
9028 if (!STRINGP (file
))
9030 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9035 rc
= XpmReadFileToPixmap (NULL
, FRAME_W32_WINDOW (f
),
9036 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
9041 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
9042 rc
= XpmCreatePixmapFromBuffer (NULL
, FRAME_W32_WINDOW (f
),
9043 XSTRING (buffer
)->data
,
9044 &img
->pixmap
, &img
->mask
,
9049 if (rc
== XpmSuccess
)
9051 /* Remember allocated colors. */
9052 img
->ncolors
= attrs
.nalloc_pixels
;
9053 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
9054 * sizeof *img
->colors
);
9055 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
9056 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
9058 img
->width
= attrs
.width
;
9059 img
->height
= attrs
.height
;
9060 xassert (img
->width
> 0 && img
->height
> 0);
9062 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
9064 XpmFreeAttributes (&attrs
);
9072 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
9075 case XpmFileInvalid
:
9076 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
9080 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
9083 case XpmColorFailed
:
9084 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
9088 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
9093 return rc
== XpmSuccess
;
9096 #endif /* HAVE_XPM != 0 */
9099 #if 0 /* NTEMACS_TODO : Color tables on W32. */
9100 /***********************************************************************
9102 ***********************************************************************/
9104 /* An entry in the color table mapping an RGB color to a pixel color. */
9109 unsigned long pixel
;
9111 /* Next in color table collision list. */
9112 struct ct_color
*next
;
9115 /* The bucket vector size to use. Must be prime. */
9119 /* Value is a hash of the RGB color given by R, G, and B. */
9121 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
9123 /* The color hash table. */
9125 struct ct_color
**ct_table
;
9127 /* Number of entries in the color table. */
9129 int ct_colors_allocated
;
9131 /* Function prototypes. */
9133 static void init_color_table
P_ ((void));
9134 static void free_color_table
P_ ((void));
9135 static unsigned long *colors_in_color_table
P_ ((int *n
));
9136 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
9137 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
9140 /* Initialize the color table. */
9145 int size
= CT_SIZE
* sizeof (*ct_table
);
9146 ct_table
= (struct ct_color
**) xmalloc (size
);
9147 bzero (ct_table
, size
);
9148 ct_colors_allocated
= 0;
9152 /* Free memory associated with the color table. */
9158 struct ct_color
*p
, *next
;
9160 for (i
= 0; i
< CT_SIZE
; ++i
)
9161 for (p
= ct_table
[i
]; p
; p
= next
)
9172 /* Value is a pixel color for RGB color R, G, B on frame F. If an
9173 entry for that color already is in the color table, return the
9174 pixel color of that entry. Otherwise, allocate a new color for R,
9175 G, B, and make an entry in the color table. */
9177 static unsigned long
9178 lookup_rgb_color (f
, r
, g
, b
)
9182 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
9183 int i
= hash
% CT_SIZE
;
9186 for (p
= ct_table
[i
]; p
; p
= p
->next
)
9187 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
9196 color
= PALETTERGB (r
, g
, b
);
9198 ++ct_colors_allocated
;
9200 p
= (struct ct_color
*) xmalloc (sizeof *p
);
9205 p
->next
= ct_table
[i
];
9213 /* Look up pixel color PIXEL which is used on frame F in the color
9214 table. If not already present, allocate it. Value is PIXEL. */
9216 static unsigned long
9217 lookup_pixel_color (f
, pixel
)
9219 unsigned long pixel
;
9221 int i
= pixel
% CT_SIZE
;
9224 for (p
= ct_table
[i
]; p
; p
= p
->next
)
9225 if (p
->pixel
== pixel
)
9236 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
9237 color
.pixel
= pixel
;
9238 XQueryColor (NULL
, cmap
, &color
);
9239 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
9244 ++ct_colors_allocated
;
9246 p
= (struct ct_color
*) xmalloc (sizeof *p
);
9251 p
->next
= ct_table
[i
];
9255 return FRAME_FOREGROUND_PIXEL (f
);
9261 /* Value is a vector of all pixel colors contained in the color table,
9262 allocated via xmalloc. Set *N to the number of colors. */
9264 static unsigned long *
9265 colors_in_color_table (n
)
9270 unsigned long *colors
;
9272 if (ct_colors_allocated
== 0)
9279 colors
= (unsigned long *) xmalloc (ct_colors_allocated
9281 *n
= ct_colors_allocated
;
9283 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
9284 for (p
= ct_table
[i
]; p
; p
= p
->next
)
9285 colors
[j
++] = p
->pixel
;
9291 #endif /* NTEMACS_TODO */
9294 /***********************************************************************
9296 ***********************************************************************/
9298 #if 0 /* NTEMACS_TODO : W32 versions of low level algorithms */
9299 static void x_laplace_write_row
P_ ((struct frame
*, long *,
9300 int, XImage
*, int));
9301 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
9302 XColor
*, int, XImage
*, int));
9305 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
9306 frame we operate on, CMAP is the color-map in effect, and WIDTH is
9307 the width of one row in the image. */
9310 x_laplace_read_row (f
, cmap
, colors
, width
, ximg
, y
)
9320 for (x
= 0; x
< width
; ++x
)
9321 colors
[x
].pixel
= XGetPixel (ximg
, x
, y
);
9323 XQueryColors (NULL
, cmap
, colors
, width
);
9327 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
9328 containing the pixel colors to write. F is the frame we are
9332 x_laplace_write_row (f
, pixels
, width
, ximg
, y
)
9341 for (x
= 0; x
< width
; ++x
)
9342 XPutPixel (ximg
, x
, y
, pixels
[x
]);
9346 /* Transform image IMG which is used on frame F with a Laplace
9347 edge-detection algorithm. The result is an image that can be used
9348 to draw disabled buttons, for example. */
9355 #if 0 /* NTEMACS_TODO : W32 version */
9356 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
9357 XImage
*ximg
, *oimg
;
9363 int in_y
, out_y
, rc
;
9368 /* Get the X image IMG->pixmap. */
9369 ximg
= XGetImage (NULL
, img
->pixmap
,
9370 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9372 /* Allocate 3 input rows, and one output row of colors. */
9373 for (i
= 0; i
< 3; ++i
)
9374 in
[i
] = (XColor
*) alloca (img
->width
* sizeof (XColor
));
9375 out
= (long *) alloca (img
->width
* sizeof (long));
9377 /* Create an X image for output. */
9378 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
9381 /* Fill first two rows. */
9382 x_laplace_read_row (f
, cmap
, in
[0], img
->width
, ximg
, 0);
9383 x_laplace_read_row (f
, cmap
, in
[1], img
->width
, ximg
, 1);
9386 /* Write first row, all zeros. */
9387 init_color_table ();
9388 pixel
= lookup_rgb_color (f
, 0, 0, 0);
9389 for (x
= 0; x
< img
->width
; ++x
)
9391 x_laplace_write_row (f
, out
, img
->width
, oimg
, 0);
9394 for (y
= 2; y
< img
->height
; ++y
)
9397 int rowb
= (y
+ 2) % 3;
9399 x_laplace_read_row (f
, cmap
, in
[rowa
], img
->width
, ximg
, in_y
++);
9401 for (x
= 0; x
< img
->width
- 2; ++x
)
9403 int r
= in
[rowa
][x
].red
+ mv2
- in
[rowb
][x
+ 2].red
;
9404 int g
= in
[rowa
][x
].green
+ mv2
- in
[rowb
][x
+ 2].green
;
9405 int b
= in
[rowa
][x
].blue
+ mv2
- in
[rowb
][x
+ 2].blue
;
9407 out
[x
+ 1] = lookup_rgb_color (f
, r
& 0xffff, g
& 0xffff,
9411 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
++);
9414 /* Write last line, all zeros. */
9415 for (x
= 0; x
< img
->width
; ++x
)
9417 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
);
9419 /* Free the input image, and free resources of IMG. */
9420 XDestroyImage (ximg
);
9421 x_clear_image (f
, img
);
9423 /* Put the output image into pixmap, and destroy it. */
9424 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
9425 x_destroy_x_image (oimg
);
9427 /* Remember new pixmap and colors in IMG. */
9428 img
->pixmap
= pixmap
;
9429 img
->colors
= colors_in_color_table (&img
->ncolors
);
9430 free_color_table ();
9433 #endif /* NTEMACS_TODO */
9437 /* Build a mask for image IMG which is used on frame F. FILE is the
9438 name of an image file, for error messages. HOW determines how to
9439 determine the background color of IMG. If it is a list '(R G B)',
9440 with R, G, and B being integers >= 0, take that as the color of the
9441 background. Otherwise, determine the background color of IMG
9442 heuristically. Value is non-zero if successful. */
9445 x_build_heuristic_mask (f
, img
, how
)
9450 #if 0 /* NTEMACS_TODO : W32 version */
9451 Display
*dpy
= FRAME_W32_DISPLAY (f
);
9452 XImage
*ximg
, *mask_img
;
9453 int x
, y
, rc
, look_at_corners_p
;
9458 /* Create an image and pixmap serving as mask. */
9459 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
9460 &mask_img
, &img
->mask
);
9467 /* Get the X image of IMG->pixmap. */
9468 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
9471 /* Determine the background color of ximg. If HOW is `(R G B)'
9472 take that as color. Otherwise, try to determine the color
9474 look_at_corners_p
= 1;
9482 && NATNUMP (XCAR (how
)))
9484 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
9488 if (i
== 3 && NILP (how
))
9490 char color_name
[30];
9491 XColor exact
, color
;
9494 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
9496 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
9497 if (XLookupColor (dpy
, cmap
, color_name
, &exact
, &color
))
9500 look_at_corners_p
= 0;
9505 if (look_at_corners_p
)
9507 unsigned long corners
[4];
9510 /* Get the colors at the corners of ximg. */
9511 corners
[0] = XGetPixel (ximg
, 0, 0);
9512 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
9513 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
9514 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
9516 /* Choose the most frequently found color as background. */
9517 for (i
= best_count
= 0; i
< 4; ++i
)
9521 for (j
= n
= 0; j
< 4; ++j
)
9522 if (corners
[i
] == corners
[j
])
9526 bg
= corners
[i
], best_count
= n
;
9530 /* Set all bits in mask_img to 1 whose color in ximg is different
9531 from the background color bg. */
9532 for (y
= 0; y
< img
->height
; ++y
)
9533 for (x
= 0; x
< img
->width
; ++x
)
9534 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
9536 /* Put mask_img into img->mask. */
9537 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
9538 x_destroy_x_image (mask_img
);
9539 XDestroyImage (ximg
);
9542 #endif /* NTEMACS_TODO */
9549 /***********************************************************************
9550 PBM (mono, gray, color)
9551 ***********************************************************************/
9554 static int pbm_image_p
P_ ((Lisp_Object object
));
9555 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
9556 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
9558 /* The symbol `pbm' identifying images of this type. */
9562 /* Indices of image specification fields in gs_format, below. */
9564 enum pbm_keyword_index
9577 /* Vector of image_keyword structures describing the format
9578 of valid user-defined image specifications. */
9580 static struct image_keyword pbm_format
[PBM_LAST
] =
9582 {":type", IMAGE_SYMBOL_VALUE
, 1},
9583 {":file", IMAGE_STRING_VALUE
, 0},
9584 {":data", IMAGE_STRING_VALUE
, 0},
9585 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9586 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9587 {":relief", IMAGE_INTEGER_VALUE
, 0},
9588 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9589 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9592 /* Structure describing the image type `pbm'. */
9594 static struct image_type pbm_type
=
9604 /* Return non-zero if OBJECT is a valid PBM image specification. */
9607 pbm_image_p (object
)
9610 struct image_keyword fmt
[PBM_LAST
];
9612 bcopy (pbm_format
, fmt
, sizeof fmt
);
9614 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
)
9615 || (fmt
[PBM_ASCENT
].count
9616 && XFASTINT (fmt
[PBM_ASCENT
].value
) > 100))
9619 /* Must specify either :data or :file. */
9620 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
9624 /* Scan a decimal number from *S and return it. Advance *S while
9625 reading the number. END is the end of the string. Value is -1 at
9629 pbm_scan_number (s
, end
)
9630 unsigned char **s
, *end
;
9636 /* Skip white-space. */
9637 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
9642 /* Skip comment to end of line. */
9643 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
9646 else if (isdigit (c
))
9648 /* Read decimal number. */
9650 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
9651 val
= 10 * val
+ c
- '0';
9662 /* Read FILE into memory. Value is a pointer to a buffer allocated
9663 with xmalloc holding FILE's contents. Value is null if an error
9664 occured. *SIZE is set to the size of the file. */
9667 pbm_read_file (file
, size
)
9675 if (stat (XSTRING (file
)->data
, &st
) == 0
9676 && (fp
= fopen (XSTRING (file
)->data
, "r")) != NULL
9677 && (buf
= (char *) xmalloc (st
.st_size
),
9678 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
9698 /* Load PBM image IMG for use on frame F. */
9706 int width
, height
, max_color_idx
= 0;
9708 Lisp_Object file
, specified_file
;
9709 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
9710 struct gcpro gcpro1
;
9711 unsigned char *contents
= NULL
;
9712 unsigned char *end
, *p
;
9715 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9719 if (STRINGP (specified_file
))
9721 file
= x_find_image_file (specified_file
);
9722 if (!STRINGP (file
))
9724 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9729 contents
= pbm_read_file (file
, &size
);
9730 if (contents
== NULL
)
9732 image_error ("Error reading `%s'", file
, Qnil
);
9738 end
= contents
+ size
;
9743 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9744 p
= XSTRING (data
)->data
;
9745 end
= p
+ STRING_BYTES (XSTRING (data
));
9748 /* Check magic number. */
9749 if (end
- p
< 2 || *p
++ != 'P')
9751 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
9761 raw_p
= 0, type
= PBM_MONO
;
9765 raw_p
= 0, type
= PBM_GRAY
;
9769 raw_p
= 0, type
= PBM_COLOR
;
9773 raw_p
= 1, type
= PBM_MONO
;
9777 raw_p
= 1, type
= PBM_GRAY
;
9781 raw_p
= 1, type
= PBM_COLOR
;
9785 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
9789 /* Read width, height, maximum color-component. Characters
9790 starting with `#' up to the end of a line are ignored. */
9791 width
= pbm_scan_number (&p
, end
);
9792 height
= pbm_scan_number (&p
, end
);
9794 if (type
!= PBM_MONO
)
9796 max_color_idx
= pbm_scan_number (&p
, end
);
9797 if (raw_p
&& max_color_idx
> 255)
9798 max_color_idx
= 255;
9803 || (type
!= PBM_MONO
&& max_color_idx
< 0))
9807 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
9808 &ximg
, &img
->pixmap
))
9814 /* Initialize the color hash table. */
9815 init_color_table ();
9817 if (type
== PBM_MONO
)
9821 for (y
= 0; y
< height
; ++y
)
9822 for (x
= 0; x
< width
; ++x
)
9832 g
= pbm_scan_number (&p
, end
);
9834 XPutPixel (ximg
, x
, y
, (g
9835 ? FRAME_FOREGROUND_PIXEL (f
)
9836 : FRAME_BACKGROUND_PIXEL (f
)));
9841 for (y
= 0; y
< height
; ++y
)
9842 for (x
= 0; x
< width
; ++x
)
9846 if (type
== PBM_GRAY
)
9847 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
9856 r
= pbm_scan_number (&p
, end
);
9857 g
= pbm_scan_number (&p
, end
);
9858 b
= pbm_scan_number (&p
, end
);
9861 if (r
< 0 || g
< 0 || b
< 0)
9865 XDestroyImage (ximg
);
9867 image_error ("Invalid pixel value in image `%s'",
9872 /* RGB values are now in the range 0..max_color_idx.
9873 Scale this to the range 0..0xffff supported by X. */
9874 r
= (double) r
* 65535 / max_color_idx
;
9875 g
= (double) g
* 65535 / max_color_idx
;
9876 b
= (double) b
* 65535 / max_color_idx
;
9877 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
9881 /* Store in IMG->colors the colors allocated for the image, and
9882 free the color table. */
9883 img
->colors
= colors_in_color_table (&img
->ncolors
);
9884 free_color_table ();
9886 /* Put the image into a pixmap. */
9887 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9888 x_destroy_x_image (ximg
);
9892 img
->height
= height
;
9898 #endif /* HAVE_PBM */
9901 /***********************************************************************
9903 ***********************************************************************/
9909 /* Function prototypes. */
9911 static int png_image_p
P_ ((Lisp_Object object
));
9912 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
9914 /* The symbol `png' identifying images of this type. */
9918 /* Indices of image specification fields in png_format, below. */
9920 enum png_keyword_index
9933 /* Vector of image_keyword structures describing the format
9934 of valid user-defined image specifications. */
9936 static struct image_keyword png_format
[PNG_LAST
] =
9938 {":type", IMAGE_SYMBOL_VALUE
, 1},
9939 {":data", IMAGE_STRING_VALUE
, 0},
9940 {":file", IMAGE_STRING_VALUE
, 0},
9941 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9942 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9943 {":relief", IMAGE_INTEGER_VALUE
, 0},
9944 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9945 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9948 /* Structure describing the image type `png'. */
9950 static struct image_type png_type
=
9960 /* Return non-zero if OBJECT is a valid PNG image specification. */
9963 png_image_p (object
)
9966 struct image_keyword fmt
[PNG_LAST
];
9967 bcopy (png_format
, fmt
, sizeof fmt
);
9969 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
)
9970 || (fmt
[PNG_ASCENT
].count
9971 && XFASTINT (fmt
[PNG_ASCENT
].value
) > 100))
9974 /* Must specify either the :data or :file keyword. */
9975 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
9979 /* Error and warning handlers installed when the PNG library
9983 my_png_error (png_ptr
, msg
)
9984 png_struct
*png_ptr
;
9987 xassert (png_ptr
!= NULL
);
9988 image_error ("PNG error: %s", build_string (msg
), Qnil
);
9989 longjmp (png_ptr
->jmpbuf
, 1);
9994 my_png_warning (png_ptr
, msg
)
9995 png_struct
*png_ptr
;
9998 xassert (png_ptr
!= NULL
);
9999 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
10002 /* Memory source for PNG decoding. */
10004 struct png_memory_storage
10006 unsigned char *bytes
; /* The data */
10007 size_t len
; /* How big is it? */
10008 int index
; /* Where are we? */
10012 /* Function set as reader function when reading PNG image from memory.
10013 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
10014 bytes from the input to DATA. */
10017 png_read_from_memory (png_ptr
, data
, length
)
10018 png_structp png_ptr
;
10022 struct png_memory_storage
*tbr
10023 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
10025 if (length
> tbr
->len
- tbr
->index
)
10026 png_error (png_ptr
, "Read error");
10028 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
10029 tbr
->index
= tbr
->index
+ length
;
10032 /* Load PNG image IMG for use on frame F. Value is non-zero if
10040 Lisp_Object file
, specified_file
;
10041 Lisp_Object specified_data
;
10043 XImage
*ximg
, *mask_img
= NULL
;
10044 struct gcpro gcpro1
;
10045 png_struct
*png_ptr
= NULL
;
10046 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
10049 png_byte
*pixels
= NULL
;
10050 png_byte
**rows
= NULL
;
10051 png_uint_32 width
, height
;
10052 int bit_depth
, color_type
, interlace_type
;
10054 png_uint_32 row_bytes
;
10057 double screen_gamma
, image_gamma
;
10059 struct png_memory_storage tbr
; /* Data to be read */
10061 /* Find out what file to load. */
10062 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10063 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10067 if (NILP (specified_data
))
10069 file
= x_find_image_file (specified_file
);
10070 if (!STRINGP (file
))
10072 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10077 /* Open the image file. */
10078 fp
= fopen (XSTRING (file
)->data
, "rb");
10081 image_error ("Cannot open image file `%s'", file
, Qnil
);
10087 /* Check PNG signature. */
10088 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
10089 || !png_check_sig (sig
, sizeof sig
))
10091 image_error ("Not a PNG file:` %s'", file
, Qnil
);
10099 /* Read from memory. */
10100 tbr
.bytes
= XSTRING (specified_data
)->data
;
10101 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
10104 /* Check PNG signature. */
10105 if (tbr
.len
< sizeof sig
10106 || !png_check_sig (tbr
.bytes
, sizeof sig
))
10108 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
10113 /* Need to skip past the signature. */
10114 tbr
.bytes
+= sizeof (sig
);
10117 /* Initialize read and info structs for PNG lib. */
10118 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
10119 my_png_error
, my_png_warning
);
10122 if (fp
) fclose (fp
);
10127 info_ptr
= png_create_info_struct (png_ptr
);
10130 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
10131 if (fp
) fclose (fp
);
10136 end_info
= png_create_info_struct (png_ptr
);
10139 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
10140 if (fp
) fclose (fp
);
10145 /* Set error jump-back. We come back here when the PNG library
10146 detects an error. */
10147 if (setjmp (png_ptr
->jmpbuf
))
10151 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
10154 if (fp
) fclose (fp
);
10159 /* Read image info. */
10160 if (!NILP (specified_data
))
10161 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
10163 png_init_io (png_ptr
, fp
);
10165 png_set_sig_bytes (png_ptr
, sizeof sig
);
10166 png_read_info (png_ptr
, info_ptr
);
10167 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
10168 &interlace_type
, NULL
, NULL
);
10170 /* If image contains simply transparency data, we prefer to
10171 construct a clipping mask. */
10172 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
10177 /* This function is easier to write if we only have to handle
10178 one data format: RGB or RGBA with 8 bits per channel. Let's
10179 transform other formats into that format. */
10181 /* Strip more than 8 bits per channel. */
10182 if (bit_depth
== 16)
10183 png_set_strip_16 (png_ptr
);
10185 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
10187 png_set_expand (png_ptr
);
10189 /* Convert grayscale images to RGB. */
10190 if (color_type
== PNG_COLOR_TYPE_GRAY
10191 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
10192 png_set_gray_to_rgb (png_ptr
);
10194 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
10195 gamma_str
= getenv ("SCREEN_GAMMA");
10196 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
10198 /* Tell the PNG lib to handle gamma correction for us. */
10200 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
10201 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
10202 /* There is a special chunk in the image specifying the gamma. */
10203 png_set_sRGB (png_ptr
, info_ptr
, intent
);
10206 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
10207 /* Image contains gamma information. */
10208 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
10210 /* Use a default of 0.5 for the image gamma. */
10211 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
10213 /* Handle alpha channel by combining the image with a background
10214 color. Do this only if a real alpha channel is supplied. For
10215 simple transparency, we prefer a clipping mask. */
10216 if (!transparent_p
)
10218 png_color_16
*image_background
;
10220 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
10221 /* Image contains a background color with which to
10222 combine the image. */
10223 png_set_background (png_ptr
, image_background
,
10224 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
10227 /* Image does not contain a background color with which
10228 to combine the image data via an alpha channel. Use
10229 the frame's background instead. */
10232 png_color_16 frame_background
;
10235 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
10236 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
10237 XQueryColor (FRAME_W32_DISPLAY (f
), cmap
, &color
);
10240 bzero (&frame_background
, sizeof frame_background
);
10241 frame_background
.red
= color
.red
;
10242 frame_background
.green
= color
.green
;
10243 frame_background
.blue
= color
.blue
;
10245 png_set_background (png_ptr
, &frame_background
,
10246 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
10250 /* Update info structure. */
10251 png_read_update_info (png_ptr
, info_ptr
);
10253 /* Get number of channels. Valid values are 1 for grayscale images
10254 and images with a palette, 2 for grayscale images with transparency
10255 information (alpha channel), 3 for RGB images, and 4 for RGB
10256 images with alpha channel, i.e. RGBA. If conversions above were
10257 sufficient we should only have 3 or 4 channels here. */
10258 channels
= png_get_channels (png_ptr
, info_ptr
);
10259 xassert (channels
== 3 || channels
== 4);
10261 /* Number of bytes needed for one row of the image. */
10262 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
10264 /* Allocate memory for the image. */
10265 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
10266 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
10267 for (i
= 0; i
< height
; ++i
)
10268 rows
[i
] = pixels
+ i
* row_bytes
;
10270 /* Read the entire image. */
10271 png_read_image (png_ptr
, rows
);
10272 png_read_end (png_ptr
, info_ptr
);
10281 /* Create the X image and pixmap. */
10282 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
10289 /* Create an image and pixmap serving as mask if the PNG image
10290 contains an alpha channel. */
10293 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
10294 &mask_img
, &img
->mask
))
10296 x_destroy_x_image (ximg
);
10297 XFreePixmap (FRAME_W32_DISPLAY (f
), img
->pixmap
);
10303 /* Fill the X image and mask from PNG data. */
10304 init_color_table ();
10306 for (y
= 0; y
< height
; ++y
)
10308 png_byte
*p
= rows
[y
];
10310 for (x
= 0; x
< width
; ++x
)
10317 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
10319 /* An alpha channel, aka mask channel, associates variable
10320 transparency with an image. Where other image formats
10321 support binary transparency---fully transparent or fully
10322 opaque---PNG allows up to 254 levels of partial transparency.
10323 The PNG library implements partial transparency by combining
10324 the image with a specified background color.
10326 I'm not sure how to handle this here nicely: because the
10327 background on which the image is displayed may change, for
10328 real alpha channel support, it would be necessary to create
10329 a new image for each possible background.
10331 What I'm doing now is that a mask is created if we have
10332 boolean transparency information. Otherwise I'm using
10333 the frame's background color to combine the image with. */
10338 XPutPixel (mask_img
, x
, y
, *p
> 0);
10344 /* Remember colors allocated for this image. */
10345 img
->colors
= colors_in_color_table (&img
->ncolors
);
10346 free_color_table ();
10349 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
10353 img
->width
= width
;
10354 img
->height
= height
;
10356 /* Put the image into the pixmap, then free the X image and its buffer. */
10357 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10358 x_destroy_x_image (ximg
);
10360 /* Same for the mask. */
10363 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
10364 x_destroy_x_image (mask_img
);
10372 #endif /* HAVE_PNG != 0 */
10376 /***********************************************************************
10378 ***********************************************************************/
10382 /* Work around a warning about HAVE_STDLIB_H being redefined in
10384 #ifdef HAVE_STDLIB_H
10385 #define HAVE_STDLIB_H_1
10386 #undef HAVE_STDLIB_H
10387 #endif /* HAVE_STLIB_H */
10389 #include <jpeglib.h>
10390 #include <jerror.h>
10391 #include <setjmp.h>
10393 #ifdef HAVE_STLIB_H_1
10394 #define HAVE_STDLIB_H 1
10397 static int jpeg_image_p
P_ ((Lisp_Object object
));
10398 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
10400 /* The symbol `jpeg' identifying images of this type. */
10404 /* Indices of image specification fields in gs_format, below. */
10406 enum jpeg_keyword_index
10415 JPEG_HEURISTIC_MASK
,
10419 /* Vector of image_keyword structures describing the format
10420 of valid user-defined image specifications. */
10422 static struct image_keyword jpeg_format
[JPEG_LAST
] =
10424 {":type", IMAGE_SYMBOL_VALUE
, 1},
10425 {":data", IMAGE_STRING_VALUE
, 0},
10426 {":file", IMAGE_STRING_VALUE
, 0},
10427 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
10428 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
10429 {":relief", IMAGE_INTEGER_VALUE
, 0},
10430 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10431 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
10434 /* Structure describing the image type `jpeg'. */
10436 static struct image_type jpeg_type
=
10446 /* Return non-zero if OBJECT is a valid JPEG image specification. */
10449 jpeg_image_p (object
)
10450 Lisp_Object object
;
10452 struct image_keyword fmt
[JPEG_LAST
];
10454 bcopy (jpeg_format
, fmt
, sizeof fmt
);
10456 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
)
10457 || (fmt
[JPEG_ASCENT
].count
10458 && XFASTINT (fmt
[JPEG_ASCENT
].value
) > 100))
10461 /* Must specify either the :data or :file keyword. */
10462 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
10466 struct my_jpeg_error_mgr
10468 struct jpeg_error_mgr pub
;
10469 jmp_buf setjmp_buffer
;
10473 my_error_exit (cinfo
)
10474 j_common_ptr cinfo
;
10476 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
10477 longjmp (mgr
->setjmp_buffer
, 1);
10480 /* Init source method for JPEG data source manager. Called by
10481 jpeg_read_header() before any data is actually read. See
10482 libjpeg.doc from the JPEG lib distribution. */
10485 our_init_source (cinfo
)
10486 j_decompress_ptr cinfo
;
10491 /* Fill input buffer method for JPEG data source manager. Called
10492 whenever more data is needed. We read the whole image in one step,
10493 so this only adds a fake end of input marker at the end. */
10496 our_fill_input_buffer (cinfo
)
10497 j_decompress_ptr cinfo
;
10499 /* Insert a fake EOI marker. */
10500 struct jpeg_source_mgr
*src
= cinfo
->src
;
10501 static JOCTET buffer
[2];
10503 buffer
[0] = (JOCTET
) 0xFF;
10504 buffer
[1] = (JOCTET
) JPEG_EOI
;
10506 src
->next_input_byte
= buffer
;
10507 src
->bytes_in_buffer
= 2;
10512 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
10513 is the JPEG data source manager. */
10516 our_skip_input_data (cinfo
, num_bytes
)
10517 j_decompress_ptr cinfo
;
10520 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
10524 if (num_bytes
> src
->bytes_in_buffer
)
10525 ERREXIT (cinfo
, JERR_INPUT_EOF
);
10527 src
->bytes_in_buffer
-= num_bytes
;
10528 src
->next_input_byte
+= num_bytes
;
10533 /* Method to terminate data source. Called by
10534 jpeg_finish_decompress() after all data has been processed. */
10537 our_term_source (cinfo
)
10538 j_decompress_ptr cinfo
;
10543 /* Set up the JPEG lib for reading an image from DATA which contains
10544 LEN bytes. CINFO is the decompression info structure created for
10545 reading the image. */
10548 jpeg_memory_src (cinfo
, data
, len
)
10549 j_decompress_ptr cinfo
;
10553 struct jpeg_source_mgr
*src
;
10555 if (cinfo
->src
== NULL
)
10557 /* First time for this JPEG object? */
10558 cinfo
->src
= (struct jpeg_source_mgr
*)
10559 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
10560 sizeof (struct jpeg_source_mgr
));
10561 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
10562 src
->next_input_byte
= data
;
10565 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
10566 src
->init_source
= our_init_source
;
10567 src
->fill_input_buffer
= our_fill_input_buffer
;
10568 src
->skip_input_data
= our_skip_input_data
;
10569 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
10570 src
->term_source
= our_term_source
;
10571 src
->bytes_in_buffer
= len
;
10572 src
->next_input_byte
= data
;
10576 /* Load image IMG for use on frame F. Patterned after example.c
10577 from the JPEG lib. */
10584 struct jpeg_decompress_struct cinfo
;
10585 struct my_jpeg_error_mgr mgr
;
10586 Lisp_Object file
, specified_file
;
10587 Lisp_Object specified_data
;
10590 int row_stride
, x
, y
;
10591 XImage
*ximg
= NULL
;
10593 unsigned long *colors
;
10595 struct gcpro gcpro1
;
10597 /* Open the JPEG file. */
10598 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10599 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10603 if (NILP (specified_data
))
10605 file
= x_find_image_file (specified_file
);
10606 if (!STRINGP (file
))
10608 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
10613 fp
= fopen (XSTRING (file
)->data
, "r");
10616 image_error ("Cannot open `%s'", file
, Qnil
);
10622 /* Customize libjpeg's error handling to call my_error_exit when an
10623 error is detected. This function will perform a longjmp. */
10624 mgr
.pub
.error_exit
= my_error_exit
;
10625 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
10627 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
10631 /* Called from my_error_exit. Display a JPEG error. */
10632 char buffer
[JMSG_LENGTH_MAX
];
10633 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
10634 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
10635 build_string (buffer
));
10638 /* Close the input file and destroy the JPEG object. */
10641 jpeg_destroy_decompress (&cinfo
);
10645 /* If we already have an XImage, free that. */
10646 x_destroy_x_image (ximg
);
10648 /* Free pixmap and colors. */
10649 x_clear_image (f
, img
);
10656 /* Create the JPEG decompression object. Let it read from fp.
10657 Read the JPEG image header. */
10658 jpeg_create_decompress (&cinfo
);
10660 if (NILP (specified_data
))
10661 jpeg_stdio_src (&cinfo
, fp
);
10663 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
10664 STRING_BYTES (XSTRING (specified_data
)));
10666 jpeg_read_header (&cinfo
, TRUE
);
10668 /* Customize decompression so that color quantization will be used.
10669 Start decompression. */
10670 cinfo
.quantize_colors
= TRUE
;
10671 jpeg_start_decompress (&cinfo
);
10672 width
= img
->width
= cinfo
.output_width
;
10673 height
= img
->height
= cinfo
.output_height
;
10677 /* Create X image and pixmap. */
10678 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
10682 longjmp (mgr
.setjmp_buffer
, 2);
10685 /* Allocate colors. When color quantization is used,
10686 cinfo.actual_number_of_colors has been set with the number of
10687 colors generated, and cinfo.colormap is a two-dimensional array
10688 of color indices in the range 0..cinfo.actual_number_of_colors.
10689 No more than 255 colors will be generated. */
10693 if (cinfo
.out_color_components
> 2)
10694 ir
= 0, ig
= 1, ib
= 2;
10695 else if (cinfo
.out_color_components
> 1)
10696 ir
= 0, ig
= 1, ib
= 0;
10698 ir
= 0, ig
= 0, ib
= 0;
10700 /* Use the color table mechanism because it handles colors that
10701 cannot be allocated nicely. Such colors will be replaced with
10702 a default color, and we don't have to care about which colors
10703 can be freed safely, and which can't. */
10704 init_color_table ();
10705 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
10708 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
10710 /* Multiply RGB values with 255 because X expects RGB values
10711 in the range 0..0xffff. */
10712 int r
= cinfo
.colormap
[ir
][i
] << 8;
10713 int g
= cinfo
.colormap
[ig
][i
] << 8;
10714 int b
= cinfo
.colormap
[ib
][i
] << 8;
10715 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
10718 /* Remember those colors actually allocated. */
10719 img
->colors
= colors_in_color_table (&img
->ncolors
);
10720 free_color_table ();
10724 row_stride
= width
* cinfo
.output_components
;
10725 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
10727 for (y
= 0; y
< height
; ++y
)
10729 jpeg_read_scanlines (&cinfo
, buffer
, 1);
10730 for (x
= 0; x
< cinfo
.output_width
; ++x
)
10731 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
10735 jpeg_finish_decompress (&cinfo
);
10736 jpeg_destroy_decompress (&cinfo
);
10740 /* Put the image into the pixmap. */
10741 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
10742 x_destroy_x_image (ximg
);
10748 #endif /* HAVE_JPEG */
10752 /***********************************************************************
10754 ***********************************************************************/
10758 #include <tiffio.h>
10760 static int tiff_image_p
P_ ((Lisp_Object object
));
10761 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
10763 /* The symbol `tiff' identifying images of this type. */
10767 /* Indices of image specification fields in tiff_format, below. */
10769 enum tiff_keyword_index
10778 TIFF_HEURISTIC_MASK
,
10782 /* Vector of image_keyword structures describing the format
10783 of valid user-defined image specifications. */
10785 static struct image_keyword tiff_format
[TIFF_LAST
] =
10787 {":type", IMAGE_SYMBOL_VALUE
, 1},
10788 {":data", IMAGE_STRING_VALUE
, 0},
10789 {":file", IMAGE_STRING_VALUE
, 0},
10790 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
10791 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
10792 {":relief", IMAGE_INTEGER_VALUE
, 0},
10793 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
10794 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
10797 /* Structure describing the image type `tiff'. */
10799 static struct image_type tiff_type
=
10809 /* Return non-zero if OBJECT is a valid TIFF image specification. */
10812 tiff_image_p (object
)
10813 Lisp_Object object
;
10815 struct image_keyword fmt
[TIFF_LAST
];
10816 bcopy (tiff_format
, fmt
, sizeof fmt
);
10818 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
)
10819 || (fmt
[TIFF_ASCENT
].count
10820 && XFASTINT (fmt
[TIFF_ASCENT
].value
) > 100))
10823 /* Must specify either the :data or :file keyword. */
10824 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
10828 /* Reading from a memory buffer for TIFF images Based on the PNG
10829 memory source, but we have to provide a lot of extra functions.
10832 We really only need to implement read and seek, but I am not
10833 convinced that the TIFF library is smart enough not to destroy
10834 itself if we only hand it the function pointers we need to
10839 unsigned char *bytes
;
10843 tiff_memory_source
;
10846 tiff_read_from_memory (data
, buf
, size
)
10851 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
10853 if (size
> src
->len
- src
->index
)
10854 return (size_t) -1;
10855 bcopy (src
->bytes
+ src
->index
, buf
, size
);
10856 src
->index
+= size
;
10861 tiff_write_from_memory (data
, buf
, size
)
10866 return (size_t) -1;
10870 tiff_seek_in_memory (data
, off
, whence
)
10875 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
10880 case SEEK_SET
: /* Go from beginning of source. */
10884 case SEEK_END
: /* Go from end of source. */
10885 idx
= src
->len
+ off
;
10888 case SEEK_CUR
: /* Go from current position. */
10889 idx
= src
->index
+ off
;
10892 default: /* Invalid `whence'. */
10896 if (idx
> src
->len
|| idx
< 0)
10904 tiff_close_memory (data
)
10912 tiff_mmap_memory (data
, pbase
, psize
)
10917 /* It is already _IN_ memory. */
10922 tiff_unmap_memory (data
, base
, size
)
10927 /* We don't need to do this. */
10931 tiff_size_of_memory (data
)
10934 return ((tiff_memory_source
*) data
)->len
;
10937 /* Load TIFF image IMG for use on frame F. Value is non-zero if
10945 Lisp_Object file
, specified_file
;
10946 Lisp_Object specified_data
;
10948 int width
, height
, x
, y
;
10952 struct gcpro gcpro1
;
10953 tiff_memory_source memsrc
;
10955 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
10956 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
10960 if (NILP (specified_data
))
10962 /* Read from a file */
10963 file
= x_find_image_file (specified_file
);
10964 if (!STRINGP (file
))
10966 image_error ("Cannot find image file `%s'", file
, Qnil
);
10971 /* Try to open the image file. */
10972 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
10975 image_error ("Cannot open `%s'", file
, Qnil
);
10982 /* Memory source! */
10983 memsrc
.bytes
= XSTRING (specified_data
)->data
;
10984 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
10987 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
10988 (TIFFReadWriteProc
) tiff_read_from_memory
,
10989 (TIFFReadWriteProc
) tiff_write_from_memory
,
10990 tiff_seek_in_memory
,
10992 tiff_size_of_memory
,
10994 tiff_unmap_memory
);
10998 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
11004 /* Get width and height of the image, and allocate a raster buffer
11005 of width x height 32-bit values. */
11006 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
11007 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
11008 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
11010 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
11014 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
11022 /* Create the X image and pixmap. */
11023 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
11031 /* Initialize the color table. */
11032 init_color_table ();
11034 /* Process the pixel raster. Origin is in the lower-left corner. */
11035 for (y
= 0; y
< height
; ++y
)
11037 uint32
*row
= buf
+ y
* width
;
11039 for (x
= 0; x
< width
; ++x
)
11041 uint32 abgr
= row
[x
];
11042 int r
= TIFFGetR (abgr
) << 8;
11043 int g
= TIFFGetG (abgr
) << 8;
11044 int b
= TIFFGetB (abgr
) << 8;
11045 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
11049 /* Remember the colors allocated for the image. Free the color table. */
11050 img
->colors
= colors_in_color_table (&img
->ncolors
);
11051 free_color_table ();
11053 /* Put the image into the pixmap, then free the X image and its buffer. */
11054 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
11055 x_destroy_x_image (ximg
);
11059 img
->width
= width
;
11060 img
->height
= height
;
11066 #endif /* HAVE_TIFF != 0 */
11070 /***********************************************************************
11072 ***********************************************************************/
11076 #include <gif_lib.h>
11078 static int gif_image_p
P_ ((Lisp_Object object
));
11079 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
11081 /* The symbol `gif' identifying images of this type. */
11085 /* Indices of image specification fields in gif_format, below. */
11087 enum gif_keyword_index
11096 GIF_HEURISTIC_MASK
,
11101 /* Vector of image_keyword structures describing the format
11102 of valid user-defined image specifications. */
11104 static struct image_keyword gif_format
[GIF_LAST
] =
11106 {":type", IMAGE_SYMBOL_VALUE
, 1},
11107 {":data", IMAGE_STRING_VALUE
, 0},
11108 {":file", IMAGE_STRING_VALUE
, 0},
11109 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
11110 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
11111 {":relief", IMAGE_INTEGER_VALUE
, 0},
11112 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
11113 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
11114 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
11117 /* Structure describing the image type `gif'. */
11119 static struct image_type gif_type
=
11128 /* Return non-zero if OBJECT is a valid GIF image specification. */
11131 gif_image_p (object
)
11132 Lisp_Object object
;
11134 struct image_keyword fmt
[GIF_LAST
];
11135 bcopy (gif_format
, fmt
, sizeof fmt
);
11137 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
)
11138 || (fmt
[GIF_ASCENT
].count
11139 && XFASTINT (fmt
[GIF_ASCENT
].value
) > 100))
11142 /* Must specify either the :data or :file keyword. */
11143 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
11146 /* Reading a GIF image from memory
11147 Based on the PNG memory stuff to a certain extent. */
11151 unsigned char *bytes
;
11157 /* Make the current memory source available to gif_read_from_memory.
11158 It's done this way because not all versions of libungif support
11159 a UserData field in the GifFileType structure. */
11160 static gif_memory_source
*current_gif_memory_src
;
11163 gif_read_from_memory (file
, buf
, len
)
11168 gif_memory_source
*src
= current_gif_memory_src
;
11170 if (len
> src
->len
- src
->index
)
11173 bcopy (src
->bytes
+ src
->index
, buf
, len
);
11179 /* Load GIF image IMG for use on frame F. Value is non-zero if
11187 Lisp_Object file
, specified_file
;
11188 Lisp_Object specified_data
;
11189 int rc
, width
, height
, x
, y
, i
;
11191 ColorMapObject
*gif_color_map
;
11192 unsigned long pixel_colors
[256];
11194 struct gcpro gcpro1
;
11196 int ino
, image_left
, image_top
, image_width
, image_height
;
11197 gif_memory_source memsrc
;
11198 unsigned char *raster
;
11200 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
11201 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
11205 if (NILP (specified_data
))
11207 file
= x_find_image_file (specified_file
);
11208 if (!STRINGP (file
))
11210 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
11215 /* Open the GIF file. */
11216 gif
= DGifOpenFileName (XSTRING (file
)->data
);
11219 image_error ("Cannot open `%s'", file
, Qnil
);
11226 /* Read from memory! */
11227 current_gif_memory_src
= &memsrc
;
11228 memsrc
.bytes
= XSTRING (specified_data
)->data
;
11229 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
11232 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
11235 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
11241 /* Read entire contents. */
11242 rc
= DGifSlurp (gif
);
11243 if (rc
== GIF_ERROR
)
11245 image_error ("Error reading `%s'", img
->spec
, Qnil
);
11246 DGifCloseFile (gif
);
11251 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
11252 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
11253 if (ino
>= gif
->ImageCount
)
11255 image_error ("Invalid image number `%s' in image `%s'",
11257 DGifCloseFile (gif
);
11262 width
= img
->width
= gif
->SWidth
;
11263 height
= img
->height
= gif
->SHeight
;
11267 /* Create the X image and pixmap. */
11268 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
11271 DGifCloseFile (gif
);
11276 /* Allocate colors. */
11277 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
11278 if (!gif_color_map
)
11279 gif_color_map
= gif
->SColorMap
;
11280 init_color_table ();
11281 bzero (pixel_colors
, sizeof pixel_colors
);
11283 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
11285 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
11286 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
11287 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
11288 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
11291 img
->colors
= colors_in_color_table (&img
->ncolors
);
11292 free_color_table ();
11294 /* Clear the part of the screen image that are not covered by
11295 the image from the GIF file. Full animated GIF support
11296 requires more than can be done here (see the gif89 spec,
11297 disposal methods). Let's simply assume that the part
11298 not covered by a sub-image is in the frame's background color. */
11299 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
11300 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
11301 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
11302 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
11304 for (y
= 0; y
< image_top
; ++y
)
11305 for (x
= 0; x
< width
; ++x
)
11306 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
11308 for (y
= image_top
+ image_height
; y
< height
; ++y
)
11309 for (x
= 0; x
< width
; ++x
)
11310 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
11312 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
11314 for (x
= 0; x
< image_left
; ++x
)
11315 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
11316 for (x
= image_left
+ image_width
; x
< width
; ++x
)
11317 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
11320 /* Read the GIF image into the X image. We use a local variable
11321 `raster' here because RasterBits below is a char *, and invites
11322 problems with bytes >= 0x80. */
11323 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
11325 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
11327 static int interlace_start
[] = {0, 4, 2, 1};
11328 static int interlace_increment
[] = {8, 8, 4, 2};
11330 int row
= interlace_start
[0];
11334 for (y
= 0; y
< image_height
; y
++)
11336 if (row
>= image_height
)
11338 row
= interlace_start
[++pass
];
11339 while (row
>= image_height
)
11340 row
= interlace_start
[++pass
];
11343 for (x
= 0; x
< image_width
; x
++)
11345 int i
= raster
[(y
* image_width
) + x
];
11346 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
11350 row
+= interlace_increment
[pass
];
11355 for (y
= 0; y
< image_height
; ++y
)
11356 for (x
= 0; x
< image_width
; ++x
)
11358 int i
= raster
[y
* image_width
+ x
];
11359 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
11363 DGifCloseFile (gif
);
11365 /* Put the image into the pixmap, then free the X image and its buffer. */
11366 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
11367 x_destroy_x_image (ximg
);
11374 #endif /* HAVE_GIF != 0 */
11378 /***********************************************************************
11380 ***********************************************************************/
11382 #ifdef HAVE_GHOSTSCRIPT
11383 static int gs_image_p
P_ ((Lisp_Object object
));
11384 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
11385 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
11387 /* The symbol `postscript' identifying images of this type. */
11389 Lisp_Object Qpostscript
;
11391 /* Keyword symbols. */
11393 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
11395 /* Indices of image specification fields in gs_format, below. */
11397 enum gs_keyword_index
11413 /* Vector of image_keyword structures describing the format
11414 of valid user-defined image specifications. */
11416 static struct image_keyword gs_format
[GS_LAST
] =
11418 {":type", IMAGE_SYMBOL_VALUE
, 1},
11419 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
11420 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
11421 {":file", IMAGE_STRING_VALUE
, 1},
11422 {":loader", IMAGE_FUNCTION_VALUE
, 0},
11423 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
11424 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
11425 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
11426 {":relief", IMAGE_INTEGER_VALUE
, 0},
11427 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
11428 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
11431 /* Structure describing the image type `ghostscript'. */
11433 static struct image_type gs_type
=
11443 /* Free X resources of Ghostscript image IMG which is used on frame F. */
11446 gs_clear_image (f
, img
)
11450 /* IMG->data.ptr_val may contain a recorded colormap. */
11451 xfree (img
->data
.ptr_val
);
11452 x_clear_image (f
, img
);
11456 /* Return non-zero if OBJECT is a valid Ghostscript image
11460 gs_image_p (object
)
11461 Lisp_Object object
;
11463 struct image_keyword fmt
[GS_LAST
];
11467 bcopy (gs_format
, fmt
, sizeof fmt
);
11469 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
)
11470 || (fmt
[GS_ASCENT
].count
11471 && XFASTINT (fmt
[GS_ASCENT
].value
) > 100))
11474 /* Bounding box must be a list or vector containing 4 integers. */
11475 tem
= fmt
[GS_BOUNDING_BOX
].value
;
11478 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
11479 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
11484 else if (VECTORP (tem
))
11486 if (XVECTOR (tem
)->size
!= 4)
11488 for (i
= 0; i
< 4; ++i
)
11489 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
11499 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
11508 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
11509 struct gcpro gcpro1
, gcpro2
;
11511 double in_width
, in_height
;
11512 Lisp_Object pixel_colors
= Qnil
;
11514 /* Compute pixel size of pixmap needed from the given size in the
11515 image specification. Sizes in the specification are in pt. 1 pt
11516 = 1/72 in, xdpi and ydpi are stored in the frame's X display
11518 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
11519 in_width
= XFASTINT (pt_width
) / 72.0;
11520 img
->width
= in_width
* FRAME_W32_DISPLAY_INFO (f
)->resx
;
11521 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
11522 in_height
= XFASTINT (pt_height
) / 72.0;
11523 img
->height
= in_height
* FRAME_W32_DISPLAY_INFO (f
)->resy
;
11525 /* Create the pixmap. */
11527 xassert (img
->pixmap
== 0);
11528 img
->pixmap
= XCreatePixmap (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
11529 img
->width
, img
->height
,
11530 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
11535 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
11539 /* Call the loader to fill the pixmap. It returns a process object
11540 if successful. We do not record_unwind_protect here because
11541 other places in redisplay like calling window scroll functions
11542 don't either. Let the Lisp loader use `unwind-protect' instead. */
11543 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
11545 sprintf (buffer
, "%lu %lu",
11546 (unsigned long) FRAME_W32_WINDOW (f
),
11547 (unsigned long) img
->pixmap
);
11548 window_and_pixmap_id
= build_string (buffer
);
11550 sprintf (buffer
, "%lu %lu",
11551 FRAME_FOREGROUND_PIXEL (f
),
11552 FRAME_BACKGROUND_PIXEL (f
));
11553 pixel_colors
= build_string (buffer
);
11555 XSETFRAME (frame
, f
);
11556 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
11558 loader
= intern ("gs-load-image");
11560 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
11561 make_number (img
->width
),
11562 make_number (img
->height
),
11563 window_and_pixmap_id
,
11566 return PROCESSP (img
->data
.lisp_val
);
11570 /* Kill the Ghostscript process that was started to fill PIXMAP on
11571 frame F. Called from XTread_socket when receiving an event
11572 telling Emacs that Ghostscript has finished drawing. */
11575 x_kill_gs_process (pixmap
, f
)
11579 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
11583 /* Find the image containing PIXMAP. */
11584 for (i
= 0; i
< c
->used
; ++i
)
11585 if (c
->images
[i
]->pixmap
== pixmap
)
11588 /* Kill the GS process. We should have found PIXMAP in the image
11589 cache and its image should contain a process object. */
11590 xassert (i
< c
->used
);
11591 img
= c
->images
[i
];
11592 xassert (PROCESSP (img
->data
.lisp_val
));
11593 Fkill_process (img
->data
.lisp_val
, Qnil
);
11594 img
->data
.lisp_val
= Qnil
;
11596 /* On displays with a mutable colormap, figure out the colors
11597 allocated for the image by looking at the pixels of an XImage for
11599 class = FRAME_W32_DISPLAY_INFO (f
)->visual
->class;
11600 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
11606 /* Try to get an XImage for img->pixmep. */
11607 ximg
= XGetImage (FRAME_W32_DISPLAY (f
), img
->pixmap
,
11608 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
11613 /* Initialize the color table. */
11614 init_color_table ();
11616 /* For each pixel of the image, look its color up in the
11617 color table. After having done so, the color table will
11618 contain an entry for each color used by the image. */
11619 for (y
= 0; y
< img
->height
; ++y
)
11620 for (x
= 0; x
< img
->width
; ++x
)
11622 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
11623 lookup_pixel_color (f
, pixel
);
11626 /* Record colors in the image. Free color table and XImage. */
11627 img
->colors
= colors_in_color_table (&img
->ncolors
);
11628 free_color_table ();
11629 XDestroyImage (ximg
);
11631 #if 0 /* This doesn't seem to be the case. If we free the colors
11632 here, we get a BadAccess later in x_clear_image when
11633 freeing the colors. */
11634 /* We have allocated colors once, but Ghostscript has also
11635 allocated colors on behalf of us. So, to get the
11636 reference counts right, free them once. */
11639 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
11640 XFreeColors (FRAME_W32_DISPLAY (f
), cmap
,
11641 img
->colors
, img
->ncolors
, 0);
11646 image_error ("Cannot get X image of `%s'; colors will not be freed",
11653 #endif /* HAVE_GHOSTSCRIPT */
11656 /***********************************************************************
11658 ***********************************************************************/
11660 DEFUN ("x-change-window-property", Fx_change_window_property
,
11661 Sx_change_window_property
, 2, 3, 0,
11662 "Change window property PROP to VALUE on the X window of FRAME.\n\
11663 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
11664 selected frame. Value is VALUE.")
11665 (prop
, value
, frame
)
11666 Lisp_Object frame
, prop
, value
;
11668 #if 0 /* NTEMACS_TODO : port window properties to W32 */
11669 struct frame
*f
= check_x_frame (frame
);
11672 CHECK_STRING (prop
, 1);
11673 CHECK_STRING (value
, 2);
11676 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), XSTRING (prop
)->data
, False
);
11677 XChangeProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
11678 prop_atom
, XA_STRING
, 8, PropModeReplace
,
11679 XSTRING (value
)->data
, XSTRING (value
)->size
);
11681 /* Make sure the property is set when we return. */
11682 XFlush (FRAME_W32_DISPLAY (f
));
11685 #endif /* NTEMACS_TODO */
11691 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
11692 Sx_delete_window_property
, 1, 2, 0,
11693 "Remove window property PROP from X window of FRAME.\n\
11694 FRAME nil or omitted means use the selected frame. Value is PROP.")
11696 Lisp_Object prop
, frame
;
11698 #if 0 /* NTEMACS_TODO : port window properties to W32 */
11700 struct frame
*f
= check_x_frame (frame
);
11703 CHECK_STRING (prop
, 1);
11705 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), XSTRING (prop
)->data
, False
);
11706 XDeleteProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), prop_atom
);
11708 /* Make sure the property is removed when we return. */
11709 XFlush (FRAME_W32_DISPLAY (f
));
11711 #endif /* NTEMACS_TODO */
11717 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
11719 "Value is the value of window property PROP on FRAME.\n\
11720 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
11721 if FRAME hasn't a property with name PROP or if PROP has no string\n\
11724 Lisp_Object prop
, frame
;
11726 #if 0 /* NTEMACS_TODO : port window properties to W32 */
11728 struct frame
*f
= check_x_frame (frame
);
11731 Lisp_Object prop_value
= Qnil
;
11732 char *tmp_data
= NULL
;
11735 unsigned long actual_size
, bytes_remaining
;
11737 CHECK_STRING (prop
, 1);
11739 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), XSTRING (prop
)->data
, False
);
11740 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
11741 prop_atom
, 0, 0, False
, XA_STRING
,
11742 &actual_type
, &actual_format
, &actual_size
,
11743 &bytes_remaining
, (unsigned char **) &tmp_data
);
11746 int size
= bytes_remaining
;
11751 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
11752 prop_atom
, 0, bytes_remaining
,
11754 &actual_type
, &actual_format
,
11755 &actual_size
, &bytes_remaining
,
11756 (unsigned char **) &tmp_data
);
11758 prop_value
= make_string (tmp_data
, size
);
11767 #endif /* NTEMACS_TODO */
11773 /***********************************************************************
11775 ***********************************************************************/
11777 /* If non-null, an asynchronous timer that, when it expires, displays
11778 a busy cursor on all frames. */
11780 static struct atimer
*busy_cursor_atimer
;
11782 /* Non-zero means a busy cursor is currently shown. */
11784 static int busy_cursor_shown_p
;
11786 /* Number of seconds to wait before displaying a busy cursor. */
11788 static Lisp_Object Vbusy_cursor_delay
;
11790 /* Default number of seconds to wait before displaying a busy
11793 #define DEFAULT_BUSY_CURSOR_DELAY 1
11795 /* Function prototypes. */
11797 static void show_busy_cursor
P_ ((struct atimer
*));
11798 static void hide_busy_cursor
P_ ((void));
11801 /* Cancel a currently active busy-cursor timer, and start a new one. */
11804 start_busy_cursor ()
11806 #if 0 /* NTEMACS_TODO: cursor shape changes. */
11808 int secs
, usecs
= 0;
11810 cancel_busy_cursor ();
11812 if (INTEGERP (Vbusy_cursor_delay
)
11813 && XINT (Vbusy_cursor_delay
) > 0)
11814 secs
= XFASTINT (Vbusy_cursor_delay
);
11815 else if (FLOATP (Vbusy_cursor_delay
)
11816 && XFLOAT_DATA (Vbusy_cursor_delay
) > 0)
11819 tem
= Ftruncate (Vbusy_cursor_delay
, Qnil
);
11820 secs
= XFASTINT (tem
);
11821 usecs
= (XFLOAT_DATA (Vbusy_cursor_delay
) - secs
) * 1000000;
11824 secs
= DEFAULT_BUSY_CURSOR_DELAY
;
11826 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
11827 busy_cursor_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
11828 show_busy_cursor
, NULL
);
11833 /* Cancel the busy cursor timer if active, hide a busy cursor if
11837 cancel_busy_cursor ()
11839 if (busy_cursor_atimer
)
11841 cancel_atimer (busy_cursor_atimer
);
11842 busy_cursor_atimer
= NULL
;
11845 if (busy_cursor_shown_p
)
11846 hide_busy_cursor ();
11850 /* Timer function of busy_cursor_atimer. TIMER is equal to
11851 busy_cursor_atimer.
11853 Display a busy cursor on all frames by mapping the frames'
11854 busy_window. Set the busy_p flag in the frames' output_data.x
11855 structure to indicate that a busy cursor is shown on the
11859 show_busy_cursor (timer
)
11860 struct atimer
*timer
;
11862 #if 0 /* NTEMACS_TODO: cursor shape changes. */
11863 /* The timer implementation will cancel this timer automatically
11864 after this function has run. Set busy_cursor_atimer to null
11865 so that we know the timer doesn't have to be canceled. */
11866 busy_cursor_atimer
= NULL
;
11868 if (!busy_cursor_shown_p
)
11870 Lisp_Object rest
, frame
;
11874 FOR_EACH_FRAME (rest
, frame
)
11875 if (FRAME_X_P (XFRAME (frame
)))
11877 struct frame
*f
= XFRAME (frame
);
11879 f
->output_data
.w32
->busy_p
= 1;
11881 if (!f
->output_data
.w32
->busy_window
)
11883 unsigned long mask
= CWCursor
;
11884 XSetWindowAttributes attrs
;
11886 attrs
.cursor
= f
->output_data
.w32
->busy_cursor
;
11888 f
->output_data
.w32
->busy_window
11889 = XCreateWindow (FRAME_X_DISPLAY (f
),
11890 FRAME_OUTER_WINDOW (f
),
11891 0, 0, 32000, 32000, 0, 0,
11897 XMapRaised (FRAME_X_DISPLAY (f
), f
->output_data
.w32
->busy_window
);
11898 XFlush (FRAME_X_DISPLAY (f
));
11901 busy_cursor_shown_p
= 1;
11908 /* Hide the busy cursor on all frames, if it is currently shown. */
11911 hide_busy_cursor ()
11913 #if 0 /* NTEMACS_TODO: cursor shape changes. */
11914 if (busy_cursor_shown_p
)
11916 Lisp_Object rest
, frame
;
11919 FOR_EACH_FRAME (rest
, frame
)
11921 struct frame
*f
= XFRAME (frame
);
11924 /* Watch out for newly created frames. */
11925 && f
->output_data
.x
->busy_window
)
11927 XUnmapWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
11928 /* Sync here because XTread_socket looks at the busy_p flag
11929 that is reset to zero below. */
11930 XSync (FRAME_X_DISPLAY (f
), False
);
11931 f
->output_data
.x
->busy_p
= 0;
11935 busy_cursor_shown_p
= 0;
11943 /***********************************************************************
11945 ***********************************************************************/
11947 static Lisp_Object x_create_tip_frame
P_ ((struct w32_display_info
*,
11950 /* The frame of a currently visible tooltip, or null. */
11952 struct frame
*tip_frame
;
11954 /* If non-nil, a timer started that hides the last tooltip when it
11957 Lisp_Object tip_timer
;
11960 /* Create a frame for a tooltip on the display described by DPYINFO.
11961 PARMS is a list of frame parameters. Value is the frame. */
11964 x_create_tip_frame (dpyinfo
, parms
)
11965 struct w32_display_info
*dpyinfo
;
11968 #if 0 /* NTEMACS_TODO : w32 version */
11970 Lisp_Object frame
, tem
;
11972 long window_prompting
= 0;
11974 int count
= specpdl_ptr
- specpdl
;
11975 struct gcpro gcpro1
, gcpro2
, gcpro3
;
11980 /* Use this general default value to start with until we know if
11981 this frame has a specified name. */
11982 Vx_resource_name
= Vinvocation_name
;
11984 #ifdef MULTI_KBOARD
11985 kb
= dpyinfo
->kboard
;
11987 kb
= &the_only_kboard
;
11990 /* Get the name of the frame to use for resource lookup. */
11991 name
= w32_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
11992 if (!STRINGP (name
)
11993 && !EQ (name
, Qunbound
)
11995 error ("Invalid frame name--not a string or nil");
11996 Vx_resource_name
= name
;
11999 GCPRO3 (parms
, name
, frame
);
12000 tip_frame
= f
= make_frame (1);
12001 XSETFRAME (frame
, f
);
12002 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
12004 f
->output_method
= output_w32
;
12005 f
->output_data
.w32
=
12006 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
12007 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
12009 f
->output_data
.w32
->icon_bitmap
= -1;
12011 f
->output_data
.w32
->fontset
= -1;
12012 f
->icon_name
= Qnil
;
12014 #ifdef MULTI_KBOARD
12015 FRAME_KBOARD (f
) = kb
;
12017 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
12018 f
->output_data
.w32
->explicit_parent
= 0;
12020 /* Set the name; the functions to which we pass f expect the name to
12022 if (EQ (name
, Qunbound
) || NILP (name
))
12024 f
->name
= build_string (dpyinfo
->x_id_name
);
12025 f
->explicit_name
= 0;
12030 f
->explicit_name
= 1;
12031 /* use the frame's title when getting resources for this frame. */
12032 specbind (Qx_resource_name
, name
);
12035 /* Extract the window parameters from the supplied values
12036 that are needed to determine window geometry. */
12040 font
= w32_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
12043 /* First, try whatever font the caller has specified. */
12044 if (STRINGP (font
))
12046 tem
= Fquery_fontset (font
, Qnil
);
12048 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
12050 font
= x_new_font (f
, XSTRING (font
)->data
);
12053 /* Try out a font which we hope has bold and italic variations. */
12054 if (!STRINGP (font
))
12055 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
12056 if (!STRINGP (font
))
12057 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
12058 if (! STRINGP (font
))
12059 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
12060 if (! STRINGP (font
))
12061 /* This was formerly the first thing tried, but it finds too many fonts
12062 and takes too long. */
12063 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
12064 /* If those didn't work, look for something which will at least work. */
12065 if (! STRINGP (font
))
12066 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
12068 if (! STRINGP (font
))
12069 font
= build_string ("fixed");
12071 x_default_parameter (f
, parms
, Qfont
, font
,
12072 "font", "Font", RES_TYPE_STRING
);
12075 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
12076 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
12078 /* This defaults to 2 in order to match xterm. We recognize either
12079 internalBorderWidth or internalBorder (which is what xterm calls
12081 if (NILP (Fassq (Qinternal_border_width
, parms
)))
12085 value
= w32_get_arg (parms
, Qinternal_border_width
,
12086 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
12087 if (! EQ (value
, Qunbound
))
12088 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
12092 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
12093 "internalBorderWidth", "internalBorderWidth",
12096 /* Also do the stuff which must be set before the window exists. */
12097 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
12098 "foreground", "Foreground", RES_TYPE_STRING
);
12099 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
12100 "background", "Background", RES_TYPE_STRING
);
12101 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
12102 "pointerColor", "Foreground", RES_TYPE_STRING
);
12103 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
12104 "cursorColor", "Foreground", RES_TYPE_STRING
);
12105 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
12106 "borderColor", "BorderColor", RES_TYPE_STRING
);
12108 /* Init faces before x_default_parameter is called for scroll-bar
12109 parameters because that function calls x_set_scroll_bar_width,
12110 which calls change_frame_size, which calls Fset_window_buffer,
12111 which runs hooks, which call Fvertical_motion. At the end, we
12112 end up in init_iterator with a null face cache, which should not
12114 init_frame_faces (f
);
12116 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
12117 window_prompting
= x_figure_window_size (f
, parms
);
12119 if (window_prompting
& XNegative
)
12121 if (window_prompting
& YNegative
)
12122 f
->output_data
.w32
->win_gravity
= SouthEastGravity
;
12124 f
->output_data
.w32
->win_gravity
= NorthEastGravity
;
12128 if (window_prompting
& YNegative
)
12129 f
->output_data
.w32
->win_gravity
= SouthWestGravity
;
12131 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
12134 f
->output_data
.w32
->size_hint_flags
= window_prompting
;
12136 XSetWindowAttributes attrs
;
12137 unsigned long mask
;
12140 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
12141 /* Window managers looks at the override-redirect flag to
12142 determine whether or net to give windows a decoration (Xlib
12144 attrs
.override_redirect
= True
;
12145 attrs
.save_under
= True
;
12146 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
12147 /* Arrange for getting MapNotify and UnmapNotify events. */
12148 attrs
.event_mask
= StructureNotifyMask
;
12150 = FRAME_W32_WINDOW (f
)
12151 = XCreateWindow (FRAME_W32_DISPLAY (f
),
12152 FRAME_W32_DISPLAY_INFO (f
)->root_window
,
12153 /* x, y, width, height */
12157 CopyFromParent
, InputOutput
, CopyFromParent
,
12164 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
12165 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
12166 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
12167 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
12168 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
12169 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
12171 /* Dimensions, especially f->height, must be done via change_frame_size.
12172 Change will not be effected unless different from the current
12175 height
= f
->height
;
12177 SET_FRAME_WIDTH (f
, 0);
12178 change_frame_size (f
, height
, width
, 1, 0, 0);
12184 /* It is now ok to make the frame official even if we get an error
12185 below. And the frame needs to be on Vframe_list or making it
12186 visible won't work. */
12187 Vframe_list
= Fcons (frame
, Vframe_list
);
12189 /* Now that the frame is official, it counts as a reference to
12191 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
12193 return unbind_to (count
, frame
);
12194 #endif /* NTEMACS_TODO */
12199 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 4, 0,
12200 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
12201 A tooltip window is a small X window displaying STRING at\n\
12202 the current mouse position.\n\
12203 FRAME nil or omitted means use the selected frame.\n\
12204 PARMS is an optional list of frame parameters which can be\n\
12205 used to change the tooltip's appearance.\n\
12206 Automatically hide the tooltip after TIMEOUT seconds.\n\
12207 TIMEOUT nil means use the default timeout of 5 seconds.")
12208 (string
, frame
, parms
, timeout
)
12209 Lisp_Object string
, frame
, parms
, timeout
;
12213 Window root
, child
;
12214 Lisp_Object buffer
;
12215 struct buffer
*old_buffer
;
12216 struct text_pos pos
;
12217 int i
, width
, height
;
12218 int root_x
, root_y
, win_x
, win_y
;
12220 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
12221 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
12222 int count
= specpdl_ptr
- specpdl
;
12224 specbind (Qinhibit_redisplay
, Qt
);
12226 GCPRO4 (string
, parms
, frame
, timeout
);
12228 CHECK_STRING (string
, 0);
12229 f
= check_x_frame (frame
);
12230 if (NILP (timeout
))
12231 timeout
= make_number (5);
12233 CHECK_NATNUM (timeout
, 2);
12235 /* Hide a previous tip, if any. */
12238 /* Add default values to frame parameters. */
12239 if (NILP (Fassq (Qname
, parms
)))
12240 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
12241 if (NILP (Fassq (Qinternal_border_width
, parms
)))
12242 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
12243 if (NILP (Fassq (Qborder_width
, parms
)))
12244 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
12245 if (NILP (Fassq (Qborder_color
, parms
)))
12246 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
12247 if (NILP (Fassq (Qbackground_color
, parms
)))
12248 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
12251 /* Create a frame for the tooltip, and record it in the global
12252 variable tip_frame. */
12253 frame
= x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f
), parms
);
12254 tip_frame
= f
= XFRAME (frame
);
12256 /* Set up the frame's root window. Currently we use a size of 80
12257 columns x 40 lines. If someone wants to show a larger tip, he
12258 will loose. I don't think this is a realistic case. */
12259 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
12260 w
->left
= w
->top
= make_number (0);
12264 w
->pseudo_window_p
= 1;
12266 /* Display the tooltip text in a temporary buffer. */
12267 buffer
= Fget_buffer_create (build_string (" *tip*"));
12268 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
12269 old_buffer
= current_buffer
;
12270 set_buffer_internal_1 (XBUFFER (buffer
));
12272 Finsert (make_number (1), &string
);
12273 clear_glyph_matrix (w
->desired_matrix
);
12274 clear_glyph_matrix (w
->current_matrix
);
12275 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
12276 try_window (FRAME_ROOT_WINDOW (f
), pos
);
12278 /* Compute width and height of the tooltip. */
12279 width
= height
= 0;
12280 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
12282 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
12283 struct glyph
*last
;
12286 /* Stop at the first empty row at the end. */
12287 if (!row
->enabled_p
|| !row
->displays_text_p
)
12290 /* Let the row go over the full width of the frame. */
12291 row
->full_width_p
= 1;
12293 /* There's a glyph at the end of rows that is use to place
12294 the cursor there. Don't include the width of this glyph. */
12295 if (row
->used
[TEXT_AREA
])
12297 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
12298 row_width
= row
->pixel_width
- last
->pixel_width
;
12301 row_width
= row
->pixel_width
;
12303 height
+= row
->height
;
12304 width
= max (width
, row_width
);
12307 /* Add the frame's internal border to the width and height the X
12308 window should have. */
12309 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
12310 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
12312 /* Move the tooltip window where the mouse pointer is. Resize and
12314 #if 0 /* NTEMACS_TODO : W32 specifics */
12316 XQueryPointer (FRAME_W32_DISPLAY (f
), FRAME_W32_DISPLAY_INFO (f
)->root_window
,
12317 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
12318 XMoveResizeWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
12319 root_x
+ 5, root_y
- height
- 5, width
, height
);
12320 XMapRaised (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
12322 #endif /* NTEMACS_TODO */
12324 /* Draw into the window. */
12325 w
->must_be_updated_p
= 1;
12326 update_single_window (w
, 1);
12328 /* Restore original current buffer. */
12329 set_buffer_internal_1 (old_buffer
);
12330 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
12332 /* Let the tip disappear after timeout seconds. */
12333 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
12334 intern ("x-hide-tip"));
12337 return unbind_to (count
, Qnil
);
12341 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
12342 "Hide the current tooltip window, if there is any.\n\
12343 Value is t is tooltip was open, nil otherwise.")
12346 int count
= specpdl_ptr
- specpdl
;
12349 specbind (Qinhibit_redisplay
, Qt
);
12351 if (!NILP (tip_timer
))
12353 call1 (intern ("cancel-timer"), tip_timer
);
12361 XSETFRAME (frame
, tip_frame
);
12362 Fdelete_frame (frame
, Qt
);
12367 return unbind_to (count
, deleted_p
? Qt
: Qnil
);
12372 /***********************************************************************
12373 File selection dialog
12374 ***********************************************************************/
12376 extern Lisp_Object Qfile_name_history
;
12378 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
12379 "Read file name, prompting with PROMPT in directory DIR.\n\
12380 Use a file selection dialog.\n\
12381 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
12382 specified. Don't let the user enter a file name in the file\n\
12383 selection dialog's entry field, if MUSTMATCH is non-nil.")
12384 (prompt
, dir
, default_filename
, mustmatch
)
12385 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
12387 struct frame
*f
= SELECTED_FRAME ();
12388 Lisp_Object file
= Qnil
;
12389 int count
= specpdl_ptr
- specpdl
;
12390 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
12391 char filename
[MAX_PATH
+ 1];
12392 char init_dir
[MAX_PATH
+ 1];
12393 int use_dialog_p
= 1;
12395 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
12396 CHECK_STRING (prompt
, 0);
12397 CHECK_STRING (dir
, 1);
12399 /* Create the dialog with PROMPT as title, using DIR as initial
12400 directory and using "*" as pattern. */
12401 dir
= Fexpand_file_name (dir
, Qnil
);
12402 strncpy (init_dir
, XSTRING (dir
)->data
, MAX_PATH
);
12403 init_dir
[MAX_PATH
] = '\0';
12404 unixtodos_filename (init_dir
);
12406 if (STRINGP (default_filename
))
12408 char *file_name_only
;
12409 char *full_path_name
= XSTRING (default_filename
)->data
;
12411 unixtodos_filename (full_path_name
);
12413 file_name_only
= strrchr (full_path_name
, '\\');
12414 if (!file_name_only
)
12415 file_name_only
= full_path_name
;
12420 /* If default_file_name is a directory, don't use the open
12421 file dialog, as it does not support selecting
12423 if (!(*file_name_only
))
12427 strncpy (filename
, file_name_only
, MAX_PATH
);
12428 filename
[MAX_PATH
] = '\0';
12431 filename
[0] = '\0';
12435 OPENFILENAME file_details
;
12436 char *filename_file
;
12438 /* Prevent redisplay. */
12439 specbind (Qinhibit_redisplay
, Qt
);
12442 bzero (&file_details
, sizeof (file_details
));
12443 file_details
.lStructSize
= sizeof (file_details
);
12444 file_details
.hwndOwner
= FRAME_W32_WINDOW (f
);
12445 file_details
.lpstrFile
= filename
;
12446 file_details
.nMaxFile
= sizeof (filename
);
12447 file_details
.lpstrInitialDir
= init_dir
;
12448 file_details
.lpstrTitle
= XSTRING (prompt
)->data
;
12449 file_details
.Flags
= OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
;
12451 if (!NILP (mustmatch
))
12452 file_details
.Flags
|= OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
;
12454 if (GetOpenFileName (&file_details
))
12456 dostounix_filename (filename
);
12457 file
= build_string (filename
);
12463 file
= unbind_to (count
, file
);
12465 /* Open File dialog will not allow folders to be selected, so resort
12466 to minibuffer completing reads for directories. */
12468 file
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
12469 dir
, mustmatch
, dir
, Qfile_name_history
,
12470 default_filename
, Qnil
);
12474 /* Make "Cancel" equivalent to C-g. */
12476 Fsignal (Qquit
, Qnil
);
12478 return unbind_to (count
, file
);
12483 /***********************************************************************
12485 ***********************************************************************/
12489 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
12490 "Value is non-nil if SPEC is a valid image specification.")
12494 return valid_image_p (spec
) ? Qt
: Qnil
;
12498 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
12504 if (valid_image_p (spec
))
12505 id
= lookup_image (SELECTED_FRAME (), spec
);
12507 debug_print (spec
);
12508 return make_number (id
);
12511 #endif /* GLYPH_DEBUG != 0 */
12515 /***********************************************************************
12516 w32 specialized functions
12517 ***********************************************************************/
12519 DEFUN ("w32-select-font", Fw32_select_font
, Sw32_select_font
, 0, 1, 0,
12520 "This will display the W32 font dialog and return an X font string corresponding to the selection.")
12524 FRAME_PTR f
= check_x_frame (frame
);
12532 bzero (&cf
, sizeof (cf
));
12533 bzero (&lf
, sizeof (lf
));
12535 cf
.lStructSize
= sizeof (cf
);
12536 cf
.hwndOwner
= FRAME_W32_WINDOW (f
);
12537 cf
.Flags
= CF_FORCEFONTEXIST
| CF_SCREENFONTS
;
12538 cf
.lpLogFont
= &lf
;
12540 /* Initialize as much of the font details as we can from the current
12542 hdc
= GetDC (FRAME_W32_WINDOW (f
));
12543 oldobj
= SelectObject (hdc
, FRAME_FONT (f
)->hfont
);
12544 GetTextFace (hdc
, LF_FACESIZE
, lf
.lfFaceName
);
12545 if (GetTextMetrics (hdc
, &tm
))
12547 lf
.lfHeight
= tm
.tmInternalLeading
- tm
.tmHeight
;
12548 lf
.lfWeight
= tm
.tmWeight
;
12549 lf
.lfItalic
= tm
.tmItalic
;
12550 lf
.lfUnderline
= tm
.tmUnderlined
;
12551 lf
.lfStrikeOut
= tm
.tmStruckOut
;
12552 lf
.lfCharSet
= tm
.tmCharSet
;
12553 cf
.Flags
|= CF_INITTOLOGFONTSTRUCT
;
12555 SelectObject (hdc
, oldobj
);
12556 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
12558 if (!ChooseFont (&cf
) || !w32_to_x_font (&lf
, buf
, 100))
12561 return build_string (buf
);
12564 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
, Sw32_send_sys_command
, 1, 2, 0,
12565 "Send frame a Windows WM_SYSCOMMAND message of type COMMAND.\n\
12566 Some useful values for command are 0xf030 to maximise frame (0xf020\n\
12567 to minimize), 0xf120 to restore frame to original size, and 0xf100\n\
12568 to activate the menubar for keyboard access. 0xf140 activates the\n\
12569 screen saver if defined.\n\
12571 If optional parameter FRAME is not specified, use selected frame.")
12573 Lisp_Object command
, frame
;
12576 FRAME_PTR f
= check_x_frame (frame
);
12578 CHECK_NUMBER (command
, 0);
12580 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
12585 DEFUN ("w32-shell-execute", Fw32_shell_execute
, Sw32_shell_execute
, 2, 4, 0,
12586 "Get Windows to perform OPERATION on DOCUMENT.\n\
12587 This is a wrapper around the ShellExecute system function, which\n\
12588 invokes the application registered to handle OPERATION for DOCUMENT.\n\
12589 OPERATION is typically \"open\", \"print\" or \"explore\" (but can be\n\
12590 nil for the default action), and DOCUMENT is typically the name of a\n\
12591 document file or URL, but can also be a program executable to run or\n\
12592 a directory to open in the Windows Explorer.\n\
12594 If DOCUMENT is a program executable, PARAMETERS can be a string\n\
12595 containing command line parameters, but otherwise should be nil.\n\
12597 SHOW-FLAG can be used to control whether the invoked application is hidden\n\
12598 or minimized. If SHOW-FLAG is nil, the application is displayed normally,\n\
12599 otherwise it is an integer representing a ShowWindow flag:\n\
12601 0 - start hidden\n\
12602 1 - start normally\n\
12603 3 - start maximized\n\
12604 6 - start minimized")
12605 (operation
, document
, parameters
, show_flag
)
12606 Lisp_Object operation
, document
, parameters
, show_flag
;
12608 Lisp_Object current_dir
;
12610 CHECK_STRING (document
, 0);
12612 /* Encode filename and current directory. */
12613 current_dir
= ENCODE_FILE (current_buffer
->directory
);
12614 document
= ENCODE_FILE (document
);
12615 if ((int) ShellExecute (NULL
,
12616 (STRINGP (operation
) ?
12617 XSTRING (operation
)->data
: NULL
),
12618 XSTRING (document
)->data
,
12619 (STRINGP (parameters
) ?
12620 XSTRING (parameters
)->data
: NULL
),
12621 XSTRING (current_dir
)->data
,
12622 (INTEGERP (show_flag
) ?
12623 XINT (show_flag
) : SW_SHOWDEFAULT
))
12626 error ("ShellExecute failed");
12629 /* Lookup virtual keycode from string representing the name of a
12630 non-ascii keystroke into the corresponding virtual key, using
12631 lispy_function_keys. */
12633 lookup_vk_code (char *key
)
12637 for (i
= 0; i
< 256; i
++)
12638 if (lispy_function_keys
[i
] != 0
12639 && strcmp (lispy_function_keys
[i
], key
) == 0)
12645 /* Convert a one-element vector style key sequence to a hot key
12648 w32_parse_hot_key (key
)
12651 /* Copied from Fdefine_key and store_in_keymap. */
12652 register Lisp_Object c
;
12654 int lisp_modifiers
;
12656 struct gcpro gcpro1
;
12658 CHECK_VECTOR (key
, 0);
12660 if (XFASTINT (Flength (key
)) != 1)
12665 c
= Faref (key
, make_number (0));
12667 if (CONSP (c
) && lucid_event_type_list_p (c
))
12668 c
= Fevent_convert_list (c
);
12672 if (! INTEGERP (c
) && ! SYMBOLP (c
))
12673 error ("Key definition is invalid");
12675 /* Work out the base key and the modifiers. */
12678 c
= parse_modifiers (c
);
12679 lisp_modifiers
= Fcar (Fcdr (c
));
12683 vk_code
= lookup_vk_code (XSYMBOL (c
)->name
->data
);
12685 else if (INTEGERP (c
))
12687 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
12688 /* Many ascii characters are their own virtual key code. */
12689 vk_code
= XINT (c
) & CHARACTERBITS
;
12692 if (vk_code
< 0 || vk_code
> 255)
12695 if ((lisp_modifiers
& meta_modifier
) != 0
12696 && !NILP (Vw32_alt_is_meta
))
12697 lisp_modifiers
|= alt_modifier
;
12699 /* Convert lisp modifiers to Windows hot-key form. */
12700 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
12701 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
12702 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
12703 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
12705 return HOTKEY (vk_code
, w32_modifiers
);
12708 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
, Sw32_register_hot_key
, 1, 1, 0,
12709 "Register KEY as a hot-key combination.\n\
12710 Certain key combinations like Alt-Tab are reserved for system use on\n\
12711 Windows, and therefore are normally intercepted by the system. However,\n\
12712 most of these key combinations can be received by registering them as\n\
12713 hot-keys, overriding their special meaning.\n\
12715 KEY must be a one element key definition in vector form that would be\n\
12716 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta\n\
12717 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper\n\
12718 is always interpreted as the Windows modifier keys.\n\
12720 The return value is the hotkey-id if registered, otherwise nil.")
12724 key
= w32_parse_hot_key (key
);
12726 if (NILP (Fmemq (key
, w32_grabbed_keys
)))
12728 /* Reuse an empty slot if possible. */
12729 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
12731 /* Safe to add new key to list, even if we have focus. */
12733 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
12737 /* Notify input thread about new hot-key definition, so that it
12738 takes effect without needing to switch focus. */
12739 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
12746 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
, Sw32_unregister_hot_key
, 1, 1, 0,
12747 "Unregister HOTKEY as a hot-key combination.")
12753 if (!INTEGERP (key
))
12754 key
= w32_parse_hot_key (key
);
12756 item
= Fmemq (key
, w32_grabbed_keys
);
12760 /* Notify input thread about hot-key definition being removed, so
12761 that it takes effect without needing focus switch. */
12762 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
12763 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
))
12766 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
12773 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
, Sw32_registered_hot_keys
, 0, 0, 0,
12774 "Return list of registered hot-key IDs.")
12777 return Fcopy_sequence (w32_grabbed_keys
);
12780 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
, Sw32_reconstruct_hot_key
, 1, 1, 0,
12781 "Convert hot-key ID to a lisp key combination.")
12783 Lisp_Object hotkeyid
;
12785 int vk_code
, w32_modifiers
;
12788 CHECK_NUMBER (hotkeyid
, 0);
12790 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
12791 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
12793 if (lispy_function_keys
[vk_code
])
12794 key
= intern (lispy_function_keys
[vk_code
]);
12796 key
= make_number (vk_code
);
12798 key
= Fcons (key
, Qnil
);
12799 if (w32_modifiers
& MOD_SHIFT
)
12800 key
= Fcons (Qshift
, key
);
12801 if (w32_modifiers
& MOD_CONTROL
)
12802 key
= Fcons (Qctrl
, key
);
12803 if (w32_modifiers
& MOD_ALT
)
12804 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
12805 if (w32_modifiers
& MOD_WIN
)
12806 key
= Fcons (Qhyper
, key
);
12811 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
, Sw32_toggle_lock_key
, 1, 2, 0,
12812 "Toggle the state of the lock key KEY.\n\
12813 KEY can be `capslock', `kp-numlock', or `scroll'.\n\
12814 If the optional parameter NEW-STATE is a number, then the state of KEY\n\
12815 is set to off if the low bit of NEW-STATE is zero, otherwise on.")
12817 Lisp_Object key
, new_state
;
12822 if (EQ (key
, intern ("capslock")))
12823 vk_code
= VK_CAPITAL
;
12824 else if (EQ (key
, intern ("kp-numlock")))
12825 vk_code
= VK_NUMLOCK
;
12826 else if (EQ (key
, intern ("scroll")))
12827 vk_code
= VK_SCROLL
;
12831 if (!dwWindowsThreadId
)
12832 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
12834 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
12835 (WPARAM
) vk_code
, (LPARAM
) new_state
))
12838 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
12839 return make_number (msg
.wParam
);
12846 /* This is zero if not using MS-Windows. */
12849 /* The section below is built by the lisp expression at the top of the file,
12850 just above where these variables are declared. */
12851 /*&&& init symbols here &&&*/
12852 Qauto_raise
= intern ("auto-raise");
12853 staticpro (&Qauto_raise
);
12854 Qauto_lower
= intern ("auto-lower");
12855 staticpro (&Qauto_lower
);
12856 Qbar
= intern ("bar");
12858 Qborder_color
= intern ("border-color");
12859 staticpro (&Qborder_color
);
12860 Qborder_width
= intern ("border-width");
12861 staticpro (&Qborder_width
);
12862 Qbox
= intern ("box");
12864 Qcursor_color
= intern ("cursor-color");
12865 staticpro (&Qcursor_color
);
12866 Qcursor_type
= intern ("cursor-type");
12867 staticpro (&Qcursor_type
);
12868 Qgeometry
= intern ("geometry");
12869 staticpro (&Qgeometry
);
12870 Qicon_left
= intern ("icon-left");
12871 staticpro (&Qicon_left
);
12872 Qicon_top
= intern ("icon-top");
12873 staticpro (&Qicon_top
);
12874 Qicon_type
= intern ("icon-type");
12875 staticpro (&Qicon_type
);
12876 Qicon_name
= intern ("icon-name");
12877 staticpro (&Qicon_name
);
12878 Qinternal_border_width
= intern ("internal-border-width");
12879 staticpro (&Qinternal_border_width
);
12880 Qleft
= intern ("left");
12881 staticpro (&Qleft
);
12882 Qright
= intern ("right");
12883 staticpro (&Qright
);
12884 Qmouse_color
= intern ("mouse-color");
12885 staticpro (&Qmouse_color
);
12886 Qnone
= intern ("none");
12887 staticpro (&Qnone
);
12888 Qparent_id
= intern ("parent-id");
12889 staticpro (&Qparent_id
);
12890 Qscroll_bar_width
= intern ("scroll-bar-width");
12891 staticpro (&Qscroll_bar_width
);
12892 Qsuppress_icon
= intern ("suppress-icon");
12893 staticpro (&Qsuppress_icon
);
12894 Qundefined_color
= intern ("undefined-color");
12895 staticpro (&Qundefined_color
);
12896 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
12897 staticpro (&Qvertical_scroll_bars
);
12898 Qvisibility
= intern ("visibility");
12899 staticpro (&Qvisibility
);
12900 Qwindow_id
= intern ("window-id");
12901 staticpro (&Qwindow_id
);
12902 Qx_frame_parameter
= intern ("x-frame-parameter");
12903 staticpro (&Qx_frame_parameter
);
12904 Qx_resource_name
= intern ("x-resource-name");
12905 staticpro (&Qx_resource_name
);
12906 Quser_position
= intern ("user-position");
12907 staticpro (&Quser_position
);
12908 Quser_size
= intern ("user-size");
12909 staticpro (&Quser_size
);
12910 Qscreen_gamma
= intern ("screen-gamma");
12911 staticpro (&Qscreen_gamma
);
12912 Qline_spacing
= intern ("line-spacing");
12913 staticpro (&Qline_spacing
);
12914 Qcenter
= intern ("center");
12915 staticpro (&Qcenter
);
12916 /* This is the end of symbol initialization. */
12918 Qhyper
= intern ("hyper");
12919 staticpro (&Qhyper
);
12920 Qsuper
= intern ("super");
12921 staticpro (&Qsuper
);
12922 Qmeta
= intern ("meta");
12923 staticpro (&Qmeta
);
12924 Qalt
= intern ("alt");
12926 Qctrl
= intern ("ctrl");
12927 staticpro (&Qctrl
);
12928 Qcontrol
= intern ("control");
12929 staticpro (&Qcontrol
);
12930 Qshift
= intern ("shift");
12931 staticpro (&Qshift
);
12933 /* Text property `display' should be nonsticky by default. */
12934 Vtext_property_default_nonsticky
12935 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
12938 Qlaplace
= intern ("laplace");
12939 staticpro (&Qlaplace
);
12941 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
12942 staticpro (&Qface_set_after_frame_default
);
12944 Fput (Qundefined_color
, Qerror_conditions
,
12945 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
12946 Fput (Qundefined_color
, Qerror_message
,
12947 build_string ("Undefined color"));
12949 staticpro (&w32_grabbed_keys
);
12950 w32_grabbed_keys
= Qnil
;
12952 DEFVAR_LISP ("w32-color-map", &Vw32_color_map
,
12953 "An array of color name mappings for windows.");
12954 Vw32_color_map
= Qnil
;
12956 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system
,
12957 "Non-nil if alt key presses are passed on to Windows.\n\
12958 When non-nil, for example, alt pressed and released and then space will\n\
12959 open the System menu. When nil, Emacs silently swallows alt key events.");
12960 Vw32_pass_alt_to_system
= Qnil
;
12962 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta
,
12963 "Non-nil if the alt key is to be considered the same as the meta key.\n\
12964 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
12965 Vw32_alt_is_meta
= Qt
;
12967 DEFVAR_INT ("w32-quit-key", &Vw32_quit_key
,
12968 "If non-zero, the virtual key code for an alternative quit key.");
12969 XSETINT (Vw32_quit_key
, 0);
12971 DEFVAR_LISP ("w32-pass-lwindow-to-system",
12972 &Vw32_pass_lwindow_to_system
,
12973 "Non-nil if the left \"Windows\" key is passed on to Windows.\n\
12974 When non-nil, the Start menu is opened by tapping the key.");
12975 Vw32_pass_lwindow_to_system
= Qt
;
12977 DEFVAR_LISP ("w32-pass-rwindow-to-system",
12978 &Vw32_pass_rwindow_to_system
,
12979 "Non-nil if the right \"Windows\" key is passed on to Windows.\n\
12980 When non-nil, the Start menu is opened by tapping the key.");
12981 Vw32_pass_rwindow_to_system
= Qt
;
12983 DEFVAR_INT ("w32-phantom-key-code",
12984 &Vw32_phantom_key_code
,
12985 "Virtual key code used to generate \"phantom\" key presses.\n\
12986 Value is a number between 0 and 255.\n\
12988 Phantom key presses are generated in order to stop the system from\n\
12989 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or\n\
12990 `w32-pass-rwindow-to-system' is nil.");
12991 /* Although 255 is technically not a valid key code, it works and
12992 means that this hack won't interfere with any real key code. */
12993 Vw32_phantom_key_code
= 255;
12995 DEFVAR_LISP ("w32-enable-num-lock",
12996 &Vw32_enable_num_lock
,
12997 "Non-nil if Num Lock should act normally.\n\
12998 Set to nil to see Num Lock as the key `kp-numlock'.");
12999 Vw32_enable_num_lock
= Qt
;
13001 DEFVAR_LISP ("w32-enable-caps-lock",
13002 &Vw32_enable_caps_lock
,
13003 "Non-nil if Caps Lock should act normally.\n\
13004 Set to nil to see Caps Lock as the key `capslock'.");
13005 Vw32_enable_caps_lock
= Qt
;
13007 DEFVAR_LISP ("w32-scroll-lock-modifier",
13008 &Vw32_scroll_lock_modifier
,
13009 "Modifier to use for the Scroll Lock on state.\n\
13010 The value can be hyper, super, meta, alt, control or shift for the\n\
13011 respective modifier, or nil to see Scroll Lock as the key `scroll'.\n\
13012 Any other value will cause the key to be ignored.");
13013 Vw32_scroll_lock_modifier
= Qt
;
13015 DEFVAR_LISP ("w32-lwindow-modifier",
13016 &Vw32_lwindow_modifier
,
13017 "Modifier to use for the left \"Windows\" key.\n\
13018 The value can be hyper, super, meta, alt, control or shift for the\n\
13019 respective modifier, or nil to appear as the key `lwindow'.\n\
13020 Any other value will cause the key to be ignored.");
13021 Vw32_lwindow_modifier
= Qnil
;
13023 DEFVAR_LISP ("w32-rwindow-modifier",
13024 &Vw32_rwindow_modifier
,
13025 "Modifier to use for the right \"Windows\" key.\n\
13026 The value can be hyper, super, meta, alt, control or shift for the\n\
13027 respective modifier, or nil to appear as the key `rwindow'.\n\
13028 Any other value will cause the key to be ignored.");
13029 Vw32_rwindow_modifier
= Qnil
;
13031 DEFVAR_LISP ("w32-apps-modifier",
13032 &Vw32_apps_modifier
,
13033 "Modifier to use for the \"Apps\" key.\n\
13034 The value can be hyper, super, meta, alt, control or shift for the\n\
13035 respective modifier, or nil to appear as the key `apps'.\n\
13036 Any other value will cause the key to be ignored.");
13037 Vw32_apps_modifier
= Qnil
;
13039 DEFVAR_LISP ("w32-enable-synthesized_fonts", &Vw32_enable_synthesized_fonts
,
13040 "Non-nil enables selection of artificially italicized and bold fonts.");
13041 Vw32_enable_synthesized_fonts
= Qnil
;
13043 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette
,
13044 "Non-nil enables Windows palette management to map colors exactly.");
13045 Vw32_enable_palette
= Qt
;
13047 DEFVAR_INT ("w32-mouse-button-tolerance",
13048 &Vw32_mouse_button_tolerance
,
13049 "Analogue of double click interval for faking middle mouse events.\n\
13050 The value is the minimum time in milliseconds that must elapse between\n\
13051 left/right button down events before they are considered distinct events.\n\
13052 If both mouse buttons are depressed within this interval, a middle mouse\n\
13053 button down event is generated instead.");
13054 XSETINT (Vw32_mouse_button_tolerance
, GetDoubleClickTime () / 2);
13056 DEFVAR_INT ("w32-mouse-move-interval",
13057 &Vw32_mouse_move_interval
,
13058 "Minimum interval between mouse move events.\n\
13059 The value is the minimum time in milliseconds that must elapse between\n\
13060 successive mouse move (or scroll bar drag) events before they are\n\
13061 reported as lisp events.");
13062 XSETINT (Vw32_mouse_move_interval
, 0);
13064 init_x_parm_symbols ();
13066 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
13067 "List of directories to search for bitmap files for w32.");
13068 Vx_bitmap_file_path
= decode_env_path ((char *) 0, "PATH");
13070 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
13071 "The shape of the pointer when over text.\n\
13072 Changing the value does not affect existing frames\n\
13073 unless you set the mouse color.");
13074 Vx_pointer_shape
= Qnil
;
13076 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
13077 "The name Emacs uses to look up resources; for internal use only.\n\
13078 `x-get-resource' uses this as the first component of the instance name\n\
13079 when requesting resource values.\n\
13080 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
13081 was invoked, or to the value specified with the `-name' or `-rn'\n\
13082 switches, if present.");
13083 Vx_resource_name
= Qnil
;
13085 Vx_nontext_pointer_shape
= Qnil
;
13087 Vx_mode_pointer_shape
= Qnil
;
13089 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape
,
13090 "The shape of the pointer when Emacs is busy.\n\
13091 This variable takes effect when you create a new frame\n\
13092 or when you set the mouse color.");
13093 Vx_busy_pointer_shape
= Qnil
;
13095 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p
,
13096 "Non-zero means Emacs displays a busy cursor on window systems.");
13097 display_busy_cursor_p
= 1;
13099 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay
,
13100 "*Seconds to wait before displaying a busy-cursor.\n\
13101 Value must be an integer or float.");
13102 Vbusy_cursor_delay
= make_number (DEFAULT_BUSY_CURSOR_DELAY
);
13104 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
13105 &Vx_sensitive_text_pointer_shape
,
13106 "The shape of the pointer when over mouse-sensitive text.\n\
13107 This variable takes effect when you create a new frame\n\
13108 or when you set the mouse color.");
13109 Vx_sensitive_text_pointer_shape
= Qnil
;
13111 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
13112 "A string indicating the foreground color of the cursor box.");
13113 Vx_cursor_fore_pixel
= Qnil
;
13115 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
13116 "Non-nil if no window manager is in use.\n\
13117 Emacs doesn't try to figure this out; this is always nil\n\
13118 unless you set it to something else.");
13119 /* We don't have any way to find this out, so set it to nil
13120 and maybe the user would like to set it to t. */
13121 Vx_no_window_manager
= Qnil
;
13123 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
13124 &Vx_pixel_size_width_font_regexp
,
13125 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
13127 Since Emacs gets width of a font matching with this regexp from\n\
13128 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
13129 such a font. This is especially effective for such large fonts as\n\
13130 Chinese, Japanese, and Korean.");
13131 Vx_pixel_size_width_font_regexp
= Qnil
;
13133 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
13134 "Time after which cached images are removed from the cache.\n\
13135 When an image has not been displayed this many seconds, remove it\n\
13136 from the image cache. Value must be an integer or nil with nil\n\
13137 meaning don't clear the cache.");
13138 Vimage_cache_eviction_delay
= make_number (30 * 60);
13140 DEFVAR_LISP ("w32-bdf-filename-alist",
13141 &Vw32_bdf_filename_alist
,
13142 "List of bdf fonts and their corresponding filenames.");
13143 Vw32_bdf_filename_alist
= Qnil
;
13145 DEFVAR_BOOL ("w32-strict-fontnames",
13146 &w32_strict_fontnames
,
13147 "Non-nil means only use fonts that are exact matches for those requested.\n\
13148 Default is nil, which allows old fontnames that are not XLFD compliant,\n\
13149 and allows third-party CJK display to work by specifying false charset\n\
13150 fields to trick Emacs into translating to Big5, SJIS etc.\n\
13151 Setting this to t will prevent wrong fonts being selected when\n\
13152 fontsets are automatically created.");
13153 w32_strict_fontnames
= 0;
13155 DEFVAR_BOOL ("w32-strict-painting",
13156 &w32_strict_painting
,
13157 "Non-nil means use strict rules for repainting frames.\n\
13158 Set this to nil to get the old behaviour for repainting; this should\n\
13159 only be necessary if the default setting causes problems.");
13160 w32_strict_painting
= 1;
13162 DEFVAR_LISP ("w32-system-coding-system",
13163 &Vw32_system_coding_system
,
13164 "Coding system used by Windows system functions, such as for font names.");
13165 Vw32_system_coding_system
= Qnil
;
13167 DEFVAR_LISP ("w32-charset-info-alist",
13168 &Vw32_charset_info_alist
,
13169 "Alist linking Emacs character sets to Windows fonts\n\
13170 and codepages. Each entry should be of the form:\n\
13172 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))\n\
13174 where CHARSET_NAME is a string used in font names to identify the charset,\n\
13175 WINDOWS_CHARSET is a symbol that can be one of:\n\
13176 w32-charset-ansi, w32-charset-default, w32-charset-symbol,\n\
13177 w32-charset-shiftjis, w32-charset-hangul, w32-charset-gb2312,\n\
13178 w32-charset-chinesebig5, "
13179 #ifdef JOHAB_CHARSET
13180 "w32-charset-johab, w32-charset-hebrew,\n\
13181 w32-charset-arabic, w32-charset-greek, w32-charset-turkish,\n\
13182 w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,\n\
13183 w32-charset-russian, w32-charset-mac, w32-charset-baltic,\n"
13185 #ifdef UNICODE_CHARSET
13186 "w32-charset-unicode, "
13188 "or w32-charset-oem.\n\
13189 CODEPAGE should be an integer specifying the codepage that should be used\n\
13190 to display the character set, t to do no translation and output as Unicode,\n\
13191 or nil to do no translation and output as 8 bit (or multibyte on far-east\n\
13192 versions of Windows) characters.");
13193 Vw32_charset_info_alist
= Qnil
;
13195 staticpro (&Qw32_charset_ansi
);
13196 Qw32_charset_ansi
= intern ("w32-charset-ansi");
13197 staticpro (&Qw32_charset_symbol
);
13198 Qw32_charset_symbol
= intern ("w32-charset-symbol");
13199 staticpro (&Qw32_charset_shiftjis
);
13200 Qw32_charset_shiftjis
= intern ("w32-charset-shiftjis");
13201 staticpro (&Qw32_charset_hangul
);
13202 Qw32_charset_hangul
= intern ("w32-charset-hangul");
13203 staticpro (&Qw32_charset_chinesebig5
);
13204 Qw32_charset_chinesebig5
= intern ("w32-charset-chinesebig5");
13205 staticpro (&Qw32_charset_gb2312
);
13206 Qw32_charset_gb2312
= intern ("w32-charset-gb2312");
13207 staticpro (&Qw32_charset_oem
);
13208 Qw32_charset_oem
= intern ("w32-charset-oem");
13210 #ifdef JOHAB_CHARSET
13212 static int w32_extra_charsets_defined
= 1;
13213 DEFVAR_BOOL ("w32-extra-charsets-defined", w32_extra_charsets_defined
, "");
13215 staticpro (&Qw32_charset_johab
);
13216 Qw32_charset_johab
= intern ("w32-charset-johab");
13217 staticpro (&Qw32_charset_easteurope
);
13218 Qw32_charset_easteurope
= intern ("w32-charset-easteurope");
13219 staticpro (&Qw32_charset_turkish
);
13220 Qw32_charset_turkish
= intern ("w32-charset-turkish");
13221 staticpro (&Qw32_charset_baltic
);
13222 Qw32_charset_baltic
= intern ("w32-charset-baltic");
13223 staticpro (&Qw32_charset_russian
);
13224 Qw32_charset_russian
= intern ("w32-charset-russian");
13225 staticpro (&Qw32_charset_arabic
);
13226 Qw32_charset_arabic
= intern ("w32-charset-arabic");
13227 staticpro (&Qw32_charset_greek
);
13228 Qw32_charset_greek
= intern ("w32-charset-greek");
13229 staticpro (&Qw32_charset_hebrew
);
13230 Qw32_charset_hebrew
= intern ("w32-charset-hebrew");
13231 staticpro (&Qw32_charset_thai
);
13232 Qw32_charset_thai
= intern ("w32-charset-thai");
13233 staticpro (&Qw32_charset_mac
);
13234 Qw32_charset_mac
= intern ("w32-charset-mac");
13238 #ifdef UNICODE_CHARSET
13240 static int w32_unicode_charset_defined
= 1;
13241 DEFVAR_BOOL ("w32-unicode-charset-defined",
13242 w32_unicode_charset_defined
, "");
13244 staticpro (&Qw32_charset_unicode
);
13245 Qw32_charset_unicode
= intern ("w32-charset-unicode");
13248 defsubr (&Sx_get_resource
);
13249 #if 0 /* NTEMACS_TODO: Port to W32 */
13250 defsubr (&Sx_change_window_property
);
13251 defsubr (&Sx_delete_window_property
);
13252 defsubr (&Sx_window_property
);
13254 defsubr (&Sxw_display_color_p
);
13255 defsubr (&Sx_display_grayscale_p
);
13256 defsubr (&Sxw_color_defined_p
);
13257 defsubr (&Sxw_color_values
);
13258 defsubr (&Sx_server_max_request_size
);
13259 defsubr (&Sx_server_vendor
);
13260 defsubr (&Sx_server_version
);
13261 defsubr (&Sx_display_pixel_width
);
13262 defsubr (&Sx_display_pixel_height
);
13263 defsubr (&Sx_display_mm_width
);
13264 defsubr (&Sx_display_mm_height
);
13265 defsubr (&Sx_display_screens
);
13266 defsubr (&Sx_display_planes
);
13267 defsubr (&Sx_display_color_cells
);
13268 defsubr (&Sx_display_visual_class
);
13269 defsubr (&Sx_display_backing_store
);
13270 defsubr (&Sx_display_save_under
);
13271 defsubr (&Sx_parse_geometry
);
13272 defsubr (&Sx_create_frame
);
13273 defsubr (&Sx_open_connection
);
13274 defsubr (&Sx_close_connection
);
13275 defsubr (&Sx_display_list
);
13276 defsubr (&Sx_synchronize
);
13278 /* W32 specific functions */
13280 defsubr (&Sw32_focus_frame
);
13281 defsubr (&Sw32_select_font
);
13282 defsubr (&Sw32_define_rgb_color
);
13283 defsubr (&Sw32_default_color_map
);
13284 defsubr (&Sw32_load_color_file
);
13285 defsubr (&Sw32_send_sys_command
);
13286 defsubr (&Sw32_shell_execute
);
13287 defsubr (&Sw32_register_hot_key
);
13288 defsubr (&Sw32_unregister_hot_key
);
13289 defsubr (&Sw32_registered_hot_keys
);
13290 defsubr (&Sw32_reconstruct_hot_key
);
13291 defsubr (&Sw32_toggle_lock_key
);
13292 defsubr (&Sw32_find_bdf_fonts
);
13294 /* Setting callback functions for fontset handler. */
13295 get_font_info_func
= w32_get_font_info
;
13297 #if 0 /* This function pointer doesn't seem to be used anywhere.
13298 And the pointer assigned has the wrong type, anyway. */
13299 list_fonts_func
= w32_list_fonts
;
13302 load_font_func
= w32_load_font
;
13303 find_ccl_program_func
= w32_find_ccl_program
;
13304 query_font_func
= w32_query_font
;
13305 set_frame_fontset_func
= x_set_font
;
13306 check_window_system_func
= check_w32
;
13308 #if 0 /* NTEMACS_TODO Image support for W32 */
13310 Qxbm
= intern ("xbm");
13312 QCtype
= intern (":type");
13313 staticpro (&QCtype
);
13314 QCalgorithm
= intern (":algorithm");
13315 staticpro (&QCalgorithm
);
13316 QCheuristic_mask
= intern (":heuristic-mask");
13317 staticpro (&QCheuristic_mask
);
13318 QCcolor_symbols
= intern (":color-symbols");
13319 staticpro (&QCcolor_symbols
);
13320 QCascent
= intern (":ascent");
13321 staticpro (&QCascent
);
13322 QCmargin
= intern (":margin");
13323 staticpro (&QCmargin
);
13324 QCrelief
= intern (":relief");
13325 staticpro (&QCrelief
);
13326 Qpostscript
= intern ("postscript");
13327 staticpro (&Qpostscript
);
13328 QCloader
= intern (":loader");
13329 staticpro (&QCloader
);
13330 QCbounding_box
= intern (":bounding-box");
13331 staticpro (&QCbounding_box
);
13332 QCpt_width
= intern (":pt-width");
13333 staticpro (&QCpt_width
);
13334 QCpt_height
= intern (":pt-height");
13335 staticpro (&QCpt_height
);
13336 QCindex
= intern (":index");
13337 staticpro (&QCindex
);
13338 Qpbm
= intern ("pbm");
13342 Qxpm
= intern ("xpm");
13347 Qjpeg
= intern ("jpeg");
13348 staticpro (&Qjpeg
);
13352 Qtiff
= intern ("tiff");
13353 staticpro (&Qtiff
);
13357 Qgif
= intern ("gif");
13362 Qpng
= intern ("png");
13366 defsubr (&Sclear_image_cache
);
13369 defsubr (&Simagep
);
13370 defsubr (&Slookup_image
);
13372 #endif /* NTEMACS_TODO */
13374 busy_cursor_atimer
= NULL
;
13375 busy_cursor_shown_p
= 0;
13377 defsubr (&Sx_show_tip
);
13378 defsubr (&Sx_hide_tip
);
13379 staticpro (&tip_timer
);
13382 defsubr (&Sx_file_dialog
);
13389 image_types
= NULL
;
13390 Vimage_types
= Qnil
;
13392 #if 0 /* NTEMACS_TODO : Image support for W32 */
13393 define_image_type (&xbm_type
);
13394 define_image_type (&gs_type
);
13395 define_image_type (&pbm_type
);
13398 define_image_type (&xpm_type
);
13402 define_image_type (&jpeg_type
);
13406 define_image_type (&tiff_type
);
13410 define_image_type (&gif_type
);
13414 define_image_type (&png_type
);
13416 #endif /* NTEMACS_TODO */
13425 button
= MessageBox (NULL
,
13426 "A fatal error has occurred!\n\n"
13427 "Select Abort to exit, Retry to debug, Ignore to continue",
13428 "Emacs Abort Dialog",
13429 MB_ICONEXCLAMATION
| MB_TASKMODAL
13430 | MB_SETFOREGROUND
| MB_ABORTRETRYIGNORE
);
13445 /* For convenience when debugging. */
13449 return GetLastError ();