]> code.delx.au - gnu-emacs/blob - src/w32fns.c
Merged fringe width related changes from xfns.c.
[gnu-emacs] / src / w32fns.c
1 /* Graphical user interface functions for the Microsoft W32 API.
2 Copyright (C) 1989, 92, 93, 94, 95, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* Added by Kevin Gallo */
23
24 #include <config.h>
25
26 #include <signal.h>
27 #include <stdio.h>
28 #include <limits.h>
29 #include <errno.h>
30
31 #include "lisp.h"
32 #include "charset.h"
33 #include "dispextern.h"
34 #include "w32term.h"
35 #include "keyboard.h"
36 #include "frame.h"
37 #include "window.h"
38 #include "buffer.h"
39 #include "fontset.h"
40 #include "intervals.h"
41 #include "blockinput.h"
42 #include "epaths.h"
43 #include "w32heap.h"
44 #include "termhooks.h"
45 #include "coding.h"
46 #include "ccl.h"
47 #include "systime.h"
48
49 #include "bitmaps/gray.xbm"
50
51 #include <commdlg.h>
52 #include <shellapi.h>
53 #include <ctype.h>
54
55 extern void free_frame_menubar ();
56 extern void x_compute_fringe_widths (struct frame *, int);
57 extern double atof ();
58 extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
59 extern void w32_menu_display_help (HWND owner, HMENU menu, UINT menu_item, UINT flags);
60 extern int quit_char;
61
62 /* A definition of XColor for non-X frames. */
63 #ifndef HAVE_X_WINDOWS
64 typedef struct {
65 unsigned long pixel;
66 unsigned short red, green, blue;
67 char flags;
68 char pad;
69 } XColor;
70 #endif
71
72 extern char *lispy_function_keys[];
73
74 /* The gray bitmap `bitmaps/gray'. This is done because w32term.c uses
75 it, and including `bitmaps/gray' more than once is a problem when
76 config.h defines `static' as an empty replacement string. */
77
78 int gray_bitmap_width = gray_width;
79 int gray_bitmap_height = gray_height;
80 unsigned char *gray_bitmap_bits = gray_bits;
81
82 /* The colormap for converting color names to RGB values */
83 Lisp_Object Vw32_color_map;
84
85 /* Non nil if alt key presses are passed on to Windows. */
86 Lisp_Object Vw32_pass_alt_to_system;
87
88 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
89 to alt_modifier. */
90 Lisp_Object Vw32_alt_is_meta;
91
92 /* If non-zero, the windows virtual key code for an alternative quit key. */
93 Lisp_Object Vw32_quit_key;
94
95 /* Non nil if left window key events are passed on to Windows (this only
96 affects whether "tapping" the key opens the Start menu). */
97 Lisp_Object Vw32_pass_lwindow_to_system;
98
99 /* Non nil if right window key events are passed on to Windows (this
100 only affects whether "tapping" the key opens the Start menu). */
101 Lisp_Object Vw32_pass_rwindow_to_system;
102
103 /* Virtual key code used to generate "phantom" key presses in order
104 to stop system from acting on Windows key events. */
105 Lisp_Object Vw32_phantom_key_code;
106
107 /* Modifier associated with the left "Windows" key, or nil to act as a
108 normal key. */
109 Lisp_Object Vw32_lwindow_modifier;
110
111 /* Modifier associated with the right "Windows" key, or nil to act as a
112 normal key. */
113 Lisp_Object Vw32_rwindow_modifier;
114
115 /* Modifier associated with the "Apps" key, or nil to act as a normal
116 key. */
117 Lisp_Object Vw32_apps_modifier;
118
119 /* Value is nil if Num Lock acts as a function key. */
120 Lisp_Object Vw32_enable_num_lock;
121
122 /* Value is nil if Caps Lock acts as a function key. */
123 Lisp_Object Vw32_enable_caps_lock;
124
125 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
126 Lisp_Object Vw32_scroll_lock_modifier;
127
128 /* Switch to control whether we inhibit requests for synthesized bold
129 and italic versions of fonts. */
130 Lisp_Object Vw32_enable_synthesized_fonts;
131
132 /* Enable palette management. */
133 Lisp_Object Vw32_enable_palette;
134
135 /* Control how close left/right button down events must be to
136 be converted to a middle button down event. */
137 Lisp_Object Vw32_mouse_button_tolerance;
138
139 /* Minimum interval between mouse movement (and scroll bar drag)
140 events that are passed on to the event loop. */
141 Lisp_Object Vw32_mouse_move_interval;
142
143 /* The name we're using in resource queries. */
144 Lisp_Object Vx_resource_name;
145
146 /* Non nil if no window manager is in use. */
147 Lisp_Object Vx_no_window_manager;
148
149 /* Non-zero means we're allowed to display a hourglass pointer. */
150
151 int display_hourglass_p;
152
153 /* The background and shape of the mouse pointer, and shape when not
154 over text or in the modeline. */
155
156 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
157 Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape;
158
159 /* The shape when over mouse-sensitive text. */
160
161 Lisp_Object Vx_sensitive_text_pointer_shape;
162
163 /* Color of chars displayed in cursor box. */
164
165 Lisp_Object Vx_cursor_fore_pixel;
166
167 /* Nonzero if using Windows. */
168
169 static int w32_in_use;
170
171 /* Search path for bitmap files. */
172
173 Lisp_Object Vx_bitmap_file_path;
174
175 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
176
177 Lisp_Object Vx_pixel_size_width_font_regexp;
178
179 /* Alist of bdf fonts and the files that define them. */
180 Lisp_Object Vw32_bdf_filename_alist;
181
182 /* A flag to control whether fonts are matched strictly or not. */
183 int w32_strict_fontnames;
184
185 /* A flag to control whether we should only repaint if GetUpdateRect
186 indicates there is an update region. */
187 int w32_strict_painting;
188
189 /* Associative list linking character set strings to Windows codepages. */
190 Lisp_Object Vw32_charset_info_alist;
191
192 /* VIETNAMESE_CHARSET is not defined in some versions of MSVC. */
193 #ifndef VIETNAMESE_CHARSET
194 #define VIETNAMESE_CHARSET 163
195 #endif
196
197 Lisp_Object Qauto_raise;
198 Lisp_Object Qauto_lower;
199 Lisp_Object Qbar;
200 Lisp_Object Qborder_color;
201 Lisp_Object Qborder_width;
202 Lisp_Object Qbox;
203 Lisp_Object Qcursor_color;
204 Lisp_Object Qcursor_type;
205 Lisp_Object Qgeometry;
206 Lisp_Object Qicon_left;
207 Lisp_Object Qicon_top;
208 Lisp_Object Qicon_type;
209 Lisp_Object Qicon_name;
210 Lisp_Object Qinternal_border_width;
211 Lisp_Object Qleft;
212 Lisp_Object Qright;
213 Lisp_Object Qmouse_color;
214 Lisp_Object Qnone;
215 Lisp_Object Qparent_id;
216 Lisp_Object Qscroll_bar_width;
217 Lisp_Object Qsuppress_icon;
218 Lisp_Object Qundefined_color;
219 Lisp_Object Qvertical_scroll_bars;
220 Lisp_Object Qvisibility;
221 Lisp_Object Qwindow_id;
222 Lisp_Object Qx_frame_parameter;
223 Lisp_Object Qx_resource_name;
224 Lisp_Object Quser_position;
225 Lisp_Object Quser_size;
226 Lisp_Object Qscreen_gamma;
227 Lisp_Object Qline_spacing;
228 Lisp_Object Qcenter;
229 Lisp_Object Qcancel_timer;
230 Lisp_Object Qhyper;
231 Lisp_Object Qsuper;
232 Lisp_Object Qmeta;
233 Lisp_Object Qalt;
234 Lisp_Object Qctrl;
235 Lisp_Object Qcontrol;
236 Lisp_Object Qshift;
237
238 Lisp_Object Qw32_charset_ansi;
239 Lisp_Object Qw32_charset_default;
240 Lisp_Object Qw32_charset_symbol;
241 Lisp_Object Qw32_charset_shiftjis;
242 Lisp_Object Qw32_charset_hangeul;
243 Lisp_Object Qw32_charset_gb2312;
244 Lisp_Object Qw32_charset_chinesebig5;
245 Lisp_Object Qw32_charset_oem;
246
247 #ifndef JOHAB_CHARSET
248 #define JOHAB_CHARSET 130
249 #endif
250 #ifdef JOHAB_CHARSET
251 Lisp_Object Qw32_charset_easteurope;
252 Lisp_Object Qw32_charset_turkish;
253 Lisp_Object Qw32_charset_baltic;
254 Lisp_Object Qw32_charset_russian;
255 Lisp_Object Qw32_charset_arabic;
256 Lisp_Object Qw32_charset_greek;
257 Lisp_Object Qw32_charset_hebrew;
258 Lisp_Object Qw32_charset_vietnamese;
259 Lisp_Object Qw32_charset_thai;
260 Lisp_Object Qw32_charset_johab;
261 Lisp_Object Qw32_charset_mac;
262 #endif
263
264 #ifdef UNICODE_CHARSET
265 Lisp_Object Qw32_charset_unicode;
266 #endif
267
268 extern Lisp_Object Qtop;
269 extern Lisp_Object Qdisplay;
270 extern Lisp_Object Qtool_bar_lines;
271
272 /* State variables for emulating a three button mouse. */
273 #define LMOUSE 1
274 #define MMOUSE 2
275 #define RMOUSE 4
276
277 static int button_state = 0;
278 static W32Msg saved_mouse_button_msg;
279 static unsigned mouse_button_timer; /* non-zero when timer is active */
280 static W32Msg saved_mouse_move_msg;
281 static unsigned mouse_move_timer;
282
283 /* W95 mousewheel handler */
284 unsigned int msh_mousewheel = 0;
285
286 #define MOUSE_BUTTON_ID 1
287 #define MOUSE_MOVE_ID 2
288
289 /* The below are defined in frame.c. */
290
291 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
292 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
293 extern Lisp_Object Qtool_bar_lines;
294
295 extern Lisp_Object Vwindow_system_version;
296
297 Lisp_Object Qface_set_after_frame_default;
298
299 #ifdef GLYPH_DEBUG
300 int image_cache_refcount, dpyinfo_refcount;
301 #endif
302
303
304 /* From w32term.c. */
305 extern Lisp_Object Vw32_num_mouse_buttons;
306 extern Lisp_Object Vw32_recognize_altgr;
307
308 extern HWND w32_system_caret_hwnd;
309 extern int w32_system_caret_width;
310 extern int w32_system_caret_height;
311 extern int w32_system_caret_x;
312 extern int w32_system_caret_y;
313
314 \f
315 /* Error if we are not connected to MS-Windows. */
316 void
317 check_w32 ()
318 {
319 if (! w32_in_use)
320 error ("MS-Windows not in use or not initialized");
321 }
322
323 /* Nonzero if we can use mouse menus.
324 You should not call this unless HAVE_MENUS is defined. */
325
326 int
327 have_menus_p ()
328 {
329 return w32_in_use;
330 }
331
332 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
333 and checking validity for W32. */
334
335 FRAME_PTR
336 check_x_frame (frame)
337 Lisp_Object frame;
338 {
339 FRAME_PTR f;
340
341 if (NILP (frame))
342 frame = selected_frame;
343 CHECK_LIVE_FRAME (frame);
344 f = XFRAME (frame);
345 if (! FRAME_W32_P (f))
346 error ("non-w32 frame used");
347 return f;
348 }
349
350 /* Let the user specify an display with a frame.
351 nil stands for the selected frame--or, if that is not a w32 frame,
352 the first display on the list. */
353
354 static struct w32_display_info *
355 check_x_display_info (frame)
356 Lisp_Object frame;
357 {
358 if (NILP (frame))
359 {
360 struct frame *sf = XFRAME (selected_frame);
361
362 if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
363 return FRAME_W32_DISPLAY_INFO (sf);
364 else
365 return &one_w32_display_info;
366 }
367 else if (STRINGP (frame))
368 return x_display_info_for_name (frame);
369 else
370 {
371 FRAME_PTR f;
372
373 CHECK_LIVE_FRAME (frame);
374 f = XFRAME (frame);
375 if (! FRAME_W32_P (f))
376 error ("non-w32 frame used");
377 return FRAME_W32_DISPLAY_INFO (f);
378 }
379 }
380 \f
381 /* Return the Emacs frame-object corresponding to an w32 window.
382 It could be the frame's main window or an icon window. */
383
384 /* This function can be called during GC, so use GC_xxx type test macros. */
385
386 struct frame *
387 x_window_to_frame (dpyinfo, wdesc)
388 struct w32_display_info *dpyinfo;
389 HWND wdesc;
390 {
391 Lisp_Object tail, frame;
392 struct frame *f;
393
394 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
395 {
396 frame = XCAR (tail);
397 if (!GC_FRAMEP (frame))
398 continue;
399 f = XFRAME (frame);
400 if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
401 continue;
402 if (f->output_data.w32->hourglass_window == wdesc)
403 return f;
404
405 if (FRAME_W32_WINDOW (f) == wdesc)
406 return f;
407 }
408 return 0;
409 }
410
411 \f
412
413 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
414 id, which is just an int that this section returns. Bitmaps are
415 reference counted so they can be shared among frames.
416
417 Bitmap indices are guaranteed to be > 0, so a negative number can
418 be used to indicate no bitmap.
419
420 If you use x_create_bitmap_from_data, then you must keep track of
421 the bitmaps yourself. That is, creating a bitmap from the same
422 data more than once will not be caught. */
423
424
425 /* Functions to access the contents of a bitmap, given an id. */
426
427 int
428 x_bitmap_height (f, id)
429 FRAME_PTR f;
430 int id;
431 {
432 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
433 }
434
435 int
436 x_bitmap_width (f, id)
437 FRAME_PTR f;
438 int id;
439 {
440 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
441 }
442
443 int
444 x_bitmap_pixmap (f, id)
445 FRAME_PTR f;
446 int id;
447 {
448 return (int) FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
449 }
450
451
452 /* Allocate a new bitmap record. Returns index of new record. */
453
454 static int
455 x_allocate_bitmap_record (f)
456 FRAME_PTR f;
457 {
458 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
459 int i;
460
461 if (dpyinfo->bitmaps == NULL)
462 {
463 dpyinfo->bitmaps_size = 10;
464 dpyinfo->bitmaps
465 = (struct w32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
466 dpyinfo->bitmaps_last = 1;
467 return 1;
468 }
469
470 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
471 return ++dpyinfo->bitmaps_last;
472
473 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
474 if (dpyinfo->bitmaps[i].refcount == 0)
475 return i + 1;
476
477 dpyinfo->bitmaps_size *= 2;
478 dpyinfo->bitmaps
479 = (struct w32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
480 dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
481 return ++dpyinfo->bitmaps_last;
482 }
483
484 /* Add one reference to the reference count of the bitmap with id ID. */
485
486 void
487 x_reference_bitmap (f, id)
488 FRAME_PTR f;
489 int id;
490 {
491 ++FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
492 }
493
494 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
495
496 int
497 x_create_bitmap_from_data (f, bits, width, height)
498 struct frame *f;
499 char *bits;
500 unsigned int width, height;
501 {
502 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
503 Pixmap bitmap;
504 int id;
505
506 bitmap = CreateBitmap (width, height,
507 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes,
508 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
509 bits);
510
511 if (! bitmap)
512 return -1;
513
514 id = x_allocate_bitmap_record (f);
515 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
516 dpyinfo->bitmaps[id - 1].file = NULL;
517 dpyinfo->bitmaps[id - 1].hinst = NULL;
518 dpyinfo->bitmaps[id - 1].refcount = 1;
519 dpyinfo->bitmaps[id - 1].depth = 1;
520 dpyinfo->bitmaps[id - 1].height = height;
521 dpyinfo->bitmaps[id - 1].width = width;
522
523 return id;
524 }
525
526 /* Create bitmap from file FILE for frame F. */
527
528 int
529 x_create_bitmap_from_file (f, file)
530 struct frame *f;
531 Lisp_Object file;
532 {
533 return -1;
534 #if 0 /* TODO : bitmap support */
535 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
536 unsigned int width, height;
537 HBITMAP bitmap;
538 int xhot, yhot, result, id;
539 Lisp_Object found;
540 int fd;
541 char *filename;
542 HINSTANCE hinst;
543
544 /* Look for an existing bitmap with the same name. */
545 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
546 {
547 if (dpyinfo->bitmaps[id].refcount
548 && dpyinfo->bitmaps[id].file
549 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
550 {
551 ++dpyinfo->bitmaps[id].refcount;
552 return id + 1;
553 }
554 }
555
556 /* Search bitmap-file-path for the file, if appropriate. */
557 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, 0);
558 if (fd < 0)
559 return -1;
560 emacs_close (fd);
561
562 filename = (char *) XSTRING (found)->data;
563
564 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
565
566 if (hinst == NULL)
567 return -1;
568
569
570 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
571 filename, &width, &height, &bitmap, &xhot, &yhot);
572 if (result != BitmapSuccess)
573 return -1;
574
575 id = x_allocate_bitmap_record (f);
576 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
577 dpyinfo->bitmaps[id - 1].refcount = 1;
578 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
579 dpyinfo->bitmaps[id - 1].depth = 1;
580 dpyinfo->bitmaps[id - 1].height = height;
581 dpyinfo->bitmaps[id - 1].width = width;
582 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
583
584 return id;
585 #endif /* TODO */
586 }
587
588 /* Remove reference to bitmap with id number ID. */
589
590 void
591 x_destroy_bitmap (f, id)
592 FRAME_PTR f;
593 int id;
594 {
595 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
596
597 if (id > 0)
598 {
599 --dpyinfo->bitmaps[id - 1].refcount;
600 if (dpyinfo->bitmaps[id - 1].refcount == 0)
601 {
602 BLOCK_INPUT;
603 DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
604 if (dpyinfo->bitmaps[id - 1].file)
605 {
606 xfree (dpyinfo->bitmaps[id - 1].file);
607 dpyinfo->bitmaps[id - 1].file = NULL;
608 }
609 UNBLOCK_INPUT;
610 }
611 }
612 }
613
614 /* Free all the bitmaps for the display specified by DPYINFO. */
615
616 static void
617 x_destroy_all_bitmaps (dpyinfo)
618 struct w32_display_info *dpyinfo;
619 {
620 int i;
621 for (i = 0; i < dpyinfo->bitmaps_last; i++)
622 if (dpyinfo->bitmaps[i].refcount > 0)
623 {
624 DeleteObject (dpyinfo->bitmaps[i].pixmap);
625 if (dpyinfo->bitmaps[i].file)
626 xfree (dpyinfo->bitmaps[i].file);
627 }
628 dpyinfo->bitmaps_last = 0;
629 }
630 \f
631 /* Connect the frame-parameter names for W32 frames
632 to the ways of passing the parameter values to the window system.
633
634 The name of a parameter, as a Lisp symbol,
635 has an `x-frame-parameter' property which is an integer in Lisp
636 but can be interpreted as an `enum x_frame_parm' in C. */
637
638 enum x_frame_parm
639 {
640 X_PARM_FOREGROUND_COLOR,
641 X_PARM_BACKGROUND_COLOR,
642 X_PARM_MOUSE_COLOR,
643 X_PARM_CURSOR_COLOR,
644 X_PARM_BORDER_COLOR,
645 X_PARM_ICON_TYPE,
646 X_PARM_FONT,
647 X_PARM_BORDER_WIDTH,
648 X_PARM_INTERNAL_BORDER_WIDTH,
649 X_PARM_NAME,
650 X_PARM_AUTORAISE,
651 X_PARM_AUTOLOWER,
652 X_PARM_VERT_SCROLL_BAR,
653 X_PARM_VISIBILITY,
654 X_PARM_MENU_BAR_LINES
655 };
656
657
658 struct x_frame_parm_table
659 {
660 char *name;
661 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
662 };
663
664 BOOL my_show_window P_ ((struct frame *, HWND, int));
665 void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
666 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
667 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
668 static void x_change_window_heights P_ ((Lisp_Object, int));
669 /* TODO: Native Input Method support; see x_create_im. */
670 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
671 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
672 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
673 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
674 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
675 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
676 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
677 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
678 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
679 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
680 static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
681 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
682 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
683 Lisp_Object));
684 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
685 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
686 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
687 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
688 Lisp_Object));
689 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
690 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
691 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
692 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
693 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
694 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
695 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
696 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
697 Lisp_Object));
698
699 static struct x_frame_parm_table x_frame_parms[] =
700 {
701 "auto-raise", x_set_autoraise,
702 "auto-lower", x_set_autolower,
703 "background-color", x_set_background_color,
704 "border-color", x_set_border_color,
705 "border-width", x_set_border_width,
706 "cursor-color", x_set_cursor_color,
707 "cursor-type", x_set_cursor_type,
708 "font", x_set_font,
709 "foreground-color", x_set_foreground_color,
710 "icon-name", x_set_icon_name,
711 "icon-type", x_set_icon_type,
712 "internal-border-width", x_set_internal_border_width,
713 "menu-bar-lines", x_set_menu_bar_lines,
714 "mouse-color", x_set_mouse_color,
715 "name", x_explicitly_set_name,
716 "scroll-bar-width", x_set_scroll_bar_width,
717 "title", x_set_title,
718 "unsplittable", x_set_unsplittable,
719 "vertical-scroll-bars", x_set_vertical_scroll_bars,
720 "visibility", x_set_visibility,
721 "tool-bar-lines", x_set_tool_bar_lines,
722 "screen-gamma", x_set_screen_gamma,
723 "line-spacing", x_set_line_spacing,
724 "left-fringe", x_set_fringe_width,
725 "right-fringe", x_set_fringe_width
726
727 };
728
729 /* Attach the `x-frame-parameter' properties to
730 the Lisp symbol names of parameters relevant to W32. */
731
732 void
733 init_x_parm_symbols ()
734 {
735 int i;
736
737 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
738 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
739 make_number (i));
740 }
741 \f
742 /* Change the parameters of frame F as specified by ALIST.
743 If a parameter is not specially recognized, do nothing;
744 otherwise call the `x_set_...' function for that parameter. */
745
746 void
747 x_set_frame_parameters (f, alist)
748 FRAME_PTR f;
749 Lisp_Object alist;
750 {
751 Lisp_Object tail;
752
753 /* If both of these parameters are present, it's more efficient to
754 set them both at once. So we wait until we've looked at the
755 entire list before we set them. */
756 int width, height;
757
758 /* Same here. */
759 Lisp_Object left, top;
760
761 /* Same with these. */
762 Lisp_Object icon_left, icon_top;
763
764 /* Record in these vectors all the parms specified. */
765 Lisp_Object *parms;
766 Lisp_Object *values;
767 int i, p;
768 int left_no_change = 0, top_no_change = 0;
769 int icon_left_no_change = 0, icon_top_no_change = 0;
770
771 struct gcpro gcpro1, gcpro2;
772
773 i = 0;
774 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
775 i++;
776
777 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
778 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
779
780 /* Extract parm names and values into those vectors. */
781
782 i = 0;
783 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
784 {
785 Lisp_Object elt;
786
787 elt = Fcar (tail);
788 parms[i] = Fcar (elt);
789 values[i] = Fcdr (elt);
790 i++;
791 }
792 /* TAIL and ALIST are not used again below here. */
793 alist = tail = Qnil;
794
795 GCPRO2 (*parms, *values);
796 gcpro1.nvars = i;
797 gcpro2.nvars = i;
798
799 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
800 because their values appear in VALUES and strings are not valid. */
801 top = left = Qunbound;
802 icon_left = icon_top = Qunbound;
803
804 /* Provide default values for HEIGHT and WIDTH. */
805 if (FRAME_NEW_WIDTH (f))
806 width = FRAME_NEW_WIDTH (f);
807 else
808 width = FRAME_WIDTH (f);
809
810 if (FRAME_NEW_HEIGHT (f))
811 height = FRAME_NEW_HEIGHT (f);
812 else
813 height = FRAME_HEIGHT (f);
814
815 /* Process foreground_color and background_color before anything else.
816 They are independent of other properties, but other properties (e.g.,
817 cursor_color) are dependent upon them. */
818 /* Process default font as well, since fringe widths depends on it. */
819 for (p = 0; p < i; p++)
820 {
821 Lisp_Object prop, val;
822
823 prop = parms[p];
824 val = values[p];
825 if (EQ (prop, Qforeground_color)
826 || EQ (prop, Qbackground_color)
827 || EQ (prop, Qfont))
828 {
829 register Lisp_Object param_index, old_value;
830
831 old_value = get_frame_param (f, prop);
832
833 if (NILP (Fequal (val, old_value)))
834 {
835 store_frame_param (f, prop, val);
836
837 param_index = Fget (prop, Qx_frame_parameter);
838 if (NATNUMP (param_index)
839 && (XFASTINT (param_index)
840 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
841 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
842 }
843 }
844 }
845
846 /* Now process them in reverse of specified order. */
847 for (i--; i >= 0; i--)
848 {
849 Lisp_Object prop, val;
850
851 prop = parms[i];
852 val = values[i];
853
854 if (EQ (prop, Qwidth) && NUMBERP (val))
855 width = XFASTINT (val);
856 else if (EQ (prop, Qheight) && NUMBERP (val))
857 height = XFASTINT (val);
858 else if (EQ (prop, Qtop))
859 top = val;
860 else if (EQ (prop, Qleft))
861 left = val;
862 else if (EQ (prop, Qicon_top))
863 icon_top = val;
864 else if (EQ (prop, Qicon_left))
865 icon_left = val;
866 else if (EQ (prop, Qforeground_color)
867 || EQ (prop, Qbackground_color)
868 || EQ (prop, Qfont))
869 /* Processed above. */
870 continue;
871 else
872 {
873 register Lisp_Object param_index, old_value;
874
875 old_value = get_frame_param (f, prop);
876
877 store_frame_param (f, prop, val);
878
879 param_index = Fget (prop, Qx_frame_parameter);
880 if (NATNUMP (param_index)
881 && (XFASTINT (param_index)
882 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
883 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
884 }
885 }
886
887 /* Don't die if just one of these was set. */
888 if (EQ (left, Qunbound))
889 {
890 left_no_change = 1;
891 if (f->output_data.w32->left_pos < 0)
892 left = Fcons (Qplus, Fcons (make_number (f->output_data.w32->left_pos), Qnil));
893 else
894 XSETINT (left, f->output_data.w32->left_pos);
895 }
896 if (EQ (top, Qunbound))
897 {
898 top_no_change = 1;
899 if (f->output_data.w32->top_pos < 0)
900 top = Fcons (Qplus, Fcons (make_number (f->output_data.w32->top_pos), Qnil));
901 else
902 XSETINT (top, f->output_data.w32->top_pos);
903 }
904
905 /* If one of the icon positions was not set, preserve or default it. */
906 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
907 {
908 icon_left_no_change = 1;
909 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
910 if (NILP (icon_left))
911 XSETINT (icon_left, 0);
912 }
913 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
914 {
915 icon_top_no_change = 1;
916 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
917 if (NILP (icon_top))
918 XSETINT (icon_top, 0);
919 }
920
921 /* Don't set these parameters unless they've been explicitly
922 specified. The window might be mapped or resized while we're in
923 this function, and we don't want to override that unless the lisp
924 code has asked for it.
925
926 Don't set these parameters unless they actually differ from the
927 window's current parameters; the window may not actually exist
928 yet. */
929 {
930 Lisp_Object frame;
931
932 check_frame_size (f, &height, &width);
933
934 XSETFRAME (frame, f);
935
936 if (width != FRAME_WIDTH (f)
937 || height != FRAME_HEIGHT (f)
938 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
939 Fset_frame_size (frame, make_number (width), make_number (height));
940
941 if ((!NILP (left) || !NILP (top))
942 && ! (left_no_change && top_no_change)
943 && ! (NUMBERP (left) && XINT (left) == f->output_data.w32->left_pos
944 && NUMBERP (top) && XINT (top) == f->output_data.w32->top_pos))
945 {
946 int leftpos = 0;
947 int toppos = 0;
948
949 /* Record the signs. */
950 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
951 if (EQ (left, Qminus))
952 f->output_data.w32->size_hint_flags |= XNegative;
953 else if (INTEGERP (left))
954 {
955 leftpos = XINT (left);
956 if (leftpos < 0)
957 f->output_data.w32->size_hint_flags |= XNegative;
958 }
959 else if (CONSP (left) && EQ (XCAR (left), Qminus)
960 && CONSP (XCDR (left))
961 && INTEGERP (XCAR (XCDR (left))))
962 {
963 leftpos = - XINT (XCAR (XCDR (left)));
964 f->output_data.w32->size_hint_flags |= XNegative;
965 }
966 else if (CONSP (left) && EQ (XCAR (left), Qplus)
967 && CONSP (XCDR (left))
968 && INTEGERP (XCAR (XCDR (left))))
969 {
970 leftpos = XINT (XCAR (XCDR (left)));
971 }
972
973 if (EQ (top, Qminus))
974 f->output_data.w32->size_hint_flags |= YNegative;
975 else if (INTEGERP (top))
976 {
977 toppos = XINT (top);
978 if (toppos < 0)
979 f->output_data.w32->size_hint_flags |= YNegative;
980 }
981 else if (CONSP (top) && EQ (XCAR (top), Qminus)
982 && CONSP (XCDR (top))
983 && INTEGERP (XCAR (XCDR (top))))
984 {
985 toppos = - XINT (XCAR (XCDR (top)));
986 f->output_data.w32->size_hint_flags |= YNegative;
987 }
988 else if (CONSP (top) && EQ (XCAR (top), Qplus)
989 && CONSP (XCDR (top))
990 && INTEGERP (XCAR (XCDR (top))))
991 {
992 toppos = XINT (XCAR (XCDR (top)));
993 }
994
995
996 /* Store the numeric value of the position. */
997 f->output_data.w32->top_pos = toppos;
998 f->output_data.w32->left_pos = leftpos;
999
1000 f->output_data.w32->win_gravity = NorthWestGravity;
1001
1002 /* Actually set that position, and convert to absolute. */
1003 x_set_offset (f, leftpos, toppos, -1);
1004 }
1005
1006 if ((!NILP (icon_left) || !NILP (icon_top))
1007 && ! (icon_left_no_change && icon_top_no_change))
1008 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1009 }
1010
1011 UNGCPRO;
1012 }
1013
1014 /* Store the screen positions of frame F into XPTR and YPTR.
1015 These are the positions of the containing window manager window,
1016 not Emacs's own window. */
1017
1018 void
1019 x_real_positions (f, xptr, yptr)
1020 FRAME_PTR f;
1021 int *xptr, *yptr;
1022 {
1023 POINT pt;
1024
1025 {
1026 RECT rect;
1027
1028 GetClientRect(FRAME_W32_WINDOW(f), &rect);
1029 AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
1030
1031 pt.x = rect.left;
1032 pt.y = rect.top;
1033 }
1034
1035 ClientToScreen (FRAME_W32_WINDOW(f), &pt);
1036
1037 *xptr = pt.x;
1038 *yptr = pt.y;
1039 }
1040
1041 /* Insert a description of internally-recorded parameters of frame X
1042 into the parameter alist *ALISTPTR that is to be given to the user.
1043 Only parameters that are specific to W32
1044 and whose values are not correctly recorded in the frame's
1045 param_alist need to be considered here. */
1046
1047 void
1048 x_report_frame_params (f, alistptr)
1049 struct frame *f;
1050 Lisp_Object *alistptr;
1051 {
1052 char buf[16];
1053 Lisp_Object tem;
1054
1055 /* Represent negative positions (off the top or left screen edge)
1056 in a way that Fmodify_frame_parameters will understand correctly. */
1057 XSETINT (tem, f->output_data.w32->left_pos);
1058 if (f->output_data.w32->left_pos >= 0)
1059 store_in_alist (alistptr, Qleft, tem);
1060 else
1061 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1062
1063 XSETINT (tem, f->output_data.w32->top_pos);
1064 if (f->output_data.w32->top_pos >= 0)
1065 store_in_alist (alistptr, Qtop, tem);
1066 else
1067 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1068
1069 store_in_alist (alistptr, Qborder_width,
1070 make_number (f->output_data.w32->border_width));
1071 store_in_alist (alistptr, Qinternal_border_width,
1072 make_number (f->output_data.w32->internal_border_width));
1073 sprintf (buf, "%ld", (long) FRAME_W32_WINDOW (f));
1074 store_in_alist (alistptr, Qwindow_id,
1075 build_string (buf));
1076 store_in_alist (alistptr, Qicon_name, f->icon_name);
1077 FRAME_SAMPLE_VISIBILITY (f);
1078 store_in_alist (alistptr, Qvisibility,
1079 (FRAME_VISIBLE_P (f) ? Qt
1080 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1081 store_in_alist (alistptr, Qdisplay,
1082 XCAR (FRAME_W32_DISPLAY_INFO (f)->name_list_element));
1083 }
1084 \f
1085
1086 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
1087 Sw32_define_rgb_color, 4, 4, 0,
1088 doc: /* Convert RGB numbers to a windows color reference and associate with NAME.
1089 This adds or updates a named color to w32-color-map, making it
1090 available for use. The original entry's RGB ref is returned, or nil
1091 if the entry is new. */)
1092 (red, green, blue, name)
1093 Lisp_Object red, green, blue, name;
1094 {
1095 Lisp_Object rgb;
1096 Lisp_Object oldrgb = Qnil;
1097 Lisp_Object entry;
1098
1099 CHECK_NUMBER (red);
1100 CHECK_NUMBER (green);
1101 CHECK_NUMBER (blue);
1102 CHECK_STRING (name);
1103
1104 XSET (rgb, Lisp_Int, RGB(XUINT (red), XUINT (green), XUINT (blue)));
1105
1106 BLOCK_INPUT;
1107
1108 /* replace existing entry in w32-color-map or add new entry. */
1109 entry = Fassoc (name, Vw32_color_map);
1110 if (NILP (entry))
1111 {
1112 entry = Fcons (name, rgb);
1113 Vw32_color_map = Fcons (entry, Vw32_color_map);
1114 }
1115 else
1116 {
1117 oldrgb = Fcdr (entry);
1118 Fsetcdr (entry, rgb);
1119 }
1120
1121 UNBLOCK_INPUT;
1122
1123 return (oldrgb);
1124 }
1125
1126 DEFUN ("w32-load-color-file", Fw32_load_color_file,
1127 Sw32_load_color_file, 1, 1, 0,
1128 doc: /* Create an alist of color entries from an external file.
1129 Assign this value to w32-color-map to replace the existing color map.
1130
1131 The file should define one named RGB color per line like so:
1132 R G B name
1133 where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
1134 (filename)
1135 Lisp_Object filename;
1136 {
1137 FILE *fp;
1138 Lisp_Object cmap = Qnil;
1139 Lisp_Object abspath;
1140
1141 CHECK_STRING (filename);
1142 abspath = Fexpand_file_name (filename, Qnil);
1143
1144 fp = fopen (XSTRING (filename)->data, "rt");
1145 if (fp)
1146 {
1147 char buf[512];
1148 int red, green, blue;
1149 int num;
1150
1151 BLOCK_INPUT;
1152
1153 while (fgets (buf, sizeof (buf), fp) != NULL) {
1154 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
1155 {
1156 char *name = buf + num;
1157 num = strlen (name) - 1;
1158 if (name[num] == '\n')
1159 name[num] = 0;
1160 cmap = Fcons (Fcons (build_string (name),
1161 make_number (RGB (red, green, blue))),
1162 cmap);
1163 }
1164 }
1165 fclose (fp);
1166
1167 UNBLOCK_INPUT;
1168 }
1169
1170 return cmap;
1171 }
1172
1173 /* The default colors for the w32 color map */
1174 typedef struct colormap_t
1175 {
1176 char *name;
1177 COLORREF colorref;
1178 } colormap_t;
1179
1180 colormap_t w32_color_map[] =
1181 {
1182 {"snow" , PALETTERGB (255,250,250)},
1183 {"ghost white" , PALETTERGB (248,248,255)},
1184 {"GhostWhite" , PALETTERGB (248,248,255)},
1185 {"white smoke" , PALETTERGB (245,245,245)},
1186 {"WhiteSmoke" , PALETTERGB (245,245,245)},
1187 {"gainsboro" , PALETTERGB (220,220,220)},
1188 {"floral white" , PALETTERGB (255,250,240)},
1189 {"FloralWhite" , PALETTERGB (255,250,240)},
1190 {"old lace" , PALETTERGB (253,245,230)},
1191 {"OldLace" , PALETTERGB (253,245,230)},
1192 {"linen" , PALETTERGB (250,240,230)},
1193 {"antique white" , PALETTERGB (250,235,215)},
1194 {"AntiqueWhite" , PALETTERGB (250,235,215)},
1195 {"papaya whip" , PALETTERGB (255,239,213)},
1196 {"PapayaWhip" , PALETTERGB (255,239,213)},
1197 {"blanched almond" , PALETTERGB (255,235,205)},
1198 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
1199 {"bisque" , PALETTERGB (255,228,196)},
1200 {"peach puff" , PALETTERGB (255,218,185)},
1201 {"PeachPuff" , PALETTERGB (255,218,185)},
1202 {"navajo white" , PALETTERGB (255,222,173)},
1203 {"NavajoWhite" , PALETTERGB (255,222,173)},
1204 {"moccasin" , PALETTERGB (255,228,181)},
1205 {"cornsilk" , PALETTERGB (255,248,220)},
1206 {"ivory" , PALETTERGB (255,255,240)},
1207 {"lemon chiffon" , PALETTERGB (255,250,205)},
1208 {"LemonChiffon" , PALETTERGB (255,250,205)},
1209 {"seashell" , PALETTERGB (255,245,238)},
1210 {"honeydew" , PALETTERGB (240,255,240)},
1211 {"mint cream" , PALETTERGB (245,255,250)},
1212 {"MintCream" , PALETTERGB (245,255,250)},
1213 {"azure" , PALETTERGB (240,255,255)},
1214 {"alice blue" , PALETTERGB (240,248,255)},
1215 {"AliceBlue" , PALETTERGB (240,248,255)},
1216 {"lavender" , PALETTERGB (230,230,250)},
1217 {"lavender blush" , PALETTERGB (255,240,245)},
1218 {"LavenderBlush" , PALETTERGB (255,240,245)},
1219 {"misty rose" , PALETTERGB (255,228,225)},
1220 {"MistyRose" , PALETTERGB (255,228,225)},
1221 {"white" , PALETTERGB (255,255,255)},
1222 {"black" , PALETTERGB ( 0, 0, 0)},
1223 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1224 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1225 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1226 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1227 {"dim gray" , PALETTERGB (105,105,105)},
1228 {"DimGray" , PALETTERGB (105,105,105)},
1229 {"dim grey" , PALETTERGB (105,105,105)},
1230 {"DimGrey" , PALETTERGB (105,105,105)},
1231 {"slate gray" , PALETTERGB (112,128,144)},
1232 {"SlateGray" , PALETTERGB (112,128,144)},
1233 {"slate grey" , PALETTERGB (112,128,144)},
1234 {"SlateGrey" , PALETTERGB (112,128,144)},
1235 {"light slate gray" , PALETTERGB (119,136,153)},
1236 {"LightSlateGray" , PALETTERGB (119,136,153)},
1237 {"light slate grey" , PALETTERGB (119,136,153)},
1238 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1239 {"gray" , PALETTERGB (190,190,190)},
1240 {"grey" , PALETTERGB (190,190,190)},
1241 {"light grey" , PALETTERGB (211,211,211)},
1242 {"LightGrey" , PALETTERGB (211,211,211)},
1243 {"light gray" , PALETTERGB (211,211,211)},
1244 {"LightGray" , PALETTERGB (211,211,211)},
1245 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1246 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1247 {"navy" , PALETTERGB ( 0, 0,128)},
1248 {"navy blue" , PALETTERGB ( 0, 0,128)},
1249 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1250 {"cornflower blue" , PALETTERGB (100,149,237)},
1251 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1252 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1253 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1254 {"slate blue" , PALETTERGB (106, 90,205)},
1255 {"SlateBlue" , PALETTERGB (106, 90,205)},
1256 {"medium slate blue" , PALETTERGB (123,104,238)},
1257 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1258 {"light slate blue" , PALETTERGB (132,112,255)},
1259 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1260 {"medium blue" , PALETTERGB ( 0, 0,205)},
1261 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1262 {"royal blue" , PALETTERGB ( 65,105,225)},
1263 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1264 {"blue" , PALETTERGB ( 0, 0,255)},
1265 {"dodger blue" , PALETTERGB ( 30,144,255)},
1266 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1267 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1268 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1269 {"sky blue" , PALETTERGB (135,206,235)},
1270 {"SkyBlue" , PALETTERGB (135,206,235)},
1271 {"light sky blue" , PALETTERGB (135,206,250)},
1272 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1273 {"steel blue" , PALETTERGB ( 70,130,180)},
1274 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1275 {"light steel blue" , PALETTERGB (176,196,222)},
1276 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1277 {"light blue" , PALETTERGB (173,216,230)},
1278 {"LightBlue" , PALETTERGB (173,216,230)},
1279 {"powder blue" , PALETTERGB (176,224,230)},
1280 {"PowderBlue" , PALETTERGB (176,224,230)},
1281 {"pale turquoise" , PALETTERGB (175,238,238)},
1282 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1283 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1284 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1285 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1286 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1287 {"turquoise" , PALETTERGB ( 64,224,208)},
1288 {"cyan" , PALETTERGB ( 0,255,255)},
1289 {"light cyan" , PALETTERGB (224,255,255)},
1290 {"LightCyan" , PALETTERGB (224,255,255)},
1291 {"cadet blue" , PALETTERGB ( 95,158,160)},
1292 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1293 {"medium aquamarine" , PALETTERGB (102,205,170)},
1294 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1295 {"aquamarine" , PALETTERGB (127,255,212)},
1296 {"dark green" , PALETTERGB ( 0,100, 0)},
1297 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1298 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1299 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1300 {"dark sea green" , PALETTERGB (143,188,143)},
1301 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1302 {"sea green" , PALETTERGB ( 46,139, 87)},
1303 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1304 {"medium sea green" , PALETTERGB ( 60,179,113)},
1305 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1306 {"light sea green" , PALETTERGB ( 32,178,170)},
1307 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1308 {"pale green" , PALETTERGB (152,251,152)},
1309 {"PaleGreen" , PALETTERGB (152,251,152)},
1310 {"spring green" , PALETTERGB ( 0,255,127)},
1311 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1312 {"lawn green" , PALETTERGB (124,252, 0)},
1313 {"LawnGreen" , PALETTERGB (124,252, 0)},
1314 {"green" , PALETTERGB ( 0,255, 0)},
1315 {"chartreuse" , PALETTERGB (127,255, 0)},
1316 {"medium spring green" , PALETTERGB ( 0,250,154)},
1317 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1318 {"green yellow" , PALETTERGB (173,255, 47)},
1319 {"GreenYellow" , PALETTERGB (173,255, 47)},
1320 {"lime green" , PALETTERGB ( 50,205, 50)},
1321 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1322 {"yellow green" , PALETTERGB (154,205, 50)},
1323 {"YellowGreen" , PALETTERGB (154,205, 50)},
1324 {"forest green" , PALETTERGB ( 34,139, 34)},
1325 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1326 {"olive drab" , PALETTERGB (107,142, 35)},
1327 {"OliveDrab" , PALETTERGB (107,142, 35)},
1328 {"dark khaki" , PALETTERGB (189,183,107)},
1329 {"DarkKhaki" , PALETTERGB (189,183,107)},
1330 {"khaki" , PALETTERGB (240,230,140)},
1331 {"pale goldenrod" , PALETTERGB (238,232,170)},
1332 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1333 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1334 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1335 {"light yellow" , PALETTERGB (255,255,224)},
1336 {"LightYellow" , PALETTERGB (255,255,224)},
1337 {"yellow" , PALETTERGB (255,255, 0)},
1338 {"gold" , PALETTERGB (255,215, 0)},
1339 {"light goldenrod" , PALETTERGB (238,221,130)},
1340 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1341 {"goldenrod" , PALETTERGB (218,165, 32)},
1342 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1343 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1344 {"rosy brown" , PALETTERGB (188,143,143)},
1345 {"RosyBrown" , PALETTERGB (188,143,143)},
1346 {"indian red" , PALETTERGB (205, 92, 92)},
1347 {"IndianRed" , PALETTERGB (205, 92, 92)},
1348 {"saddle brown" , PALETTERGB (139, 69, 19)},
1349 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1350 {"sienna" , PALETTERGB (160, 82, 45)},
1351 {"peru" , PALETTERGB (205,133, 63)},
1352 {"burlywood" , PALETTERGB (222,184,135)},
1353 {"beige" , PALETTERGB (245,245,220)},
1354 {"wheat" , PALETTERGB (245,222,179)},
1355 {"sandy brown" , PALETTERGB (244,164, 96)},
1356 {"SandyBrown" , PALETTERGB (244,164, 96)},
1357 {"tan" , PALETTERGB (210,180,140)},
1358 {"chocolate" , PALETTERGB (210,105, 30)},
1359 {"firebrick" , PALETTERGB (178,34, 34)},
1360 {"brown" , PALETTERGB (165,42, 42)},
1361 {"dark salmon" , PALETTERGB (233,150,122)},
1362 {"DarkSalmon" , PALETTERGB (233,150,122)},
1363 {"salmon" , PALETTERGB (250,128,114)},
1364 {"light salmon" , PALETTERGB (255,160,122)},
1365 {"LightSalmon" , PALETTERGB (255,160,122)},
1366 {"orange" , PALETTERGB (255,165, 0)},
1367 {"dark orange" , PALETTERGB (255,140, 0)},
1368 {"DarkOrange" , PALETTERGB (255,140, 0)},
1369 {"coral" , PALETTERGB (255,127, 80)},
1370 {"light coral" , PALETTERGB (240,128,128)},
1371 {"LightCoral" , PALETTERGB (240,128,128)},
1372 {"tomato" , PALETTERGB (255, 99, 71)},
1373 {"orange red" , PALETTERGB (255, 69, 0)},
1374 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1375 {"red" , PALETTERGB (255, 0, 0)},
1376 {"hot pink" , PALETTERGB (255,105,180)},
1377 {"HotPink" , PALETTERGB (255,105,180)},
1378 {"deep pink" , PALETTERGB (255, 20,147)},
1379 {"DeepPink" , PALETTERGB (255, 20,147)},
1380 {"pink" , PALETTERGB (255,192,203)},
1381 {"light pink" , PALETTERGB (255,182,193)},
1382 {"LightPink" , PALETTERGB (255,182,193)},
1383 {"pale violet red" , PALETTERGB (219,112,147)},
1384 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1385 {"maroon" , PALETTERGB (176, 48, 96)},
1386 {"medium violet red" , PALETTERGB (199, 21,133)},
1387 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1388 {"violet red" , PALETTERGB (208, 32,144)},
1389 {"VioletRed" , PALETTERGB (208, 32,144)},
1390 {"magenta" , PALETTERGB (255, 0,255)},
1391 {"violet" , PALETTERGB (238,130,238)},
1392 {"plum" , PALETTERGB (221,160,221)},
1393 {"orchid" , PALETTERGB (218,112,214)},
1394 {"medium orchid" , PALETTERGB (186, 85,211)},
1395 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1396 {"dark orchid" , PALETTERGB (153, 50,204)},
1397 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1398 {"dark violet" , PALETTERGB (148, 0,211)},
1399 {"DarkViolet" , PALETTERGB (148, 0,211)},
1400 {"blue violet" , PALETTERGB (138, 43,226)},
1401 {"BlueViolet" , PALETTERGB (138, 43,226)},
1402 {"purple" , PALETTERGB (160, 32,240)},
1403 {"medium purple" , PALETTERGB (147,112,219)},
1404 {"MediumPurple" , PALETTERGB (147,112,219)},
1405 {"thistle" , PALETTERGB (216,191,216)},
1406 {"gray0" , PALETTERGB ( 0, 0, 0)},
1407 {"grey0" , PALETTERGB ( 0, 0, 0)},
1408 {"dark grey" , PALETTERGB (169,169,169)},
1409 {"DarkGrey" , PALETTERGB (169,169,169)},
1410 {"dark gray" , PALETTERGB (169,169,169)},
1411 {"DarkGray" , PALETTERGB (169,169,169)},
1412 {"dark blue" , PALETTERGB ( 0, 0,139)},
1413 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1414 {"dark cyan" , PALETTERGB ( 0,139,139)},
1415 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1416 {"dark magenta" , PALETTERGB (139, 0,139)},
1417 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1418 {"dark red" , PALETTERGB (139, 0, 0)},
1419 {"DarkRed" , PALETTERGB (139, 0, 0)},
1420 {"light green" , PALETTERGB (144,238,144)},
1421 {"LightGreen" , PALETTERGB (144,238,144)},
1422 };
1423
1424 DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
1425 0, 0, 0, doc: /* Return the default color map. */)
1426 ()
1427 {
1428 int i;
1429 colormap_t *pc = w32_color_map;
1430 Lisp_Object cmap;
1431
1432 BLOCK_INPUT;
1433
1434 cmap = Qnil;
1435
1436 for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
1437 pc++, i++)
1438 cmap = Fcons (Fcons (build_string (pc->name),
1439 make_number (pc->colorref)),
1440 cmap);
1441
1442 UNBLOCK_INPUT;
1443
1444 return (cmap);
1445 }
1446
1447 Lisp_Object
1448 w32_to_x_color (rgb)
1449 Lisp_Object rgb;
1450 {
1451 Lisp_Object color;
1452
1453 CHECK_NUMBER (rgb);
1454
1455 BLOCK_INPUT;
1456
1457 color = Frassq (rgb, Vw32_color_map);
1458
1459 UNBLOCK_INPUT;
1460
1461 if (!NILP (color))
1462 return (Fcar (color));
1463 else
1464 return Qnil;
1465 }
1466
1467 COLORREF
1468 w32_color_map_lookup (colorname)
1469 char *colorname;
1470 {
1471 Lisp_Object tail, ret = Qnil;
1472
1473 BLOCK_INPUT;
1474
1475 for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail))
1476 {
1477 register Lisp_Object elt, tem;
1478
1479 elt = Fcar (tail);
1480 if (!CONSP (elt)) continue;
1481
1482 tem = Fcar (elt);
1483
1484 if (lstrcmpi (XSTRING (tem)->data, colorname) == 0)
1485 {
1486 ret = XUINT (Fcdr (elt));
1487 break;
1488 }
1489
1490 QUIT;
1491 }
1492
1493
1494 UNBLOCK_INPUT;
1495
1496 return ret;
1497 }
1498
1499 COLORREF
1500 x_to_w32_color (colorname)
1501 char * colorname;
1502 {
1503 register Lisp_Object ret = Qnil;
1504
1505 BLOCK_INPUT;
1506
1507 if (colorname[0] == '#')
1508 {
1509 /* Could be an old-style RGB Device specification. */
1510 char *color;
1511 int size;
1512 color = colorname + 1;
1513
1514 size = strlen(color);
1515 if (size == 3 || size == 6 || size == 9 || size == 12)
1516 {
1517 UINT colorval;
1518 int i, pos;
1519 pos = 0;
1520 size /= 3;
1521 colorval = 0;
1522
1523 for (i = 0; i < 3; i++)
1524 {
1525 char *end;
1526 char t;
1527 unsigned long value;
1528
1529 /* The check for 'x' in the following conditional takes into
1530 account the fact that strtol allows a "0x" in front of
1531 our numbers, and we don't. */
1532 if (!isxdigit(color[0]) || color[1] == 'x')
1533 break;
1534 t = color[size];
1535 color[size] = '\0';
1536 value = strtoul(color, &end, 16);
1537 color[size] = t;
1538 if (errno == ERANGE || end - color != size)
1539 break;
1540 switch (size)
1541 {
1542 case 1:
1543 value = value * 0x10;
1544 break;
1545 case 2:
1546 break;
1547 case 3:
1548 value /= 0x10;
1549 break;
1550 case 4:
1551 value /= 0x100;
1552 break;
1553 }
1554 colorval |= (value << pos);
1555 pos += 0x8;
1556 if (i == 2)
1557 {
1558 UNBLOCK_INPUT;
1559 return (colorval);
1560 }
1561 color = end;
1562 }
1563 }
1564 }
1565 else if (strnicmp(colorname, "rgb:", 4) == 0)
1566 {
1567 char *color;
1568 UINT colorval;
1569 int i, pos;
1570 pos = 0;
1571
1572 colorval = 0;
1573 color = colorname + 4;
1574 for (i = 0; i < 3; i++)
1575 {
1576 char *end;
1577 unsigned long value;
1578
1579 /* The check for 'x' in the following conditional takes into
1580 account the fact that strtol allows a "0x" in front of
1581 our numbers, and we don't. */
1582 if (!isxdigit(color[0]) || color[1] == 'x')
1583 break;
1584 value = strtoul(color, &end, 16);
1585 if (errno == ERANGE)
1586 break;
1587 switch (end - color)
1588 {
1589 case 1:
1590 value = value * 0x10 + value;
1591 break;
1592 case 2:
1593 break;
1594 case 3:
1595 value /= 0x10;
1596 break;
1597 case 4:
1598 value /= 0x100;
1599 break;
1600 default:
1601 value = ULONG_MAX;
1602 }
1603 if (value == ULONG_MAX)
1604 break;
1605 colorval |= (value << pos);
1606 pos += 0x8;
1607 if (i == 2)
1608 {
1609 if (*end != '\0')
1610 break;
1611 UNBLOCK_INPUT;
1612 return (colorval);
1613 }
1614 if (*end != '/')
1615 break;
1616 color = end + 1;
1617 }
1618 }
1619 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1620 {
1621 /* This is an RGB Intensity specification. */
1622 char *color;
1623 UINT colorval;
1624 int i, pos;
1625 pos = 0;
1626
1627 colorval = 0;
1628 color = colorname + 5;
1629 for (i = 0; i < 3; i++)
1630 {
1631 char *end;
1632 double value;
1633 UINT val;
1634
1635 value = strtod(color, &end);
1636 if (errno == ERANGE)
1637 break;
1638 if (value < 0.0 || value > 1.0)
1639 break;
1640 val = (UINT)(0x100 * value);
1641 /* We used 0x100 instead of 0xFF to give an continuous
1642 range between 0.0 and 1.0 inclusive. The next statement
1643 fixes the 1.0 case. */
1644 if (val == 0x100)
1645 val = 0xFF;
1646 colorval |= (val << pos);
1647 pos += 0x8;
1648 if (i == 2)
1649 {
1650 if (*end != '\0')
1651 break;
1652 UNBLOCK_INPUT;
1653 return (colorval);
1654 }
1655 if (*end != '/')
1656 break;
1657 color = end + 1;
1658 }
1659 }
1660 /* I am not going to attempt to handle any of the CIE color schemes
1661 or TekHVC, since I don't know the algorithms for conversion to
1662 RGB. */
1663
1664 /* If we fail to lookup the color name in w32_color_map, then check the
1665 colorname to see if it can be crudely approximated: If the X color
1666 ends in a number (e.g., "darkseagreen2"), strip the number and
1667 return the result of looking up the base color name. */
1668 ret = w32_color_map_lookup (colorname);
1669 if (NILP (ret))
1670 {
1671 int len = strlen (colorname);
1672
1673 if (isdigit (colorname[len - 1]))
1674 {
1675 char *ptr, *approx = alloca (len + 1);
1676
1677 strcpy (approx, colorname);
1678 ptr = &approx[len - 1];
1679 while (ptr > approx && isdigit (*ptr))
1680 *ptr-- = '\0';
1681
1682 ret = w32_color_map_lookup (approx);
1683 }
1684 }
1685
1686 UNBLOCK_INPUT;
1687 return ret;
1688 }
1689
1690
1691 void
1692 w32_regenerate_palette (FRAME_PTR f)
1693 {
1694 struct w32_palette_entry * list;
1695 LOGPALETTE * log_palette;
1696 HPALETTE new_palette;
1697 int i;
1698
1699 /* don't bother trying to create palette if not supported */
1700 if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
1701 return;
1702
1703 log_palette = (LOGPALETTE *)
1704 alloca (sizeof (LOGPALETTE) +
1705 FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
1706 log_palette->palVersion = 0x300;
1707 log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
1708
1709 list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1710 for (i = 0;
1711 i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
1712 i++, list = list->next)
1713 log_palette->palPalEntry[i] = list->entry;
1714
1715 new_palette = CreatePalette (log_palette);
1716
1717 enter_crit ();
1718
1719 if (FRAME_W32_DISPLAY_INFO (f)->palette)
1720 DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
1721 FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
1722
1723 /* Realize display palette and garbage all frames. */
1724 release_frame_dc (f, get_frame_dc (f));
1725
1726 leave_crit ();
1727 }
1728
1729 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1730 #define SET_W32_COLOR(pe, color) \
1731 do \
1732 { \
1733 pe.peRed = GetRValue (color); \
1734 pe.peGreen = GetGValue (color); \
1735 pe.peBlue = GetBValue (color); \
1736 pe.peFlags = 0; \
1737 } while (0)
1738
1739 #if 0
1740 /* Keep these around in case we ever want to track color usage. */
1741 void
1742 w32_map_color (FRAME_PTR f, COLORREF color)
1743 {
1744 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1745
1746 if (NILP (Vw32_enable_palette))
1747 return;
1748
1749 /* check if color is already mapped */
1750 while (list)
1751 {
1752 if (W32_COLOR (list->entry) == color)
1753 {
1754 ++list->refcount;
1755 return;
1756 }
1757 list = list->next;
1758 }
1759
1760 /* not already mapped, so add to list and recreate Windows palette */
1761 list = (struct w32_palette_entry *)
1762 xmalloc (sizeof (struct w32_palette_entry));
1763 SET_W32_COLOR (list->entry, color);
1764 list->refcount = 1;
1765 list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
1766 FRAME_W32_DISPLAY_INFO (f)->color_list = list;
1767 FRAME_W32_DISPLAY_INFO (f)->num_colors++;
1768
1769 /* set flag that palette must be regenerated */
1770 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1771 }
1772
1773 void
1774 w32_unmap_color (FRAME_PTR f, COLORREF color)
1775 {
1776 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1777 struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
1778
1779 if (NILP (Vw32_enable_palette))
1780 return;
1781
1782 /* check if color is already mapped */
1783 while (list)
1784 {
1785 if (W32_COLOR (list->entry) == color)
1786 {
1787 if (--list->refcount == 0)
1788 {
1789 *prev = list->next;
1790 xfree (list);
1791 FRAME_W32_DISPLAY_INFO (f)->num_colors--;
1792 break;
1793 }
1794 else
1795 return;
1796 }
1797 prev = &list->next;
1798 list = list->next;
1799 }
1800
1801 /* set flag that palette must be regenerated */
1802 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1803 }
1804 #endif
1805
1806
1807 /* Gamma-correct COLOR on frame F. */
1808
1809 void
1810 gamma_correct (f, color)
1811 struct frame *f;
1812 COLORREF *color;
1813 {
1814 if (f->gamma)
1815 {
1816 *color = PALETTERGB (
1817 pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1818 pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1819 pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5);
1820 }
1821 }
1822
1823
1824 /* Decide if color named COLOR is valid for the display associated with
1825 the selected frame; if so, return the rgb values in COLOR_DEF.
1826 If ALLOC is nonzero, allocate a new colormap cell. */
1827
1828 int
1829 w32_defined_color (f, color, color_def, alloc)
1830 FRAME_PTR f;
1831 char *color;
1832 XColor *color_def;
1833 int alloc;
1834 {
1835 register Lisp_Object tem;
1836 COLORREF w32_color_ref;
1837
1838 tem = x_to_w32_color (color);
1839
1840 if (!NILP (tem))
1841 {
1842 if (f)
1843 {
1844 /* Apply gamma correction. */
1845 w32_color_ref = XUINT (tem);
1846 gamma_correct (f, &w32_color_ref);
1847 XSETINT (tem, w32_color_ref);
1848 }
1849
1850 /* Map this color to the palette if it is enabled. */
1851 if (!NILP (Vw32_enable_palette))
1852 {
1853 struct w32_palette_entry * entry =
1854 one_w32_display_info.color_list;
1855 struct w32_palette_entry ** prev =
1856 &one_w32_display_info.color_list;
1857
1858 /* check if color is already mapped */
1859 while (entry)
1860 {
1861 if (W32_COLOR (entry->entry) == XUINT (tem))
1862 break;
1863 prev = &entry->next;
1864 entry = entry->next;
1865 }
1866
1867 if (entry == NULL && alloc)
1868 {
1869 /* not already mapped, so add to list */
1870 entry = (struct w32_palette_entry *)
1871 xmalloc (sizeof (struct w32_palette_entry));
1872 SET_W32_COLOR (entry->entry, XUINT (tem));
1873 entry->next = NULL;
1874 *prev = entry;
1875 one_w32_display_info.num_colors++;
1876
1877 /* set flag that palette must be regenerated */
1878 one_w32_display_info.regen_palette = TRUE;
1879 }
1880 }
1881 /* Ensure COLORREF value is snapped to nearest color in (default)
1882 palette by simulating the PALETTERGB macro. This works whether
1883 or not the display device has a palette. */
1884 w32_color_ref = XUINT (tem) | 0x2000000;
1885
1886 color_def->pixel = w32_color_ref;
1887 color_def->red = GetRValue (w32_color_ref);
1888 color_def->green = GetGValue (w32_color_ref);
1889 color_def->blue = GetBValue (w32_color_ref);
1890
1891 return 1;
1892 }
1893 else
1894 {
1895 return 0;
1896 }
1897 }
1898
1899 /* Given a string ARG naming a color, compute a pixel value from it
1900 suitable for screen F.
1901 If F is not a color screen, return DEF (default) regardless of what
1902 ARG says. */
1903
1904 int
1905 x_decode_color (f, arg, def)
1906 FRAME_PTR f;
1907 Lisp_Object arg;
1908 int def;
1909 {
1910 XColor cdef;
1911
1912 CHECK_STRING (arg);
1913
1914 if (strcmp (XSTRING (arg)->data, "black") == 0)
1915 return BLACK_PIX_DEFAULT (f);
1916 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1917 return WHITE_PIX_DEFAULT (f);
1918
1919 if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
1920 return def;
1921
1922 /* w32_defined_color is responsible for coping with failures
1923 by looking for a near-miss. */
1924 if (w32_defined_color (f, XSTRING (arg)->data, &cdef, 1))
1925 return cdef.pixel;
1926
1927 /* defined_color failed; return an ultimate default. */
1928 return def;
1929 }
1930 \f
1931 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1932 the previous value of that parameter, NEW_VALUE is the new value. */
1933
1934 static void
1935 x_set_line_spacing (f, new_value, old_value)
1936 struct frame *f;
1937 Lisp_Object new_value, old_value;
1938 {
1939 if (NILP (new_value))
1940 f->extra_line_spacing = 0;
1941 else if (NATNUMP (new_value))
1942 f->extra_line_spacing = XFASTINT (new_value);
1943 else
1944 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1945 Fcons (new_value, Qnil)));
1946 if (FRAME_VISIBLE_P (f))
1947 redraw_frame (f);
1948 }
1949
1950
1951 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1952 the previous value of that parameter, NEW_VALUE is the new value. */
1953
1954 static void
1955 x_set_screen_gamma (f, new_value, old_value)
1956 struct frame *f;
1957 Lisp_Object new_value, old_value;
1958 {
1959 if (NILP (new_value))
1960 f->gamma = 0;
1961 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1962 /* The value 0.4545 is the normal viewing gamma. */
1963 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1964 else
1965 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1966 Fcons (new_value, Qnil)));
1967
1968 clear_face_cache (0);
1969 }
1970
1971
1972 /* Functions called only from `x_set_frame_param'
1973 to set individual parameters.
1974
1975 If FRAME_W32_WINDOW (f) is 0,
1976 the frame is being created and its window does not exist yet.
1977 In that case, just record the parameter's new value
1978 in the standard place; do not attempt to change the window. */
1979
1980 void
1981 x_set_foreground_color (f, arg, oldval)
1982 struct frame *f;
1983 Lisp_Object arg, oldval;
1984 {
1985 struct w32_output *x = f->output_data.w32;
1986 PIX_TYPE fg, old_fg;
1987
1988 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1989 old_fg = FRAME_FOREGROUND_PIXEL (f);
1990 FRAME_FOREGROUND_PIXEL (f) = fg;
1991
1992 if (FRAME_W32_WINDOW (f) != 0)
1993 {
1994 if (x->cursor_pixel == old_fg)
1995 x->cursor_pixel = fg;
1996
1997 update_face_from_frame_parameter (f, Qforeground_color, arg);
1998 if (FRAME_VISIBLE_P (f))
1999 redraw_frame (f);
2000 }
2001 }
2002
2003 void
2004 x_set_background_color (f, arg, oldval)
2005 struct frame *f;
2006 Lisp_Object arg, oldval;
2007 {
2008 FRAME_BACKGROUND_PIXEL (f)
2009 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
2010
2011 if (FRAME_W32_WINDOW (f) != 0)
2012 {
2013 SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX,
2014 FRAME_BACKGROUND_PIXEL (f));
2015
2016 update_face_from_frame_parameter (f, Qbackground_color, arg);
2017
2018 if (FRAME_VISIBLE_P (f))
2019 redraw_frame (f);
2020 }
2021 }
2022
2023 void
2024 x_set_mouse_color (f, arg, oldval)
2025 struct frame *f;
2026 Lisp_Object arg, oldval;
2027 {
2028 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
2029 int count;
2030 int mask_color;
2031
2032 if (!EQ (Qnil, arg))
2033 f->output_data.w32->mouse_pixel
2034 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2035 mask_color = FRAME_BACKGROUND_PIXEL (f);
2036
2037 /* Don't let pointers be invisible. */
2038 if (mask_color == f->output_data.w32->mouse_pixel
2039 && mask_color == FRAME_BACKGROUND_PIXEL (f))
2040 f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
2041
2042 #if 0 /* TODO : cursor changes */
2043 BLOCK_INPUT;
2044
2045 /* It's not okay to crash if the user selects a screwy cursor. */
2046 count = x_catch_errors (FRAME_W32_DISPLAY (f));
2047
2048 if (!EQ (Qnil, Vx_pointer_shape))
2049 {
2050 CHECK_NUMBER (Vx_pointer_shape);
2051 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
2052 }
2053 else
2054 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2055 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
2056
2057 if (!EQ (Qnil, Vx_nontext_pointer_shape))
2058 {
2059 CHECK_NUMBER (Vx_nontext_pointer_shape);
2060 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2061 XINT (Vx_nontext_pointer_shape));
2062 }
2063 else
2064 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
2065 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2066
2067 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
2068 {
2069 CHECK_NUMBER (Vx_hourglass_pointer_shape);
2070 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2071 XINT (Vx_hourglass_pointer_shape));
2072 }
2073 else
2074 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
2075 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
2076
2077 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2078 if (!EQ (Qnil, Vx_mode_pointer_shape))
2079 {
2080 CHECK_NUMBER (Vx_mode_pointer_shape);
2081 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2082 XINT (Vx_mode_pointer_shape));
2083 }
2084 else
2085 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2086 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
2087
2088 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
2089 {
2090 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
2091 cross_cursor
2092 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2093 XINT (Vx_sensitive_text_pointer_shape));
2094 }
2095 else
2096 cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
2097
2098 if (!NILP (Vx_window_horizontal_drag_shape))
2099 {
2100 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
2101 horizontal_drag_cursor
2102 = XCreateFontCursor (FRAME_X_DISPLAY (f),
2103 XINT (Vx_window_horizontal_drag_shape));
2104 }
2105 else
2106 horizontal_drag_cursor
2107 = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
2108
2109 /* Check and report errors with the above calls. */
2110 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
2111 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
2112
2113 {
2114 XColor fore_color, back_color;
2115
2116 fore_color.pixel = f->output_data.w32->mouse_pixel;
2117 back_color.pixel = mask_color;
2118 XQueryColor (FRAME_W32_DISPLAY (f),
2119 DefaultColormap (FRAME_W32_DISPLAY (f),
2120 DefaultScreen (FRAME_W32_DISPLAY (f))),
2121 &fore_color);
2122 XQueryColor (FRAME_W32_DISPLAY (f),
2123 DefaultColormap (FRAME_W32_DISPLAY (f),
2124 DefaultScreen (FRAME_W32_DISPLAY (f))),
2125 &back_color);
2126 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
2127 &fore_color, &back_color);
2128 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
2129 &fore_color, &back_color);
2130 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
2131 &fore_color, &back_color);
2132 XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
2133 &fore_color, &back_color);
2134 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
2135 &fore_color, &back_color);
2136 }
2137
2138 if (FRAME_W32_WINDOW (f) != 0)
2139 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
2140
2141 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
2142 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
2143 f->output_data.w32->text_cursor = cursor;
2144
2145 if (nontext_cursor != f->output_data.w32->nontext_cursor
2146 && f->output_data.w32->nontext_cursor != 0)
2147 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
2148 f->output_data.w32->nontext_cursor = nontext_cursor;
2149
2150 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
2151 && f->output_data.w32->hourglass_cursor != 0)
2152 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
2153 f->output_data.w32->hourglass_cursor = hourglass_cursor;
2154
2155 if (mode_cursor != f->output_data.w32->modeline_cursor
2156 && f->output_data.w32->modeline_cursor != 0)
2157 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
2158 f->output_data.w32->modeline_cursor = mode_cursor;
2159
2160 if (cross_cursor != f->output_data.w32->cross_cursor
2161 && f->output_data.w32->cross_cursor != 0)
2162 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
2163 f->output_data.w32->cross_cursor = cross_cursor;
2164
2165 XFlush (FRAME_W32_DISPLAY (f));
2166 UNBLOCK_INPUT;
2167
2168 update_face_from_frame_parameter (f, Qmouse_color, arg);
2169 #endif /* TODO */
2170 }
2171
2172 /* Defined in w32term.c. */
2173 void x_update_cursor (struct frame *f, int on_p);
2174
2175 void
2176 x_set_cursor_color (f, arg, oldval)
2177 struct frame *f;
2178 Lisp_Object arg, oldval;
2179 {
2180 unsigned long fore_pixel, pixel;
2181
2182 if (!NILP (Vx_cursor_fore_pixel))
2183 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
2184 WHITE_PIX_DEFAULT (f));
2185 else
2186 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2187
2188 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2189
2190 /* Make sure that the cursor color differs from the background color. */
2191 if (pixel == FRAME_BACKGROUND_PIXEL (f))
2192 {
2193 pixel = f->output_data.w32->mouse_pixel;
2194 if (pixel == fore_pixel)
2195 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2196 }
2197
2198 FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
2199 f->output_data.w32->cursor_pixel = pixel;
2200
2201 if (FRAME_W32_WINDOW (f) != 0)
2202 {
2203 if (FRAME_VISIBLE_P (f))
2204 {
2205 x_update_cursor (f, 0);
2206 x_update_cursor (f, 1);
2207 }
2208 }
2209
2210 update_face_from_frame_parameter (f, Qcursor_color, arg);
2211 }
2212
2213 /* Set the border-color of frame F to pixel value PIX.
2214 Note that this does not fully take effect if done before
2215 F has an window. */
2216 void
2217 x_set_border_pixel (f, pix)
2218 struct frame *f;
2219 int pix;
2220 {
2221 f->output_data.w32->border_pixel = pix;
2222
2223 if (FRAME_W32_WINDOW (f) != 0 && f->output_data.w32->border_width > 0)
2224 {
2225 if (FRAME_VISIBLE_P (f))
2226 redraw_frame (f);
2227 }
2228 }
2229
2230 /* Set the border-color of frame F to value described by ARG.
2231 ARG can be a string naming a color.
2232 The border-color is used for the border that is drawn by the server.
2233 Note that this does not fully take effect if done before
2234 F has a window; it must be redone when the window is created. */
2235
2236 void
2237 x_set_border_color (f, arg, oldval)
2238 struct frame *f;
2239 Lisp_Object arg, oldval;
2240 {
2241 int pix;
2242
2243 CHECK_STRING (arg);
2244 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2245 x_set_border_pixel (f, pix);
2246 update_face_from_frame_parameter (f, Qborder_color, arg);
2247 }
2248
2249 /* Value is the internal representation of the specified cursor type
2250 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
2251 of the bar cursor. */
2252
2253 enum text_cursor_kinds
2254 x_specified_cursor_type (arg, width)
2255 Lisp_Object arg;
2256 int *width;
2257 {
2258 enum text_cursor_kinds type;
2259
2260 if (EQ (arg, Qbar))
2261 {
2262 type = BAR_CURSOR;
2263 *width = 2;
2264 }
2265 else if (CONSP (arg)
2266 && EQ (XCAR (arg), Qbar)
2267 && INTEGERP (XCDR (arg))
2268 && XINT (XCDR (arg)) >= 0)
2269 {
2270 type = BAR_CURSOR;
2271 *width = XINT (XCDR (arg));
2272 }
2273 else if (NILP (arg))
2274 type = NO_CURSOR;
2275 else
2276 /* Treat anything unknown as "box cursor".
2277 It was bad to signal an error; people have trouble fixing
2278 .Xdefaults with Emacs, when it has something bad in it. */
2279 type = FILLED_BOX_CURSOR;
2280
2281 return type;
2282 }
2283
2284 void
2285 x_set_cursor_type (f, arg, oldval)
2286 FRAME_PTR f;
2287 Lisp_Object arg, oldval;
2288 {
2289 int width;
2290
2291 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
2292 f->output_data.w32->cursor_width = width;
2293
2294 /* Make sure the cursor gets redrawn. This is overkill, but how
2295 often do people change cursor types? */
2296 update_mode_lines++;
2297 }
2298 \f
2299 void
2300 x_set_icon_type (f, arg, oldval)
2301 struct frame *f;
2302 Lisp_Object arg, oldval;
2303 {
2304 int result;
2305
2306 if (NILP (arg) && NILP (oldval))
2307 return;
2308
2309 if (STRINGP (arg) && STRINGP (oldval)
2310 && EQ (Fstring_equal (oldval, arg), Qt))
2311 return;
2312
2313 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
2314 return;
2315
2316 BLOCK_INPUT;
2317
2318 result = x_bitmap_icon (f, arg);
2319 if (result)
2320 {
2321 UNBLOCK_INPUT;
2322 error ("No icon window available");
2323 }
2324
2325 UNBLOCK_INPUT;
2326 }
2327
2328 /* Return non-nil if frame F wants a bitmap icon. */
2329
2330 Lisp_Object
2331 x_icon_type (f)
2332 FRAME_PTR f;
2333 {
2334 Lisp_Object tem;
2335
2336 tem = assq_no_quit (Qicon_type, f->param_alist);
2337 if (CONSP (tem))
2338 return XCDR (tem);
2339 else
2340 return Qnil;
2341 }
2342
2343 void
2344 x_set_icon_name (f, arg, oldval)
2345 struct frame *f;
2346 Lisp_Object arg, oldval;
2347 {
2348 if (STRINGP (arg))
2349 {
2350 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
2351 return;
2352 }
2353 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
2354 return;
2355
2356 f->icon_name = arg;
2357
2358 #if 0
2359 if (f->output_data.w32->icon_bitmap != 0)
2360 return;
2361
2362 BLOCK_INPUT;
2363
2364 result = x_text_icon (f,
2365 (char *) XSTRING ((!NILP (f->icon_name)
2366 ? f->icon_name
2367 : !NILP (f->title)
2368 ? f->title
2369 : f->name))->data);
2370
2371 if (result)
2372 {
2373 UNBLOCK_INPUT;
2374 error ("No icon window available");
2375 }
2376
2377 /* If the window was unmapped (and its icon was mapped),
2378 the new icon is not mapped, so map the window in its stead. */
2379 if (FRAME_VISIBLE_P (f))
2380 {
2381 #ifdef USE_X_TOOLKIT
2382 XtPopup (f->output_data.w32->widget, XtGrabNone);
2383 #endif
2384 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
2385 }
2386
2387 XFlush (FRAME_W32_DISPLAY (f));
2388 UNBLOCK_INPUT;
2389 #endif
2390 }
2391
2392 extern Lisp_Object x_new_font ();
2393 extern Lisp_Object x_new_fontset();
2394
2395 void
2396 x_set_font (f, arg, oldval)
2397 struct frame *f;
2398 Lisp_Object arg, oldval;
2399 {
2400 Lisp_Object result;
2401 Lisp_Object fontset_name;
2402 Lisp_Object frame;
2403 int old_fontset = FRAME_FONTSET(f);
2404
2405 CHECK_STRING (arg);
2406
2407 fontset_name = Fquery_fontset (arg, Qnil);
2408
2409 BLOCK_INPUT;
2410 result = (STRINGP (fontset_name)
2411 ? x_new_fontset (f, XSTRING (fontset_name)->data)
2412 : x_new_font (f, XSTRING (arg)->data));
2413 UNBLOCK_INPUT;
2414
2415 if (EQ (result, Qnil))
2416 error ("Font `%s' is not defined", XSTRING (arg)->data);
2417 else if (EQ (result, Qt))
2418 error ("The characters of the given font have varying widths");
2419 else if (STRINGP (result))
2420 {
2421 if (STRINGP (fontset_name))
2422 {
2423 /* Fontset names are built from ASCII font names, so the
2424 names may be equal despite there was a change. */
2425 if (old_fontset == FRAME_FONTSET (f))
2426 return;
2427 }
2428 else if (!NILP (Fequal (result, oldval)))
2429 return;
2430
2431 store_frame_param (f, Qfont, result);
2432 recompute_basic_faces (f);
2433 }
2434 else
2435 abort ();
2436
2437 do_pending_window_change (0);
2438
2439 /* Don't call `face-set-after-frame-default' when faces haven't been
2440 initialized yet. This is the case when called from
2441 Fx_create_frame. In that case, the X widget or window doesn't
2442 exist either, and we can end up in x_report_frame_params with a
2443 null widget which gives a segfault. */
2444 if (FRAME_FACE_CACHE (f))
2445 {
2446 XSETFRAME (frame, f);
2447 call1 (Qface_set_after_frame_default, frame);
2448 }
2449 }
2450
2451 static void
2452 x_set_fringe_width (f, new_value, old_value)
2453 struct frame *f;
2454 Lisp_Object new_value, old_value;
2455 {
2456 x_compute_fringe_widths (f, 1);
2457 }
2458
2459 void
2460 x_set_border_width (f, arg, oldval)
2461 struct frame *f;
2462 Lisp_Object arg, oldval;
2463 {
2464 CHECK_NUMBER (arg);
2465
2466 if (XINT (arg) == f->output_data.w32->border_width)
2467 return;
2468
2469 if (FRAME_W32_WINDOW (f) != 0)
2470 error ("Cannot change the border width of a window");
2471
2472 f->output_data.w32->border_width = XINT (arg);
2473 }
2474
2475 void
2476 x_set_internal_border_width (f, arg, oldval)
2477 struct frame *f;
2478 Lisp_Object arg, oldval;
2479 {
2480 int old = f->output_data.w32->internal_border_width;
2481
2482 CHECK_NUMBER (arg);
2483 f->output_data.w32->internal_border_width = XINT (arg);
2484 if (f->output_data.w32->internal_border_width < 0)
2485 f->output_data.w32->internal_border_width = 0;
2486
2487 if (f->output_data.w32->internal_border_width == old)
2488 return;
2489
2490 if (FRAME_W32_WINDOW (f) != 0)
2491 {
2492 x_set_window_size (f, 0, f->width, f->height);
2493 SET_FRAME_GARBAGED (f);
2494 do_pending_window_change (0);
2495 }
2496 else
2497 SET_FRAME_GARBAGED (f);
2498 }
2499
2500 void
2501 x_set_visibility (f, value, oldval)
2502 struct frame *f;
2503 Lisp_Object value, oldval;
2504 {
2505 Lisp_Object frame;
2506 XSETFRAME (frame, f);
2507
2508 if (NILP (value))
2509 Fmake_frame_invisible (frame, Qt);
2510 else if (EQ (value, Qicon))
2511 Ficonify_frame (frame);
2512 else
2513 Fmake_frame_visible (frame);
2514 }
2515
2516 \f
2517 /* Change window heights in windows rooted in WINDOW by N lines. */
2518
2519 static void
2520 x_change_window_heights (window, n)
2521 Lisp_Object window;
2522 int n;
2523 {
2524 struct window *w = XWINDOW (window);
2525
2526 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2527 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2528
2529 if (INTEGERP (w->orig_top))
2530 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2531 if (INTEGERP (w->orig_height))
2532 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2533
2534 /* Handle just the top child in a vertical split. */
2535 if (!NILP (w->vchild))
2536 x_change_window_heights (w->vchild, n);
2537
2538 /* Adjust all children in a horizontal split. */
2539 for (window = w->hchild; !NILP (window); window = w->next)
2540 {
2541 w = XWINDOW (window);
2542 x_change_window_heights (window, n);
2543 }
2544 }
2545
2546 void
2547 x_set_menu_bar_lines (f, value, oldval)
2548 struct frame *f;
2549 Lisp_Object value, oldval;
2550 {
2551 int nlines;
2552 int olines = FRAME_MENU_BAR_LINES (f);
2553
2554 /* Right now, menu bars don't work properly in minibuf-only frames;
2555 most of the commands try to apply themselves to the minibuffer
2556 frame itself, and get an error because you can't switch buffers
2557 in or split the minibuffer window. */
2558 if (FRAME_MINIBUF_ONLY_P (f))
2559 return;
2560
2561 if (INTEGERP (value))
2562 nlines = XINT (value);
2563 else
2564 nlines = 0;
2565
2566 FRAME_MENU_BAR_LINES (f) = 0;
2567 if (nlines)
2568 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2569 else
2570 {
2571 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2572 free_frame_menubar (f);
2573 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2574
2575 /* Adjust the frame size so that the client (text) dimensions
2576 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2577 set correctly. */
2578 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2579 do_pending_window_change (0);
2580 }
2581 adjust_glyphs (f);
2582 }
2583
2584
2585 /* Set the number of lines used for the tool bar of frame F to VALUE.
2586 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2587 is the old number of tool bar lines. This function changes the
2588 height of all windows on frame F to match the new tool bar height.
2589 The frame's height doesn't change. */
2590
2591 void
2592 x_set_tool_bar_lines (f, value, oldval)
2593 struct frame *f;
2594 Lisp_Object value, oldval;
2595 {
2596 int delta, nlines, root_height;
2597 Lisp_Object root_window;
2598
2599 /* Treat tool bars like menu bars. */
2600 if (FRAME_MINIBUF_ONLY_P (f))
2601 return;
2602
2603 /* Use VALUE only if an integer >= 0. */
2604 if (INTEGERP (value) && XINT (value) >= 0)
2605 nlines = XFASTINT (value);
2606 else
2607 nlines = 0;
2608
2609 /* Make sure we redisplay all windows in this frame. */
2610 ++windows_or_buffers_changed;
2611
2612 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2613
2614 /* Don't resize the tool-bar to more than we have room for. */
2615 root_window = FRAME_ROOT_WINDOW (f);
2616 root_height = XINT (XWINDOW (root_window)->height);
2617 if (root_height - delta < 1)
2618 {
2619 delta = root_height - 1;
2620 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2621 }
2622
2623 FRAME_TOOL_BAR_LINES (f) = nlines;
2624 x_change_window_heights (root_window, delta);
2625 adjust_glyphs (f);
2626
2627 /* We also have to make sure that the internal border at the top of
2628 the frame, below the menu bar or tool bar, is redrawn when the
2629 tool bar disappears. This is so because the internal border is
2630 below the tool bar if one is displayed, but is below the menu bar
2631 if there isn't a tool bar. The tool bar draws into the area
2632 below the menu bar. */
2633 if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2634 {
2635 updating_frame = f;
2636 clear_frame ();
2637 clear_current_matrices (f);
2638 updating_frame = NULL;
2639 }
2640
2641 /* If the tool bar gets smaller, the internal border below it
2642 has to be cleared. It was formerly part of the display
2643 of the larger tool bar, and updating windows won't clear it. */
2644 if (delta < 0)
2645 {
2646 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2647 int width = PIXEL_WIDTH (f);
2648 int y = nlines * CANON_Y_UNIT (f);
2649
2650 BLOCK_INPUT;
2651 {
2652 HDC hdc = get_frame_dc (f);
2653 w32_clear_area (f, hdc, 0, y, width, height);
2654 release_frame_dc (f, hdc);
2655 }
2656 UNBLOCK_INPUT;
2657
2658 if (WINDOWP (f->tool_bar_window))
2659 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2660 }
2661 }
2662
2663
2664 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2665 w32_id_name.
2666
2667 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2668 name; if NAME is a string, set F's name to NAME and set
2669 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2670
2671 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2672 suggesting a new name, which lisp code should override; if
2673 F->explicit_name is set, ignore the new name; otherwise, set it. */
2674
2675 void
2676 x_set_name (f, name, explicit)
2677 struct frame *f;
2678 Lisp_Object name;
2679 int explicit;
2680 {
2681 /* Make sure that requests from lisp code override requests from
2682 Emacs redisplay code. */
2683 if (explicit)
2684 {
2685 /* If we're switching from explicit to implicit, we had better
2686 update the mode lines and thereby update the title. */
2687 if (f->explicit_name && NILP (name))
2688 update_mode_lines = 1;
2689
2690 f->explicit_name = ! NILP (name);
2691 }
2692 else if (f->explicit_name)
2693 return;
2694
2695 /* If NAME is nil, set the name to the w32_id_name. */
2696 if (NILP (name))
2697 {
2698 /* Check for no change needed in this very common case
2699 before we do any consing. */
2700 if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
2701 XSTRING (f->name)->data))
2702 return;
2703 name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
2704 }
2705 else
2706 CHECK_STRING (name);
2707
2708 /* Don't change the name if it's already NAME. */
2709 if (! NILP (Fstring_equal (name, f->name)))
2710 return;
2711
2712 f->name = name;
2713
2714 /* For setting the frame title, the title parameter should override
2715 the name parameter. */
2716 if (! NILP (f->title))
2717 name = f->title;
2718
2719 if (FRAME_W32_WINDOW (f))
2720 {
2721 if (STRING_MULTIBYTE (name))
2722 name = ENCODE_SYSTEM (name);
2723
2724 BLOCK_INPUT;
2725 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
2726 UNBLOCK_INPUT;
2727 }
2728 }
2729
2730 /* This function should be called when the user's lisp code has
2731 specified a name for the frame; the name will override any set by the
2732 redisplay code. */
2733 void
2734 x_explicitly_set_name (f, arg, oldval)
2735 FRAME_PTR f;
2736 Lisp_Object arg, oldval;
2737 {
2738 x_set_name (f, arg, 1);
2739 }
2740
2741 /* This function should be called by Emacs redisplay code to set the
2742 name; names set this way will never override names set by the user's
2743 lisp code. */
2744 void
2745 x_implicitly_set_name (f, arg, oldval)
2746 FRAME_PTR f;
2747 Lisp_Object arg, oldval;
2748 {
2749 x_set_name (f, arg, 0);
2750 }
2751 \f
2752 /* Change the title of frame F to NAME.
2753 If NAME is nil, use the frame name as the title.
2754
2755 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2756 name; if NAME is a string, set F's name to NAME and set
2757 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2758
2759 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2760 suggesting a new name, which lisp code should override; if
2761 F->explicit_name is set, ignore the new name; otherwise, set it. */
2762
2763 void
2764 x_set_title (f, name, old_name)
2765 struct frame *f;
2766 Lisp_Object name, old_name;
2767 {
2768 /* Don't change the title if it's already NAME. */
2769 if (EQ (name, f->title))
2770 return;
2771
2772 update_mode_lines = 1;
2773
2774 f->title = name;
2775
2776 if (NILP (name))
2777 name = f->name;
2778
2779 if (FRAME_W32_WINDOW (f))
2780 {
2781 if (STRING_MULTIBYTE (name))
2782 name = ENCODE_SYSTEM (name);
2783
2784 BLOCK_INPUT;
2785 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
2786 UNBLOCK_INPUT;
2787 }
2788 }
2789 \f
2790 void
2791 x_set_autoraise (f, arg, oldval)
2792 struct frame *f;
2793 Lisp_Object arg, oldval;
2794 {
2795 f->auto_raise = !EQ (Qnil, arg);
2796 }
2797
2798 void
2799 x_set_autolower (f, arg, oldval)
2800 struct frame *f;
2801 Lisp_Object arg, oldval;
2802 {
2803 f->auto_lower = !EQ (Qnil, arg);
2804 }
2805
2806 void
2807 x_set_unsplittable (f, arg, oldval)
2808 struct frame *f;
2809 Lisp_Object arg, oldval;
2810 {
2811 f->no_split = !NILP (arg);
2812 }
2813
2814 void
2815 x_set_vertical_scroll_bars (f, arg, oldval)
2816 struct frame *f;
2817 Lisp_Object arg, oldval;
2818 {
2819 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2820 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2821 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2822 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2823 {
2824 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = NILP (arg) ?
2825 vertical_scroll_bar_none :
2826 /* Put scroll bars on the right by default, as is conventional
2827 on MS-Windows. */
2828 EQ (Qleft, arg)
2829 ? vertical_scroll_bar_left
2830 : vertical_scroll_bar_right;
2831
2832 /* We set this parameter before creating the window for the
2833 frame, so we can get the geometry right from the start.
2834 However, if the window hasn't been created yet, we shouldn't
2835 call x_set_window_size. */
2836 if (FRAME_W32_WINDOW (f))
2837 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2838 do_pending_window_change (0);
2839 }
2840 }
2841
2842 void
2843 x_set_scroll_bar_width (f, arg, oldval)
2844 struct frame *f;
2845 Lisp_Object arg, oldval;
2846 {
2847 int wid = FONT_WIDTH (f->output_data.w32->font);
2848
2849 if (NILP (arg))
2850 {
2851 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
2852 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) +
2853 wid - 1) / wid;
2854 if (FRAME_W32_WINDOW (f))
2855 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2856 do_pending_window_change (0);
2857 }
2858 else if (INTEGERP (arg) && XINT (arg) > 0
2859 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2860 {
2861 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2862 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2863 + wid-1) / wid;
2864 if (FRAME_W32_WINDOW (f))
2865 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2866 do_pending_window_change (0);
2867 }
2868 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2869 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2870 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2871 }
2872 \f
2873 /* Subroutines of creating an frame. */
2874
2875 /* Make sure that Vx_resource_name is set to a reasonable value.
2876 Fix it up, or set it to `emacs' if it is too hopeless. */
2877
2878 static void
2879 validate_x_resource_name ()
2880 {
2881 int len = 0;
2882 /* Number of valid characters in the resource name. */
2883 int good_count = 0;
2884 /* Number of invalid characters in the resource name. */
2885 int bad_count = 0;
2886 Lisp_Object new;
2887 int i;
2888
2889 if (STRINGP (Vx_resource_name))
2890 {
2891 unsigned char *p = XSTRING (Vx_resource_name)->data;
2892 int i;
2893
2894 len = STRING_BYTES (XSTRING (Vx_resource_name));
2895
2896 /* Only letters, digits, - and _ are valid in resource names.
2897 Count the valid characters and count the invalid ones. */
2898 for (i = 0; i < len; i++)
2899 {
2900 int c = p[i];
2901 if (! ((c >= 'a' && c <= 'z')
2902 || (c >= 'A' && c <= 'Z')
2903 || (c >= '0' && c <= '9')
2904 || c == '-' || c == '_'))
2905 bad_count++;
2906 else
2907 good_count++;
2908 }
2909 }
2910 else
2911 /* Not a string => completely invalid. */
2912 bad_count = 5, good_count = 0;
2913
2914 /* If name is valid already, return. */
2915 if (bad_count == 0)
2916 return;
2917
2918 /* If name is entirely invalid, or nearly so, use `emacs'. */
2919 if (good_count == 0
2920 || (good_count == 1 && bad_count > 0))
2921 {
2922 Vx_resource_name = build_string ("emacs");
2923 return;
2924 }
2925
2926 /* Name is partly valid. Copy it and replace the invalid characters
2927 with underscores. */
2928
2929 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2930
2931 for (i = 0; i < len; i++)
2932 {
2933 int c = XSTRING (new)->data[i];
2934 if (! ((c >= 'a' && c <= 'z')
2935 || (c >= 'A' && c <= 'Z')
2936 || (c >= '0' && c <= '9')
2937 || c == '-' || c == '_'))
2938 XSTRING (new)->data[i] = '_';
2939 }
2940 }
2941
2942
2943 extern char *x_get_string_resource ();
2944
2945 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2946 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2947 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2948 class, where INSTANCE is the name under which Emacs was invoked, or
2949 the name specified by the `-name' or `-rn' command-line arguments.
2950
2951 The optional arguments COMPONENT and SUBCLASS add to the key and the
2952 class, respectively. You must specify both of them or neither.
2953 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2954 and the class is `Emacs.CLASS.SUBCLASS'. */)
2955 (attribute, class, component, subclass)
2956 Lisp_Object attribute, class, component, subclass;
2957 {
2958 register char *value;
2959 char *name_key;
2960 char *class_key;
2961
2962 CHECK_STRING (attribute);
2963 CHECK_STRING (class);
2964
2965 if (!NILP (component))
2966 CHECK_STRING (component);
2967 if (!NILP (subclass))
2968 CHECK_STRING (subclass);
2969 if (NILP (component) != NILP (subclass))
2970 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2971
2972 validate_x_resource_name ();
2973
2974 /* Allocate space for the components, the dots which separate them,
2975 and the final '\0'. Make them big enough for the worst case. */
2976 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2977 + (STRINGP (component)
2978 ? STRING_BYTES (XSTRING (component)) : 0)
2979 + STRING_BYTES (XSTRING (attribute))
2980 + 3);
2981
2982 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2983 + STRING_BYTES (XSTRING (class))
2984 + (STRINGP (subclass)
2985 ? STRING_BYTES (XSTRING (subclass)) : 0)
2986 + 3);
2987
2988 /* Start with emacs.FRAMENAME for the name (the specific one)
2989 and with `Emacs' for the class key (the general one). */
2990 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2991 strcpy (class_key, EMACS_CLASS);
2992
2993 strcat (class_key, ".");
2994 strcat (class_key, XSTRING (class)->data);
2995
2996 if (!NILP (component))
2997 {
2998 strcat (class_key, ".");
2999 strcat (class_key, XSTRING (subclass)->data);
3000
3001 strcat (name_key, ".");
3002 strcat (name_key, XSTRING (component)->data);
3003 }
3004
3005 strcat (name_key, ".");
3006 strcat (name_key, XSTRING (attribute)->data);
3007
3008 value = x_get_string_resource (Qnil,
3009 name_key, class_key);
3010
3011 if (value != (char *) 0)
3012 return build_string (value);
3013 else
3014 return Qnil;
3015 }
3016
3017 /* Used when C code wants a resource value. */
3018
3019 char *
3020 x_get_resource_string (attribute, class)
3021 char *attribute, *class;
3022 {
3023 char *name_key;
3024 char *class_key;
3025 struct frame *sf = SELECTED_FRAME ();
3026
3027 /* Allocate space for the components, the dots which separate them,
3028 and the final '\0'. */
3029 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
3030 + strlen (attribute) + 2);
3031 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3032 + strlen (class) + 2);
3033
3034 sprintf (name_key, "%s.%s",
3035 XSTRING (Vinvocation_name)->data,
3036 attribute);
3037 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3038
3039 return x_get_string_resource (sf, name_key, class_key);
3040 }
3041
3042 /* Types we might convert a resource string into. */
3043 enum resource_types
3044 {
3045 RES_TYPE_NUMBER,
3046 RES_TYPE_FLOAT,
3047 RES_TYPE_BOOLEAN,
3048 RES_TYPE_STRING,
3049 RES_TYPE_SYMBOL
3050 };
3051
3052 /* Return the value of parameter PARAM.
3053
3054 First search ALIST, then Vdefault_frame_alist, then the X defaults
3055 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3056
3057 Convert the resource to the type specified by desired_type.
3058
3059 If no default is specified, return Qunbound. If you call
3060 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
3061 and don't let it get stored in any Lisp-visible variables! */
3062
3063 static Lisp_Object
3064 w32_get_arg (alist, param, attribute, class, type)
3065 Lisp_Object alist, param;
3066 char *attribute;
3067 char *class;
3068 enum resource_types type;
3069 {
3070 register Lisp_Object tem;
3071
3072 tem = Fassq (param, alist);
3073 if (EQ (tem, Qnil))
3074 tem = Fassq (param, Vdefault_frame_alist);
3075 if (EQ (tem, Qnil))
3076 {
3077
3078 if (attribute)
3079 {
3080 tem = Fx_get_resource (build_string (attribute),
3081 build_string (class),
3082 Qnil, Qnil);
3083
3084 if (NILP (tem))
3085 return Qunbound;
3086
3087 switch (type)
3088 {
3089 case RES_TYPE_NUMBER:
3090 return make_number (atoi (XSTRING (tem)->data));
3091
3092 case RES_TYPE_FLOAT:
3093 return make_float (atof (XSTRING (tem)->data));
3094
3095 case RES_TYPE_BOOLEAN:
3096 tem = Fdowncase (tem);
3097 if (!strcmp (XSTRING (tem)->data, "on")
3098 || !strcmp (XSTRING (tem)->data, "true"))
3099 return Qt;
3100 else
3101 return Qnil;
3102
3103 case RES_TYPE_STRING:
3104 return tem;
3105
3106 case RES_TYPE_SYMBOL:
3107 /* As a special case, we map the values `true' and `on'
3108 to Qt, and `false' and `off' to Qnil. */
3109 {
3110 Lisp_Object lower;
3111 lower = Fdowncase (tem);
3112 if (!strcmp (XSTRING (lower)->data, "on")
3113 || !strcmp (XSTRING (lower)->data, "true"))
3114 return Qt;
3115 else if (!strcmp (XSTRING (lower)->data, "off")
3116 || !strcmp (XSTRING (lower)->data, "false"))
3117 return Qnil;
3118 else
3119 return Fintern (tem, Qnil);
3120 }
3121
3122 default:
3123 abort ();
3124 }
3125 }
3126 else
3127 return Qunbound;
3128 }
3129 return Fcdr (tem);
3130 }
3131
3132 /* Record in frame F the specified or default value according to ALIST
3133 of the parameter named PROP (a Lisp symbol).
3134 If no value is specified for PROP, look for an X default for XPROP
3135 on the frame named NAME.
3136 If that is not found either, use the value DEFLT. */
3137
3138 static Lisp_Object
3139 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3140 struct frame *f;
3141 Lisp_Object alist;
3142 Lisp_Object prop;
3143 Lisp_Object deflt;
3144 char *xprop;
3145 char *xclass;
3146 enum resource_types type;
3147 {
3148 Lisp_Object tem;
3149
3150 tem = w32_get_arg (alist, prop, xprop, xclass, type);
3151 if (EQ (tem, Qunbound))
3152 tem = deflt;
3153 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3154 return tem;
3155 }
3156 \f
3157 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3158 doc: /* Parse an X-style geometry string STRING.
3159 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3160 The properties returned may include `top', `left', `height', and `width'.
3161 The value of `left' or `top' may be an integer,
3162 or a list (+ N) meaning N pixels relative to top/left corner,
3163 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3164 (string)
3165 Lisp_Object string;
3166 {
3167 int geometry, x, y;
3168 unsigned int width, height;
3169 Lisp_Object result;
3170
3171 CHECK_STRING (string);
3172
3173 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3174 &x, &y, &width, &height);
3175
3176 result = Qnil;
3177 if (geometry & XValue)
3178 {
3179 Lisp_Object element;
3180
3181 if (x >= 0 && (geometry & XNegative))
3182 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3183 else if (x < 0 && ! (geometry & XNegative))
3184 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3185 else
3186 element = Fcons (Qleft, make_number (x));
3187 result = Fcons (element, result);
3188 }
3189
3190 if (geometry & YValue)
3191 {
3192 Lisp_Object element;
3193
3194 if (y >= 0 && (geometry & YNegative))
3195 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3196 else if (y < 0 && ! (geometry & YNegative))
3197 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3198 else
3199 element = Fcons (Qtop, make_number (y));
3200 result = Fcons (element, result);
3201 }
3202
3203 if (geometry & WidthValue)
3204 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3205 if (geometry & HeightValue)
3206 result = Fcons (Fcons (Qheight, make_number (height)), result);
3207
3208 return result;
3209 }
3210
3211 /* Calculate the desired size and position of this window,
3212 and return the flags saying which aspects were specified.
3213
3214 This function does not make the coordinates positive. */
3215
3216 #define DEFAULT_ROWS 40
3217 #define DEFAULT_COLS 80
3218
3219 static int
3220 x_figure_window_size (f, parms)
3221 struct frame *f;
3222 Lisp_Object parms;
3223 {
3224 register Lisp_Object tem0, tem1, tem2;
3225 long window_prompting = 0;
3226
3227 /* Default values if we fall through.
3228 Actually, if that happens we should get
3229 window manager prompting. */
3230 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3231 f->height = DEFAULT_ROWS;
3232 /* Window managers expect that if program-specified
3233 positions are not (0,0), they're intentional, not defaults. */
3234 f->output_data.w32->top_pos = 0;
3235 f->output_data.w32->left_pos = 0;
3236
3237 /* Ensure that old new_width and new_height will not override the
3238 values set here. */
3239 FRAME_NEW_WIDTH (f) = 0;
3240 FRAME_NEW_HEIGHT (f) = 0;
3241
3242 tem0 = w32_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3243 tem1 = w32_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3244 tem2 = w32_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3245 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3246 {
3247 if (!EQ (tem0, Qunbound))
3248 {
3249 CHECK_NUMBER (tem0);
3250 f->height = XINT (tem0);
3251 }
3252 if (!EQ (tem1, Qunbound))
3253 {
3254 CHECK_NUMBER (tem1);
3255 SET_FRAME_WIDTH (f, XINT (tem1));
3256 }
3257 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3258 window_prompting |= USSize;
3259 else
3260 window_prompting |= PSize;
3261 }
3262
3263 f->output_data.w32->vertical_scroll_bar_extra
3264 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3265 ? 0
3266 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3267 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3268 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
3269 x_compute_fringe_widths (f, 0);
3270 f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3271 f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3272
3273 tem0 = w32_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3274 tem1 = w32_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3275 tem2 = w32_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3276 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3277 {
3278 if (EQ (tem0, Qminus))
3279 {
3280 f->output_data.w32->top_pos = 0;
3281 window_prompting |= YNegative;
3282 }
3283 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3284 && CONSP (XCDR (tem0))
3285 && INTEGERP (XCAR (XCDR (tem0))))
3286 {
3287 f->output_data.w32->top_pos = - XINT (XCAR (XCDR (tem0)));
3288 window_prompting |= YNegative;
3289 }
3290 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3291 && CONSP (XCDR (tem0))
3292 && INTEGERP (XCAR (XCDR (tem0))))
3293 {
3294 f->output_data.w32->top_pos = XINT (XCAR (XCDR (tem0)));
3295 }
3296 else if (EQ (tem0, Qunbound))
3297 f->output_data.w32->top_pos = 0;
3298 else
3299 {
3300 CHECK_NUMBER (tem0);
3301 f->output_data.w32->top_pos = XINT (tem0);
3302 if (f->output_data.w32->top_pos < 0)
3303 window_prompting |= YNegative;
3304 }
3305
3306 if (EQ (tem1, Qminus))
3307 {
3308 f->output_data.w32->left_pos = 0;
3309 window_prompting |= XNegative;
3310 }
3311 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3312 && CONSP (XCDR (tem1))
3313 && INTEGERP (XCAR (XCDR (tem1))))
3314 {
3315 f->output_data.w32->left_pos = - XINT (XCAR (XCDR (tem1)));
3316 window_prompting |= XNegative;
3317 }
3318 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3319 && CONSP (XCDR (tem1))
3320 && INTEGERP (XCAR (XCDR (tem1))))
3321 {
3322 f->output_data.w32->left_pos = XINT (XCAR (XCDR (tem1)));
3323 }
3324 else if (EQ (tem1, Qunbound))
3325 f->output_data.w32->left_pos = 0;
3326 else
3327 {
3328 CHECK_NUMBER (tem1);
3329 f->output_data.w32->left_pos = XINT (tem1);
3330 if (f->output_data.w32->left_pos < 0)
3331 window_prompting |= XNegative;
3332 }
3333
3334 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3335 window_prompting |= USPosition;
3336 else
3337 window_prompting |= PPosition;
3338 }
3339
3340 return window_prompting;
3341 }
3342
3343 \f
3344
3345 extern LRESULT CALLBACK w32_wnd_proc ();
3346
3347 BOOL
3348 w32_init_class (hinst)
3349 HINSTANCE hinst;
3350 {
3351 WNDCLASS wc;
3352
3353 wc.style = CS_HREDRAW | CS_VREDRAW;
3354 wc.lpfnWndProc = (WNDPROC) w32_wnd_proc;
3355 wc.cbClsExtra = 0;
3356 wc.cbWndExtra = WND_EXTRA_BYTES;
3357 wc.hInstance = hinst;
3358 wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
3359 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
3360 wc.hbrBackground = NULL; /* GetStockObject (WHITE_BRUSH); */
3361 wc.lpszMenuName = NULL;
3362 wc.lpszClassName = EMACS_CLASS;
3363
3364 return (RegisterClass (&wc));
3365 }
3366
3367 HWND
3368 w32_createscrollbar (f, bar)
3369 struct frame *f;
3370 struct scroll_bar * bar;
3371 {
3372 return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
3373 /* Position and size of scroll bar. */
3374 XINT(bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3375 XINT(bar->top),
3376 XINT(bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3377 XINT(bar->height),
3378 FRAME_W32_WINDOW (f),
3379 NULL,
3380 hinst,
3381 NULL));
3382 }
3383
3384 void
3385 w32_createwindow (f)
3386 struct frame *f;
3387 {
3388 HWND hwnd;
3389 RECT rect;
3390
3391 rect.left = rect.top = 0;
3392 rect.right = PIXEL_WIDTH (f);
3393 rect.bottom = PIXEL_HEIGHT (f);
3394
3395 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
3396 FRAME_EXTERNAL_MENU_BAR (f));
3397
3398 /* Do first time app init */
3399
3400 if (!hprevinst)
3401 {
3402 w32_init_class (hinst);
3403 }
3404
3405 FRAME_W32_WINDOW (f) = hwnd
3406 = CreateWindow (EMACS_CLASS,
3407 f->namebuf,
3408 f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
3409 f->output_data.w32->left_pos,
3410 f->output_data.w32->top_pos,
3411 rect.right - rect.left,
3412 rect.bottom - rect.top,
3413 NULL,
3414 NULL,
3415 hinst,
3416 NULL);
3417
3418 if (hwnd)
3419 {
3420 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
3421 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
3422 SetWindowLong (hwnd, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
3423 SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
3424 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
3425
3426 /* Enable drag-n-drop. */
3427 DragAcceptFiles (hwnd, TRUE);
3428
3429 /* Do this to discard the default setting specified by our parent. */
3430 ShowWindow (hwnd, SW_HIDE);
3431 }
3432 }
3433
3434 void
3435 my_post_msg (wmsg, hwnd, msg, wParam, lParam)
3436 W32Msg * wmsg;
3437 HWND hwnd;
3438 UINT msg;
3439 WPARAM wParam;
3440 LPARAM lParam;
3441 {
3442 wmsg->msg.hwnd = hwnd;
3443 wmsg->msg.message = msg;
3444 wmsg->msg.wParam = wParam;
3445 wmsg->msg.lParam = lParam;
3446 wmsg->msg.time = GetMessageTime ();
3447
3448 post_msg (wmsg);
3449 }
3450
3451 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
3452 between left and right keys as advertised. We test for this
3453 support dynamically, and set a flag when the support is absent. If
3454 absent, we keep track of the left and right control and alt keys
3455 ourselves. This is particularly necessary on keyboards that rely
3456 upon the AltGr key, which is represented as having the left control
3457 and right alt keys pressed. For these keyboards, we need to know
3458 when the left alt key has been pressed in addition to the AltGr key
3459 so that we can properly support M-AltGr-key sequences (such as M-@
3460 on Swedish keyboards). */
3461
3462 #define EMACS_LCONTROL 0
3463 #define EMACS_RCONTROL 1
3464 #define EMACS_LMENU 2
3465 #define EMACS_RMENU 3
3466
3467 static int modifiers[4];
3468 static int modifiers_recorded;
3469 static int modifier_key_support_tested;
3470
3471 static void
3472 test_modifier_support (unsigned int wparam)
3473 {
3474 unsigned int l, r;
3475
3476 if (wparam != VK_CONTROL && wparam != VK_MENU)
3477 return;
3478 if (wparam == VK_CONTROL)
3479 {
3480 l = VK_LCONTROL;
3481 r = VK_RCONTROL;
3482 }
3483 else
3484 {
3485 l = VK_LMENU;
3486 r = VK_RMENU;
3487 }
3488 if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
3489 modifiers_recorded = 1;
3490 else
3491 modifiers_recorded = 0;
3492 modifier_key_support_tested = 1;
3493 }
3494
3495 static void
3496 record_keydown (unsigned int wparam, unsigned int lparam)
3497 {
3498 int i;
3499
3500 if (!modifier_key_support_tested)
3501 test_modifier_support (wparam);
3502
3503 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
3504 return;
3505
3506 if (wparam == VK_CONTROL)
3507 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
3508 else
3509 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
3510
3511 modifiers[i] = 1;
3512 }
3513
3514 static void
3515 record_keyup (unsigned int wparam, unsigned int lparam)
3516 {
3517 int i;
3518
3519 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
3520 return;
3521
3522 if (wparam == VK_CONTROL)
3523 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
3524 else
3525 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
3526
3527 modifiers[i] = 0;
3528 }
3529
3530 /* Emacs can lose focus while a modifier key has been pressed. When
3531 it regains focus, be conservative and clear all modifiers since
3532 we cannot reconstruct the left and right modifier state. */
3533 static void
3534 reset_modifiers ()
3535 {
3536 SHORT ctrl, alt;
3537
3538 if (GetFocus () == NULL)
3539 /* Emacs doesn't have keyboard focus. Do nothing. */
3540 return;
3541
3542 ctrl = GetAsyncKeyState (VK_CONTROL);
3543 alt = GetAsyncKeyState (VK_MENU);
3544
3545 if (!(ctrl & 0x08000))
3546 /* Clear any recorded control modifier state. */
3547 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3548
3549 if (!(alt & 0x08000))
3550 /* Clear any recorded alt modifier state. */
3551 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3552
3553 /* Update the state of all modifier keys, because modifiers used in
3554 hot-key combinations can get stuck on if Emacs loses focus as a
3555 result of a hot-key being pressed. */
3556 {
3557 BYTE keystate[256];
3558
3559 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
3560
3561 GetKeyboardState (keystate);
3562 keystate[VK_SHIFT] = CURRENT_STATE (VK_SHIFT);
3563 keystate[VK_CONTROL] = CURRENT_STATE (VK_CONTROL);
3564 keystate[VK_LCONTROL] = CURRENT_STATE (VK_LCONTROL);
3565 keystate[VK_RCONTROL] = CURRENT_STATE (VK_RCONTROL);
3566 keystate[VK_MENU] = CURRENT_STATE (VK_MENU);
3567 keystate[VK_LMENU] = CURRENT_STATE (VK_LMENU);
3568 keystate[VK_RMENU] = CURRENT_STATE (VK_RMENU);
3569 keystate[VK_LWIN] = CURRENT_STATE (VK_LWIN);
3570 keystate[VK_RWIN] = CURRENT_STATE (VK_RWIN);
3571 keystate[VK_APPS] = CURRENT_STATE (VK_APPS);
3572 SetKeyboardState (keystate);
3573 }
3574 }
3575
3576 /* Synchronize modifier state with what is reported with the current
3577 keystroke. Even if we cannot distinguish between left and right
3578 modifier keys, we know that, if no modifiers are set, then neither
3579 the left or right modifier should be set. */
3580 static void
3581 sync_modifiers ()
3582 {
3583 if (!modifiers_recorded)
3584 return;
3585
3586 if (!(GetKeyState (VK_CONTROL) & 0x8000))
3587 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3588
3589 if (!(GetKeyState (VK_MENU) & 0x8000))
3590 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3591 }
3592
3593 static int
3594 modifier_set (int vkey)
3595 {
3596 if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
3597 return (GetKeyState (vkey) & 0x1);
3598 if (!modifiers_recorded)
3599 return (GetKeyState (vkey) & 0x8000);
3600
3601 switch (vkey)
3602 {
3603 case VK_LCONTROL:
3604 return modifiers[EMACS_LCONTROL];
3605 case VK_RCONTROL:
3606 return modifiers[EMACS_RCONTROL];
3607 case VK_LMENU:
3608 return modifiers[EMACS_LMENU];
3609 case VK_RMENU:
3610 return modifiers[EMACS_RMENU];
3611 }
3612 return (GetKeyState (vkey) & 0x8000);
3613 }
3614
3615 /* Convert between the modifier bits W32 uses and the modifier bits
3616 Emacs uses. */
3617
3618 unsigned int
3619 w32_key_to_modifier (int key)
3620 {
3621 Lisp_Object key_mapping;
3622
3623 switch (key)
3624 {
3625 case VK_LWIN:
3626 key_mapping = Vw32_lwindow_modifier;
3627 break;
3628 case VK_RWIN:
3629 key_mapping = Vw32_rwindow_modifier;
3630 break;
3631 case VK_APPS:
3632 key_mapping = Vw32_apps_modifier;
3633 break;
3634 case VK_SCROLL:
3635 key_mapping = Vw32_scroll_lock_modifier;
3636 break;
3637 default:
3638 key_mapping = Qnil;
3639 }
3640
3641 /* NB. This code runs in the input thread, asychronously to the lisp
3642 thread, so we must be careful to ensure access to lisp data is
3643 thread-safe. The following code is safe because the modifier
3644 variable values are updated atomically from lisp and symbols are
3645 not relocated by GC. Also, we don't have to worry about seeing GC
3646 markbits here. */
3647 if (EQ (key_mapping, Qhyper))
3648 return hyper_modifier;
3649 if (EQ (key_mapping, Qsuper))
3650 return super_modifier;
3651 if (EQ (key_mapping, Qmeta))
3652 return meta_modifier;
3653 if (EQ (key_mapping, Qalt))
3654 return alt_modifier;
3655 if (EQ (key_mapping, Qctrl))
3656 return ctrl_modifier;
3657 if (EQ (key_mapping, Qcontrol)) /* synonym for ctrl */
3658 return ctrl_modifier;
3659 if (EQ (key_mapping, Qshift))
3660 return shift_modifier;
3661
3662 /* Don't generate any modifier if not explicitly requested. */
3663 return 0;
3664 }
3665
3666 unsigned int
3667 w32_get_modifiers ()
3668 {
3669 return ((modifier_set (VK_SHIFT) ? shift_modifier : 0) |
3670 (modifier_set (VK_CONTROL) ? ctrl_modifier : 0) |
3671 (modifier_set (VK_LWIN) ? w32_key_to_modifier (VK_LWIN) : 0) |
3672 (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) |
3673 (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) |
3674 (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) |
3675 (modifier_set (VK_MENU) ?
3676 ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
3677 }
3678
3679 /* We map the VK_* modifiers into console modifier constants
3680 so that we can use the same routines to handle both console
3681 and window input. */
3682
3683 static int
3684 construct_console_modifiers ()
3685 {
3686 int mods;
3687
3688 mods = 0;
3689 mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
3690 mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
3691 mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0;
3692 mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0;
3693 mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
3694 mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
3695 mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
3696 mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
3697 mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0;
3698 mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0;
3699 mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0;
3700
3701 return mods;
3702 }
3703
3704 static int
3705 w32_get_key_modifiers (unsigned int wparam, unsigned int lparam)
3706 {
3707 int mods;
3708
3709 /* Convert to emacs modifiers. */
3710 mods = w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam);
3711
3712 return mods;
3713 }
3714
3715 unsigned int
3716 map_keypad_keys (unsigned int virt_key, unsigned int extended)
3717 {
3718 if (virt_key < VK_CLEAR || virt_key > VK_DELETE)
3719 return virt_key;
3720
3721 if (virt_key == VK_RETURN)
3722 return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
3723
3724 if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN)
3725 return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key);
3726
3727 if (virt_key == VK_INSERT || virt_key == VK_DELETE)
3728 return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key);
3729
3730 if (virt_key == VK_CLEAR)
3731 return (!extended ? VK_NUMPAD_CLEAR : virt_key);
3732
3733 return virt_key;
3734 }
3735
3736 /* List of special key combinations which w32 would normally capture,
3737 but emacs should grab instead. Not directly visible to lisp, to
3738 simplify synchronization. Each item is an integer encoding a virtual
3739 key code and modifier combination to capture. */
3740 Lisp_Object w32_grabbed_keys;
3741
3742 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
3743 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
3744 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
3745 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
3746
3747 /* Register hot-keys for reserved key combinations when Emacs has
3748 keyboard focus, since this is the only way Emacs can receive key
3749 combinations like Alt-Tab which are used by the system. */
3750
3751 static void
3752 register_hot_keys (hwnd)
3753 HWND hwnd;
3754 {
3755 Lisp_Object keylist;
3756
3757 /* Use GC_CONSP, since we are called asynchronously. */
3758 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3759 {
3760 Lisp_Object key = XCAR (keylist);
3761
3762 /* Deleted entries get set to nil. */
3763 if (!INTEGERP (key))
3764 continue;
3765
3766 RegisterHotKey (hwnd, HOTKEY_ID (key),
3767 HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
3768 }
3769 }
3770
3771 static void
3772 unregister_hot_keys (hwnd)
3773 HWND hwnd;
3774 {
3775 Lisp_Object keylist;
3776
3777 /* Use GC_CONSP, since we are called asynchronously. */
3778 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3779 {
3780 Lisp_Object key = XCAR (keylist);
3781
3782 if (!INTEGERP (key))
3783 continue;
3784
3785 UnregisterHotKey (hwnd, HOTKEY_ID (key));
3786 }
3787 }
3788
3789 /* Main message dispatch loop. */
3790
3791 static void
3792 w32_msg_pump (deferred_msg * msg_buf)
3793 {
3794 MSG msg;
3795 int result;
3796 HWND focus_window;
3797
3798 msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
3799
3800 while (GetMessage (&msg, NULL, 0, 0))
3801 {
3802 if (msg.hwnd == NULL)
3803 {
3804 switch (msg.message)
3805 {
3806 case WM_NULL:
3807 /* Produced by complete_deferred_msg; just ignore. */
3808 break;
3809 case WM_EMACS_CREATEWINDOW:
3810 w32_createwindow ((struct frame *) msg.wParam);
3811 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3812 abort ();
3813 break;
3814 case WM_EMACS_SETLOCALE:
3815 SetThreadLocale (msg.wParam);
3816 /* Reply is not expected. */
3817 break;
3818 case WM_EMACS_SETKEYBOARDLAYOUT:
3819 result = (int) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
3820 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
3821 result, 0))
3822 abort ();
3823 break;
3824 case WM_EMACS_REGISTER_HOT_KEY:
3825 focus_window = GetFocus ();
3826 if (focus_window != NULL)
3827 RegisterHotKey (focus_window,
3828 HOTKEY_ID (msg.wParam),
3829 HOTKEY_MODIFIERS (msg.wParam),
3830 HOTKEY_VK_CODE (msg.wParam));
3831 /* Reply is not expected. */
3832 break;
3833 case WM_EMACS_UNREGISTER_HOT_KEY:
3834 focus_window = GetFocus ();
3835 if (focus_window != NULL)
3836 UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam));
3837 /* Mark item as erased. NB: this code must be
3838 thread-safe. The next line is okay because the cons
3839 cell is never made into garbage and is not relocated by
3840 GC. */
3841 XSETCAR ((Lisp_Object) msg.lParam, Qnil);
3842 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3843 abort ();
3844 break;
3845 case WM_EMACS_TOGGLE_LOCK_KEY:
3846 {
3847 int vk_code = (int) msg.wParam;
3848 int cur_state = (GetKeyState (vk_code) & 1);
3849 Lisp_Object new_state = (Lisp_Object) msg.lParam;
3850
3851 /* NB: This code must be thread-safe. It is safe to
3852 call NILP because symbols are not relocated by GC,
3853 and pointer here is not touched by GC (so the markbit
3854 can't be set). Numbers are safe because they are
3855 immediate values. */
3856 if (NILP (new_state)
3857 || (NUMBERP (new_state)
3858 && ((XUINT (new_state)) & 1) != cur_state))
3859 {
3860 one_w32_display_info.faked_key = vk_code;
3861
3862 keybd_event ((BYTE) vk_code,
3863 (BYTE) MapVirtualKey (vk_code, 0),
3864 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3865 keybd_event ((BYTE) vk_code,
3866 (BYTE) MapVirtualKey (vk_code, 0),
3867 KEYEVENTF_EXTENDEDKEY | 0, 0);
3868 keybd_event ((BYTE) vk_code,
3869 (BYTE) MapVirtualKey (vk_code, 0),
3870 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3871 cur_state = !cur_state;
3872 }
3873 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
3874 cur_state, 0))
3875 abort ();
3876 }
3877 break;
3878 default:
3879 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
3880 }
3881 }
3882 else
3883 {
3884 DispatchMessage (&msg);
3885 }
3886
3887 /* Exit nested loop when our deferred message has completed. */
3888 if (msg_buf->completed)
3889 break;
3890 }
3891 }
3892
3893 deferred_msg * deferred_msg_head;
3894
3895 static deferred_msg *
3896 find_deferred_msg (HWND hwnd, UINT msg)
3897 {
3898 deferred_msg * item;
3899
3900 /* Don't actually need synchronization for read access, since
3901 modification of single pointer is always atomic. */
3902 /* enter_crit (); */
3903
3904 for (item = deferred_msg_head; item != NULL; item = item->next)
3905 if (item->w32msg.msg.hwnd == hwnd
3906 && item->w32msg.msg.message == msg)
3907 break;
3908
3909 /* leave_crit (); */
3910
3911 return item;
3912 }
3913
3914 static LRESULT
3915 send_deferred_msg (deferred_msg * msg_buf,
3916 HWND hwnd,
3917 UINT msg,
3918 WPARAM wParam,
3919 LPARAM lParam)
3920 {
3921 /* Only input thread can send deferred messages. */
3922 if (GetCurrentThreadId () != dwWindowsThreadId)
3923 abort ();
3924
3925 /* It is an error to send a message that is already deferred. */
3926 if (find_deferred_msg (hwnd, msg) != NULL)
3927 abort ();
3928
3929 /* Enforced synchronization is not needed because this is the only
3930 function that alters deferred_msg_head, and the following critical
3931 section is guaranteed to only be serially reentered (since only the
3932 input thread can call us). */
3933
3934 /* enter_crit (); */
3935
3936 msg_buf->completed = 0;
3937 msg_buf->next = deferred_msg_head;
3938 deferred_msg_head = msg_buf;
3939 my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam);
3940
3941 /* leave_crit (); */
3942
3943 /* Start a new nested message loop to process other messages until
3944 this one is completed. */
3945 w32_msg_pump (msg_buf);
3946
3947 deferred_msg_head = msg_buf->next;
3948
3949 return msg_buf->result;
3950 }
3951
3952 void
3953 complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
3954 {
3955 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
3956
3957 if (msg_buf == NULL)
3958 /* Message may have been cancelled, so don't abort(). */
3959 return;
3960
3961 msg_buf->result = result;
3962 msg_buf->completed = 1;
3963
3964 /* Ensure input thread is woken so it notices the completion. */
3965 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
3966 }
3967
3968 void
3969 cancel_all_deferred_msgs ()
3970 {
3971 deferred_msg * item;
3972
3973 /* Don't actually need synchronization for read access, since
3974 modification of single pointer is always atomic. */
3975 /* enter_crit (); */
3976
3977 for (item = deferred_msg_head; item != NULL; item = item->next)
3978 {
3979 item->result = 0;
3980 item->completed = 1;
3981 }
3982
3983 /* leave_crit (); */
3984
3985 /* Ensure input thread is woken so it notices the completion. */
3986 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
3987 }
3988
3989 DWORD
3990 w32_msg_worker (dw)
3991 DWORD dw;
3992 {
3993 MSG msg;
3994 deferred_msg dummy_buf;
3995
3996 /* Ensure our message queue is created */
3997
3998 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
3999
4000 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
4001 abort ();
4002
4003 memset (&dummy_buf, 0, sizeof (dummy_buf));
4004 dummy_buf.w32msg.msg.hwnd = NULL;
4005 dummy_buf.w32msg.msg.message = WM_NULL;
4006
4007 /* This is the inital message loop which should only exit when the
4008 application quits. */
4009 w32_msg_pump (&dummy_buf);
4010
4011 return 0;
4012 }
4013
4014 static void
4015 post_character_message (hwnd, msg, wParam, lParam, modifiers)
4016 HWND hwnd;
4017 UINT msg;
4018 WPARAM wParam;
4019 LPARAM lParam;
4020 DWORD modifiers;
4021
4022 {
4023 W32Msg wmsg;
4024
4025 wmsg.dwModifiers = modifiers;
4026
4027 /* Detect quit_char and set quit-flag directly. Note that we
4028 still need to post a message to ensure the main thread will be
4029 woken up if blocked in sys_select(), but we do NOT want to post
4030 the quit_char message itself (because it will usually be as if
4031 the user had typed quit_char twice). Instead, we post a dummy
4032 message that has no particular effect. */
4033 {
4034 int c = wParam;
4035 if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
4036 c = make_ctrl_char (c) & 0377;
4037 if (c == quit_char
4038 || (wmsg.dwModifiers == 0 &&
4039 XFASTINT (Vw32_quit_key) && wParam == XFASTINT (Vw32_quit_key)))
4040 {
4041 Vquit_flag = Qt;
4042
4043 /* The choice of message is somewhat arbitrary, as long as
4044 the main thread handler just ignores it. */
4045 msg = WM_NULL;
4046
4047 /* Interrupt any blocking system calls. */
4048 signal_quit ();
4049
4050 /* As a safety precaution, forcibly complete any deferred
4051 messages. This is a kludge, but I don't see any particularly
4052 clean way to handle the situation where a deferred message is
4053 "dropped" in the lisp thread, and will thus never be
4054 completed, eg. by the user trying to activate the menubar
4055 when the lisp thread is busy, and then typing C-g when the
4056 menubar doesn't open promptly (with the result that the
4057 menubar never responds at all because the deferred
4058 WM_INITMENU message is never completed). Another problem
4059 situation is when the lisp thread calls SendMessage (to send
4060 a window manager command) when a message has been deferred;
4061 the lisp thread gets blocked indefinitely waiting for the
4062 deferred message to be completed, which itself is waiting for
4063 the lisp thread to respond.
4064
4065 Note that we don't want to block the input thread waiting for
4066 a reponse from the lisp thread (although that would at least
4067 solve the deadlock problem above), because we want to be able
4068 to receive C-g to interrupt the lisp thread. */
4069 cancel_all_deferred_msgs ();
4070 }
4071 }
4072
4073 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4074 }
4075
4076 /* Main window procedure */
4077
4078 LRESULT CALLBACK
4079 w32_wnd_proc (hwnd, msg, wParam, lParam)
4080 HWND hwnd;
4081 UINT msg;
4082 WPARAM wParam;
4083 LPARAM lParam;
4084 {
4085 struct frame *f;
4086 struct w32_display_info *dpyinfo = &one_w32_display_info;
4087 W32Msg wmsg;
4088 int windows_translate;
4089 int key;
4090
4091 /* Note that it is okay to call x_window_to_frame, even though we are
4092 not running in the main lisp thread, because frame deletion
4093 requires the lisp thread to synchronize with this thread. Thus, if
4094 a frame struct is returned, it can be used without concern that the
4095 lisp thread might make it disappear while we are using it.
4096
4097 NB. Walking the frame list in this thread is safe (as long as
4098 writes of Lisp_Object slots are atomic, which they are on Windows).
4099 Although delete-frame can destructively modify the frame list while
4100 we are walking it, a garbage collection cannot occur until after
4101 delete-frame has synchronized with this thread.
4102
4103 It is also safe to use functions that make GDI calls, such as
4104 w32_clear_rect, because these functions must obtain a DC handle
4105 from the frame struct using get_frame_dc which is thread-aware. */
4106
4107 switch (msg)
4108 {
4109 case WM_ERASEBKGND:
4110 f = x_window_to_frame (dpyinfo, hwnd);
4111 if (f)
4112 {
4113 HDC hdc = get_frame_dc (f);
4114 GetUpdateRect (hwnd, &wmsg.rect, FALSE);
4115 w32_clear_rect (f, hdc, &wmsg.rect);
4116 release_frame_dc (f, hdc);
4117
4118 #if defined (W32_DEBUG_DISPLAY)
4119 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
4120 f,
4121 wmsg.rect.left, wmsg.rect.top,
4122 wmsg.rect.right, wmsg.rect.bottom));
4123 #endif /* W32_DEBUG_DISPLAY */
4124 }
4125 return 1;
4126 case WM_PALETTECHANGED:
4127 /* ignore our own changes */
4128 if ((HWND)wParam != hwnd)
4129 {
4130 f = x_window_to_frame (dpyinfo, hwnd);
4131 if (f)
4132 /* get_frame_dc will realize our palette and force all
4133 frames to be redrawn if needed. */
4134 release_frame_dc (f, get_frame_dc (f));
4135 }
4136 return 0;
4137 case WM_PAINT:
4138 {
4139 PAINTSTRUCT paintStruct;
4140 RECT update_rect;
4141
4142 f = x_window_to_frame (dpyinfo, hwnd);
4143 if (f == 0)
4144 {
4145 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd));
4146 return 0;
4147 }
4148
4149 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
4150 fails. Apparently this can happen under some
4151 circumstances. */
4152 if (!w32_strict_painting || GetUpdateRect (hwnd, &update_rect, FALSE))
4153 {
4154 enter_crit ();
4155 BeginPaint (hwnd, &paintStruct);
4156
4157 if (w32_strict_painting)
4158 /* The rectangles returned by GetUpdateRect and BeginPaint
4159 do not always match. GetUpdateRect seems to be the
4160 more reliable of the two. */
4161 wmsg.rect = update_rect;
4162 else
4163 wmsg.rect = paintStruct.rcPaint;
4164
4165 #if defined (W32_DEBUG_DISPLAY)
4166 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
4167 f,
4168 wmsg.rect.left, wmsg.rect.top,
4169 wmsg.rect.right, wmsg.rect.bottom));
4170 DebPrint ((" [update region is %d,%d-%d,%d]\n",
4171 update_rect.left, update_rect.top,
4172 update_rect.right, update_rect.bottom));
4173 #endif
4174 EndPaint (hwnd, &paintStruct);
4175 leave_crit ();
4176
4177 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4178
4179 return 0;
4180 }
4181
4182 /* If GetUpdateRect returns 0 (meaning there is no update
4183 region), assume the whole window needs to be repainted. */
4184 GetClientRect(hwnd, &wmsg.rect);
4185 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4186 return 0;
4187 }
4188
4189 case WM_INPUTLANGCHANGE:
4190 /* Inform lisp thread of keyboard layout changes. */
4191 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4192
4193 /* Clear dead keys in the keyboard state; for simplicity only
4194 preserve modifier key states. */
4195 {
4196 int i;
4197 BYTE keystate[256];
4198
4199 GetKeyboardState (keystate);
4200 for (i = 0; i < 256; i++)
4201 if (1
4202 && i != VK_SHIFT
4203 && i != VK_LSHIFT
4204 && i != VK_RSHIFT
4205 && i != VK_CAPITAL
4206 && i != VK_NUMLOCK
4207 && i != VK_SCROLL
4208 && i != VK_CONTROL
4209 && i != VK_LCONTROL
4210 && i != VK_RCONTROL
4211 && i != VK_MENU
4212 && i != VK_LMENU
4213 && i != VK_RMENU
4214 && i != VK_LWIN
4215 && i != VK_RWIN)
4216 keystate[i] = 0;
4217 SetKeyboardState (keystate);
4218 }
4219 goto dflt;
4220
4221 case WM_HOTKEY:
4222 /* Synchronize hot keys with normal input. */
4223 PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
4224 return (0);
4225
4226 case WM_KEYUP:
4227 case WM_SYSKEYUP:
4228 record_keyup (wParam, lParam);
4229 goto dflt;
4230
4231 case WM_KEYDOWN:
4232 case WM_SYSKEYDOWN:
4233 /* Ignore keystrokes we fake ourself; see below. */
4234 if (dpyinfo->faked_key == wParam)
4235 {
4236 dpyinfo->faked_key = 0;
4237 /* Make sure TranslateMessage sees them though (as long as
4238 they don't produce WM_CHAR messages). This ensures that
4239 indicator lights are toggled promptly on Windows 9x, for
4240 example. */
4241 if (lispy_function_keys[wParam] != 0)
4242 {
4243 windows_translate = 1;
4244 goto translate;
4245 }
4246 return 0;
4247 }
4248
4249 /* Synchronize modifiers with current keystroke. */
4250 sync_modifiers ();
4251 record_keydown (wParam, lParam);
4252 wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
4253
4254 windows_translate = 0;
4255
4256 switch (wParam)
4257 {
4258 case VK_LWIN:
4259 if (NILP (Vw32_pass_lwindow_to_system))
4260 {
4261 /* Prevent system from acting on keyup (which opens the
4262 Start menu if no other key was pressed) by simulating a
4263 press of Space which we will ignore. */
4264 if (GetAsyncKeyState (wParam) & 1)
4265 {
4266 if (NUMBERP (Vw32_phantom_key_code))
4267 key = XUINT (Vw32_phantom_key_code) & 255;
4268 else
4269 key = VK_SPACE;
4270 dpyinfo->faked_key = key;
4271 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
4272 }
4273 }
4274 if (!NILP (Vw32_lwindow_modifier))
4275 return 0;
4276 break;
4277 case VK_RWIN:
4278 if (NILP (Vw32_pass_rwindow_to_system))
4279 {
4280 if (GetAsyncKeyState (wParam) & 1)
4281 {
4282 if (NUMBERP (Vw32_phantom_key_code))
4283 key = XUINT (Vw32_phantom_key_code) & 255;
4284 else
4285 key = VK_SPACE;
4286 dpyinfo->faked_key = key;
4287 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
4288 }
4289 }
4290 if (!NILP (Vw32_rwindow_modifier))
4291 return 0;
4292 break;
4293 case VK_APPS:
4294 if (!NILP (Vw32_apps_modifier))
4295 return 0;
4296 break;
4297 case VK_MENU:
4298 if (NILP (Vw32_pass_alt_to_system))
4299 /* Prevent DefWindowProc from activating the menu bar if an
4300 Alt key is pressed and released by itself. */
4301 return 0;
4302 windows_translate = 1;
4303 break;
4304 case VK_CAPITAL:
4305 /* Decide whether to treat as modifier or function key. */
4306 if (NILP (Vw32_enable_caps_lock))
4307 goto disable_lock_key;
4308 windows_translate = 1;
4309 break;
4310 case VK_NUMLOCK:
4311 /* Decide whether to treat as modifier or function key. */
4312 if (NILP (Vw32_enable_num_lock))
4313 goto disable_lock_key;
4314 windows_translate = 1;
4315 break;
4316 case VK_SCROLL:
4317 /* Decide whether to treat as modifier or function key. */
4318 if (NILP (Vw32_scroll_lock_modifier))
4319 goto disable_lock_key;
4320 windows_translate = 1;
4321 break;
4322 disable_lock_key:
4323 /* Ensure the appropriate lock key state (and indicator light)
4324 remains in the same state. We do this by faking another
4325 press of the relevant key. Apparently, this really is the
4326 only way to toggle the state of the indicator lights. */
4327 dpyinfo->faked_key = wParam;
4328 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4329 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
4330 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4331 KEYEVENTF_EXTENDEDKEY | 0, 0);
4332 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4333 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
4334 /* Ensure indicator lights are updated promptly on Windows 9x
4335 (TranslateMessage apparently does this), after forwarding
4336 input event. */
4337 post_character_message (hwnd, msg, wParam, lParam,
4338 w32_get_key_modifiers (wParam, lParam));
4339 windows_translate = 1;
4340 break;
4341 case VK_CONTROL:
4342 case VK_SHIFT:
4343 case VK_PROCESSKEY: /* Generated by IME. */
4344 windows_translate = 1;
4345 break;
4346 case VK_CANCEL:
4347 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
4348 which is confusing for purposes of key binding; convert
4349 VK_CANCEL events into VK_PAUSE events. */
4350 wParam = VK_PAUSE;
4351 break;
4352 case VK_PAUSE:
4353 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
4354 for purposes of key binding; convert these back into
4355 VK_NUMLOCK events, at least when we want to see NumLock key
4356 presses. (Note that there is never any possibility that
4357 VK_PAUSE with Ctrl really is C-Pause as per above.) */
4358 if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL))
4359 wParam = VK_NUMLOCK;
4360 break;
4361 default:
4362 /* If not defined as a function key, change it to a WM_CHAR message. */
4363 if (lispy_function_keys[wParam] == 0)
4364 {
4365 DWORD modifiers = construct_console_modifiers ();
4366
4367 if (!NILP (Vw32_recognize_altgr)
4368 && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))
4369 {
4370 /* Always let TranslateMessage handle AltGr key chords;
4371 for some reason, ToAscii doesn't always process AltGr
4372 chords correctly. */
4373 windows_translate = 1;
4374 }
4375 else if ((modifiers & (~SHIFT_PRESSED & ~CAPSLOCK_ON)) != 0)
4376 {
4377 /* Handle key chords including any modifiers other
4378 than shift directly, in order to preserve as much
4379 modifier information as possible. */
4380 if ('A' <= wParam && wParam <= 'Z')
4381 {
4382 /* Don't translate modified alphabetic keystrokes,
4383 so the user doesn't need to constantly switch
4384 layout to type control or meta keystrokes when
4385 the normal layout translates alphabetic
4386 characters to non-ascii characters. */
4387 if (!modifier_set (VK_SHIFT))
4388 wParam += ('a' - 'A');
4389 msg = WM_CHAR;
4390 }
4391 else
4392 {
4393 /* Try to handle other keystrokes by determining the
4394 base character (ie. translating the base key plus
4395 shift modifier). */
4396 int add;
4397 int isdead = 0;
4398 KEY_EVENT_RECORD key;
4399
4400 key.bKeyDown = TRUE;
4401 key.wRepeatCount = 1;
4402 key.wVirtualKeyCode = wParam;
4403 key.wVirtualScanCode = (lParam & 0xFF0000) >> 16;
4404 key.uChar.AsciiChar = 0;
4405 key.dwControlKeyState = modifiers;
4406
4407 add = w32_kbd_patch_key (&key);
4408 /* 0 means an unrecognised keycode, negative means
4409 dead key. Ignore both. */
4410 while (--add >= 0)
4411 {
4412 /* Forward asciified character sequence. */
4413 post_character_message
4414 (hwnd, WM_CHAR, key.uChar.AsciiChar, lParam,
4415 w32_get_key_modifiers (wParam, lParam));
4416 w32_kbd_patch_key (&key);
4417 }
4418 return 0;
4419 }
4420 }
4421 else
4422 {
4423 /* Let TranslateMessage handle everything else. */
4424 windows_translate = 1;
4425 }
4426 }
4427 }
4428
4429 translate:
4430 if (windows_translate)
4431 {
4432 MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
4433
4434 windows_msg.time = GetMessageTime ();
4435 TranslateMessage (&windows_msg);
4436 goto dflt;
4437 }
4438
4439 /* Fall through */
4440
4441 case WM_SYSCHAR:
4442 case WM_CHAR:
4443 post_character_message (hwnd, msg, wParam, lParam,
4444 w32_get_key_modifiers (wParam, lParam));
4445 break;
4446
4447 /* Simulate middle mouse button events when left and right buttons
4448 are used together, but only if user has two button mouse. */
4449 case WM_LBUTTONDOWN:
4450 case WM_RBUTTONDOWN:
4451 if (XINT (Vw32_num_mouse_buttons) > 2)
4452 goto handle_plain_button;
4453
4454 {
4455 int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
4456 int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
4457
4458 if (button_state & this)
4459 return 0;
4460
4461 if (button_state == 0)
4462 SetCapture (hwnd);
4463
4464 button_state |= this;
4465
4466 if (button_state & other)
4467 {
4468 if (mouse_button_timer)
4469 {
4470 KillTimer (hwnd, mouse_button_timer);
4471 mouse_button_timer = 0;
4472
4473 /* Generate middle mouse event instead. */
4474 msg = WM_MBUTTONDOWN;
4475 button_state |= MMOUSE;
4476 }
4477 else if (button_state & MMOUSE)
4478 {
4479 /* Ignore button event if we've already generated a
4480 middle mouse down event. This happens if the
4481 user releases and press one of the two buttons
4482 after we've faked a middle mouse event. */
4483 return 0;
4484 }
4485 else
4486 {
4487 /* Flush out saved message. */
4488 post_msg (&saved_mouse_button_msg);
4489 }
4490 wmsg.dwModifiers = w32_get_modifiers ();
4491 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4492
4493 /* Clear message buffer. */
4494 saved_mouse_button_msg.msg.hwnd = 0;
4495 }
4496 else
4497 {
4498 /* Hold onto message for now. */
4499 mouse_button_timer =
4500 SetTimer (hwnd, MOUSE_BUTTON_ID,
4501 XINT (Vw32_mouse_button_tolerance), NULL);
4502 saved_mouse_button_msg.msg.hwnd = hwnd;
4503 saved_mouse_button_msg.msg.message = msg;
4504 saved_mouse_button_msg.msg.wParam = wParam;
4505 saved_mouse_button_msg.msg.lParam = lParam;
4506 saved_mouse_button_msg.msg.time = GetMessageTime ();
4507 saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
4508 }
4509 }
4510 return 0;
4511
4512 case WM_LBUTTONUP:
4513 case WM_RBUTTONUP:
4514 if (XINT (Vw32_num_mouse_buttons) > 2)
4515 goto handle_plain_button;
4516
4517 {
4518 int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
4519 int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
4520
4521 if ((button_state & this) == 0)
4522 return 0;
4523
4524 button_state &= ~this;
4525
4526 if (button_state & MMOUSE)
4527 {
4528 /* Only generate event when second button is released. */
4529 if ((button_state & other) == 0)
4530 {
4531 msg = WM_MBUTTONUP;
4532 button_state &= ~MMOUSE;
4533
4534 if (button_state) abort ();
4535 }
4536 else
4537 return 0;
4538 }
4539 else
4540 {
4541 /* Flush out saved message if necessary. */
4542 if (saved_mouse_button_msg.msg.hwnd)
4543 {
4544 post_msg (&saved_mouse_button_msg);
4545 }
4546 }
4547 wmsg.dwModifiers = w32_get_modifiers ();
4548 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4549
4550 /* Always clear message buffer and cancel timer. */
4551 saved_mouse_button_msg.msg.hwnd = 0;
4552 KillTimer (hwnd, mouse_button_timer);
4553 mouse_button_timer = 0;
4554
4555 if (button_state == 0)
4556 ReleaseCapture ();
4557 }
4558 return 0;
4559
4560 case WM_MBUTTONDOWN:
4561 case WM_MBUTTONUP:
4562 handle_plain_button:
4563 {
4564 BOOL up;
4565 int button;
4566
4567 if (parse_button (msg, &button, &up))
4568 {
4569 if (up) ReleaseCapture ();
4570 else SetCapture (hwnd);
4571 button = (button == 0) ? LMOUSE :
4572 ((button == 1) ? MMOUSE : RMOUSE);
4573 if (up)
4574 button_state &= ~button;
4575 else
4576 button_state |= button;
4577 }
4578 }
4579
4580 wmsg.dwModifiers = w32_get_modifiers ();
4581 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4582 return 0;
4583
4584 case WM_VSCROLL:
4585 case WM_MOUSEMOVE:
4586 if (XINT (Vw32_mouse_move_interval) <= 0
4587 || (msg == WM_MOUSEMOVE && button_state == 0))
4588 {
4589 wmsg.dwModifiers = w32_get_modifiers ();
4590 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4591 return 0;
4592 }
4593
4594 /* Hang onto mouse move and scroll messages for a bit, to avoid
4595 sending such events to Emacs faster than it can process them.
4596 If we get more events before the timer from the first message
4597 expires, we just replace the first message. */
4598
4599 if (saved_mouse_move_msg.msg.hwnd == 0)
4600 mouse_move_timer =
4601 SetTimer (hwnd, MOUSE_MOVE_ID,
4602 XINT (Vw32_mouse_move_interval), NULL);
4603
4604 /* Hold onto message for now. */
4605 saved_mouse_move_msg.msg.hwnd = hwnd;
4606 saved_mouse_move_msg.msg.message = msg;
4607 saved_mouse_move_msg.msg.wParam = wParam;
4608 saved_mouse_move_msg.msg.lParam = lParam;
4609 saved_mouse_move_msg.msg.time = GetMessageTime ();
4610 saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
4611
4612 return 0;
4613
4614 case WM_MOUSEWHEEL:
4615 wmsg.dwModifiers = w32_get_modifiers ();
4616 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4617 return 0;
4618
4619 case WM_DROPFILES:
4620 wmsg.dwModifiers = w32_get_modifiers ();
4621 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4622 return 0;
4623
4624 case WM_TIMER:
4625 /* Flush out saved messages if necessary. */
4626 if (wParam == mouse_button_timer)
4627 {
4628 if (saved_mouse_button_msg.msg.hwnd)
4629 {
4630 post_msg (&saved_mouse_button_msg);
4631 saved_mouse_button_msg.msg.hwnd = 0;
4632 }
4633 KillTimer (hwnd, mouse_button_timer);
4634 mouse_button_timer = 0;
4635 }
4636 else if (wParam == mouse_move_timer)
4637 {
4638 if (saved_mouse_move_msg.msg.hwnd)
4639 {
4640 post_msg (&saved_mouse_move_msg);
4641 saved_mouse_move_msg.msg.hwnd = 0;
4642 }
4643 KillTimer (hwnd, mouse_move_timer);
4644 mouse_move_timer = 0;
4645 }
4646 return 0;
4647
4648 case WM_NCACTIVATE:
4649 /* Windows doesn't send us focus messages when putting up and
4650 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
4651 The only indication we get that something happened is receiving
4652 this message afterwards. So this is a good time to reset our
4653 keyboard modifiers' state. */
4654 reset_modifiers ();
4655 goto dflt;
4656
4657 case WM_INITMENU:
4658 button_state = 0;
4659 ReleaseCapture ();
4660 /* We must ensure menu bar is fully constructed and up to date
4661 before allowing user interaction with it. To achieve this
4662 we send this message to the lisp thread and wait for a
4663 reply (whose value is not actually needed) to indicate that
4664 the menu bar is now ready for use, so we can now return.
4665
4666 To remain responsive in the meantime, we enter a nested message
4667 loop that can process all other messages.
4668
4669 However, we skip all this if the message results from calling
4670 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
4671 thread a message because it is blocked on us at this point. We
4672 set menubar_active before calling TrackPopupMenu to indicate
4673 this (there is no possibility of confusion with real menubar
4674 being active). */
4675
4676 f = x_window_to_frame (dpyinfo, hwnd);
4677 if (f
4678 && (f->output_data.w32->menubar_active
4679 /* We can receive this message even in the absence of a
4680 menubar (ie. when the system menu is activated) - in this
4681 case we do NOT want to forward the message, otherwise it
4682 will cause the menubar to suddenly appear when the user
4683 had requested it to be turned off! */
4684 || f->output_data.w32->menubar_widget == NULL))
4685 return 0;
4686
4687 {
4688 deferred_msg msg_buf;
4689
4690 /* Detect if message has already been deferred; in this case
4691 we cannot return any sensible value to ignore this. */
4692 if (find_deferred_msg (hwnd, msg) != NULL)
4693 abort ();
4694
4695 return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
4696 }
4697
4698 case WM_EXITMENULOOP:
4699 f = x_window_to_frame (dpyinfo, hwnd);
4700
4701 /* Indicate that menubar can be modified again. */
4702 if (f)
4703 f->output_data.w32->menubar_active = 0;
4704 goto dflt;
4705
4706 case WM_MENUSELECT:
4707 /* Direct handling of help_echo in menus. Should be safe now
4708 that we generate the help_echo by placing a help event in the
4709 keyboard buffer. */
4710 {
4711 HMENU menu = (HMENU) lParam;
4712 UINT menu_item = (UINT) LOWORD (wParam);
4713 UINT flags = (UINT) HIWORD (wParam);
4714
4715 w32_menu_display_help (hwnd, menu, menu_item, flags);
4716 }
4717 return 0;
4718
4719 case WM_MEASUREITEM:
4720 f = x_window_to_frame (dpyinfo, hwnd);
4721 if (f)
4722 {
4723 MEASUREITEMSTRUCT * pMis = (MEASUREITEMSTRUCT *) lParam;
4724
4725 if (pMis->CtlType == ODT_MENU)
4726 {
4727 /* Work out dimensions for popup menu titles. */
4728 char * title = (char *) pMis->itemData;
4729 HDC hdc = GetDC (hwnd);
4730 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
4731 LOGFONT menu_logfont;
4732 HFONT old_font;
4733 SIZE size;
4734
4735 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
4736 menu_logfont.lfWeight = FW_BOLD;
4737 menu_font = CreateFontIndirect (&menu_logfont);
4738 old_font = SelectObject (hdc, menu_font);
4739
4740 pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE);
4741 if (title)
4742 {
4743 GetTextExtentPoint32 (hdc, title, strlen (title), &size);
4744 pMis->itemWidth = size.cx;
4745 if (pMis->itemHeight < size.cy)
4746 pMis->itemHeight = size.cy;
4747 }
4748 else
4749 pMis->itemWidth = 0;
4750
4751 SelectObject (hdc, old_font);
4752 DeleteObject (menu_font);
4753 ReleaseDC (hwnd, hdc);
4754 return TRUE;
4755 }
4756 }
4757 return 0;
4758
4759 case WM_DRAWITEM:
4760 f = x_window_to_frame (dpyinfo, hwnd);
4761 if (f)
4762 {
4763 DRAWITEMSTRUCT * pDis = (DRAWITEMSTRUCT *) lParam;
4764
4765 if (pDis->CtlType == ODT_MENU)
4766 {
4767 /* Draw popup menu title. */
4768 char * title = (char *) pDis->itemData;
4769 if (title)
4770 {
4771 HDC hdc = pDis->hDC;
4772 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
4773 LOGFONT menu_logfont;
4774 HFONT old_font;
4775
4776 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
4777 menu_logfont.lfWeight = FW_BOLD;
4778 menu_font = CreateFontIndirect (&menu_logfont);
4779 old_font = SelectObject (hdc, menu_font);
4780
4781 /* Always draw title as if not selected. */
4782 ExtTextOut (hdc,
4783 pDis->rcItem.left
4784 + GetSystemMetrics (SM_CXMENUCHECK),
4785 pDis->rcItem.top,
4786 ETO_OPAQUE, &pDis->rcItem,
4787 title, strlen (title), NULL);
4788
4789 SelectObject (hdc, old_font);
4790 DeleteObject (menu_font);
4791 }
4792 return TRUE;
4793 }
4794 }
4795 return 0;
4796
4797 #if 0
4798 /* Still not right - can't distinguish between clicks in the
4799 client area of the frame from clicks forwarded from the scroll
4800 bars - may have to hook WM_NCHITTEST to remember the mouse
4801 position and then check if it is in the client area ourselves. */
4802 case WM_MOUSEACTIVATE:
4803 /* Discard the mouse click that activates a frame, allowing the
4804 user to click anywhere without changing point (or worse!).
4805 Don't eat mouse clicks on scrollbars though!! */
4806 if (LOWORD (lParam) == HTCLIENT )
4807 return MA_ACTIVATEANDEAT;
4808 goto dflt;
4809 #endif
4810
4811 case WM_ACTIVATEAPP:
4812 case WM_ACTIVATE:
4813 case WM_WINDOWPOSCHANGED:
4814 case WM_SHOWWINDOW:
4815 /* Inform lisp thread that a frame might have just been obscured
4816 or exposed, so should recheck visibility of all frames. */
4817 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4818 goto dflt;
4819
4820 case WM_SETFOCUS:
4821 dpyinfo->faked_key = 0;
4822 reset_modifiers ();
4823 register_hot_keys (hwnd);
4824 goto command;
4825 case WM_KILLFOCUS:
4826 unregister_hot_keys (hwnd);
4827 button_state = 0;
4828 ReleaseCapture ();
4829 /* Relinquish the system caret. */
4830 if (w32_system_caret_hwnd)
4831 {
4832 DestroyCaret ();
4833 w32_system_caret_hwnd = NULL;
4834 }
4835 case WM_MOVE:
4836 case WM_SIZE:
4837 case WM_COMMAND:
4838 command:
4839 wmsg.dwModifiers = w32_get_modifiers ();
4840 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4841 goto dflt;
4842
4843 case WM_CLOSE:
4844 wmsg.dwModifiers = w32_get_modifiers ();
4845 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4846 return 0;
4847
4848 case WM_WINDOWPOSCHANGING:
4849 /* Don't restrict the sizing of tip frames. */
4850 if (hwnd == tip_window)
4851 return 0;
4852 {
4853 WINDOWPLACEMENT wp;
4854 LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
4855
4856 wp.length = sizeof (WINDOWPLACEMENT);
4857 GetWindowPlacement (hwnd, &wp);
4858
4859 if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0)
4860 {
4861 RECT rect;
4862 int wdiff;
4863 int hdiff;
4864 DWORD font_width;
4865 DWORD line_height;
4866 DWORD internal_border;
4867 DWORD scrollbar_extra;
4868 RECT wr;
4869
4870 wp.length = sizeof(wp);
4871 GetWindowRect (hwnd, &wr);
4872
4873 enter_crit ();
4874
4875 font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
4876 line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
4877 internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
4878 scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
4879
4880 leave_crit ();
4881
4882 memset (&rect, 0, sizeof (rect));
4883 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
4884 GetMenu (hwnd) != NULL);
4885
4886 /* Force width and height of client area to be exact
4887 multiples of the character cell dimensions. */
4888 wdiff = (lppos->cx - (rect.right - rect.left)
4889 - 2 * internal_border - scrollbar_extra)
4890 % font_width;
4891 hdiff = (lppos->cy - (rect.bottom - rect.top)
4892 - 2 * internal_border)
4893 % line_height;
4894
4895 if (wdiff || hdiff)
4896 {
4897 /* For right/bottom sizing we can just fix the sizes.
4898 However for top/left sizing we will need to fix the X
4899 and Y positions as well. */
4900
4901 lppos->cx -= wdiff;
4902 lppos->cy -= hdiff;
4903
4904 if (wp.showCmd != SW_SHOWMAXIMIZED
4905 && (lppos->flags & SWP_NOMOVE) == 0)
4906 {
4907 if (lppos->x != wr.left || lppos->y != wr.top)
4908 {
4909 lppos->x += wdiff;
4910 lppos->y += hdiff;
4911 }
4912 else
4913 {
4914 lppos->flags |= SWP_NOMOVE;
4915 }
4916 }
4917
4918 return 0;
4919 }
4920 }
4921 }
4922
4923 goto dflt;
4924
4925 case WM_GETMINMAXINFO:
4926 /* Hack to correct bug that allows Emacs frames to be resized
4927 below the Minimum Tracking Size. */
4928 ((LPMINMAXINFO) lParam)->ptMinTrackSize.y++;
4929 /* Hack to allow resizing the Emacs frame above the screen size.
4930 Note that Windows 9x limits coordinates to 16-bits. */
4931 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767;
4932 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767;
4933 return 0;
4934
4935 case WM_EMACS_CREATESCROLLBAR:
4936 return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
4937 (struct scroll_bar *) lParam);
4938
4939 case WM_EMACS_SHOWWINDOW:
4940 return ShowWindow ((HWND) wParam, (WPARAM) lParam);
4941
4942 case WM_EMACS_SETFOREGROUND:
4943 {
4944 HWND foreground_window;
4945 DWORD foreground_thread, retval;
4946
4947 /* On NT 5.0, and apparently Windows 98, it is necessary to
4948 attach to the thread that currently has focus in order to
4949 pull the focus away from it. */
4950 foreground_window = GetForegroundWindow ();
4951 foreground_thread = GetWindowThreadProcessId (foreground_window, NULL);
4952 if (!foreground_window
4953 || foreground_thread == GetCurrentThreadId ()
4954 || !AttachThreadInput (GetCurrentThreadId (),
4955 foreground_thread, TRUE))
4956 foreground_thread = 0;
4957
4958 retval = SetForegroundWindow ((HWND) wParam);
4959
4960 /* Detach from the previous foreground thread. */
4961 if (foreground_thread)
4962 AttachThreadInput (GetCurrentThreadId (),
4963 foreground_thread, FALSE);
4964
4965 return retval;
4966 }
4967
4968 case WM_EMACS_SETWINDOWPOS:
4969 {
4970 WINDOWPOS * pos = (WINDOWPOS *) wParam;
4971 return SetWindowPos (hwnd, pos->hwndInsertAfter,
4972 pos->x, pos->y, pos->cx, pos->cy, pos->flags);
4973 }
4974
4975 case WM_EMACS_DESTROYWINDOW:
4976 DragAcceptFiles ((HWND) wParam, FALSE);
4977 return DestroyWindow ((HWND) wParam);
4978
4979 case WM_EMACS_DESTROY_CARET:
4980 w32_system_caret_hwnd = NULL;
4981 return DestroyCaret ();
4982
4983 case WM_EMACS_TRACK_CARET:
4984 /* If there is currently no system caret, create one. */
4985 if (w32_system_caret_hwnd == NULL)
4986 {
4987 w32_system_caret_hwnd = hwnd;
4988 CreateCaret (hwnd, NULL, w32_system_caret_width,
4989 w32_system_caret_height);
4990 }
4991 return SetCaretPos (w32_system_caret_x, w32_system_caret_y);
4992
4993 case WM_EMACS_TRACKPOPUPMENU:
4994 {
4995 UINT flags;
4996 POINT *pos;
4997 int retval;
4998 pos = (POINT *)lParam;
4999 flags = TPM_CENTERALIGN;
5000 if (button_state & LMOUSE)
5001 flags |= TPM_LEFTBUTTON;
5002 else if (button_state & RMOUSE)
5003 flags |= TPM_RIGHTBUTTON;
5004
5005 /* Remember we did a SetCapture on the initial mouse down event,
5006 so for safety, we make sure the capture is cancelled now. */
5007 ReleaseCapture ();
5008 button_state = 0;
5009
5010 /* Use menubar_active to indicate that WM_INITMENU is from
5011 TrackPopupMenu below, and should be ignored. */
5012 f = x_window_to_frame (dpyinfo, hwnd);
5013 if (f)
5014 f->output_data.w32->menubar_active = 1;
5015
5016 if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
5017 0, hwnd, NULL))
5018 {
5019 MSG amsg;
5020 /* Eat any mouse messages during popupmenu */
5021 while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
5022 PM_REMOVE));
5023 /* Get the menu selection, if any */
5024 if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE))
5025 {
5026 retval = LOWORD (amsg.wParam);
5027 }
5028 else
5029 {
5030 retval = 0;
5031 }
5032 }
5033 else
5034 {
5035 retval = -1;
5036 }
5037
5038 return retval;
5039 }
5040
5041 default:
5042 /* Check for messages registered at runtime. */
5043 if (msg == msh_mousewheel)
5044 {
5045 wmsg.dwModifiers = w32_get_modifiers ();
5046 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
5047 return 0;
5048 }
5049
5050 dflt:
5051 return DefWindowProc (hwnd, msg, wParam, lParam);
5052 }
5053
5054
5055 /* The most common default return code for handled messages is 0. */
5056 return 0;
5057 }
5058
5059 void
5060 my_create_window (f)
5061 struct frame * f;
5062 {
5063 MSG msg;
5064
5065 if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
5066 abort ();
5067 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
5068 }
5069
5070
5071 /* Create a tooltip window. Unlike my_create_window, we do not do this
5072 indirectly via the Window thread, as we do not need to process Window
5073 messages for the tooltip. Creating tooltips indirectly also creates
5074 deadlocks when tooltips are created for menu items. */
5075 void
5076 my_create_tip_window (f)
5077 struct frame *f;
5078 {
5079 RECT rect;
5080
5081 rect.left = rect.top = 0;
5082 rect.right = PIXEL_WIDTH (f);
5083 rect.bottom = PIXEL_HEIGHT (f);
5084
5085 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
5086 FRAME_EXTERNAL_MENU_BAR (f));
5087
5088 tip_window = FRAME_W32_WINDOW (f)
5089 = CreateWindow (EMACS_CLASS,
5090 f->namebuf,
5091 f->output_data.w32->dwStyle,
5092 f->output_data.w32->left_pos,
5093 f->output_data.w32->top_pos,
5094 rect.right - rect.left,
5095 rect.bottom - rect.top,
5096 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
5097 NULL,
5098 hinst,
5099 NULL);
5100
5101 if (tip_window)
5102 {
5103 SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
5104 SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
5105 SetWindowLong (tip_window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
5106 SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
5107
5108 /* Tip frames have no scrollbars. */
5109 SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
5110
5111 /* Do this to discard the default setting specified by our parent. */
5112 ShowWindow (tip_window, SW_HIDE);
5113 }
5114 }
5115
5116
5117 /* Create and set up the w32 window for frame F. */
5118
5119 static void
5120 w32_window (f, window_prompting, minibuffer_only)
5121 struct frame *f;
5122 long window_prompting;
5123 int minibuffer_only;
5124 {
5125 BLOCK_INPUT;
5126
5127 /* Use the resource name as the top-level window name
5128 for looking up resources. Make a non-Lisp copy
5129 for the window manager, so GC relocation won't bother it.
5130
5131 Elsewhere we specify the window name for the window manager. */
5132
5133 {
5134 char *str = (char *) XSTRING (Vx_resource_name)->data;
5135 f->namebuf = (char *) xmalloc (strlen (str) + 1);
5136 strcpy (f->namebuf, str);
5137 }
5138
5139 my_create_window (f);
5140
5141 validate_x_resource_name ();
5142
5143 /* x_set_name normally ignores requests to set the name if the
5144 requested name is the same as the current name. This is the one
5145 place where that assumption isn't correct; f->name is set, but
5146 the server hasn't been told. */
5147 {
5148 Lisp_Object name;
5149 int explicit = f->explicit_name;
5150
5151 f->explicit_name = 0;
5152 name = f->name;
5153 f->name = Qnil;
5154 x_set_name (f, name, explicit);
5155 }
5156
5157 UNBLOCK_INPUT;
5158
5159 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
5160 initialize_frame_menubar (f);
5161
5162 if (FRAME_W32_WINDOW (f) == 0)
5163 error ("Unable to create window");
5164 }
5165
5166 /* Handle the icon stuff for this window. Perhaps later we might
5167 want an x_set_icon_position which can be called interactively as
5168 well. */
5169
5170 static void
5171 x_icon (f, parms)
5172 struct frame *f;
5173 Lisp_Object parms;
5174 {
5175 Lisp_Object icon_x, icon_y;
5176
5177 /* Set the position of the icon. Note that Windows 95 groups all
5178 icons in the tray. */
5179 icon_x = w32_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
5180 icon_y = w32_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
5181 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
5182 {
5183 CHECK_NUMBER (icon_x);
5184 CHECK_NUMBER (icon_y);
5185 }
5186 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
5187 error ("Both left and top icon corners of icon must be specified");
5188
5189 BLOCK_INPUT;
5190
5191 if (! EQ (icon_x, Qunbound))
5192 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
5193
5194 #if 0 /* TODO */
5195 /* Start up iconic or window? */
5196 x_wm_set_window_state
5197 (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
5198 ? IconicState
5199 : NormalState));
5200
5201 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
5202 ? f->icon_name
5203 : f->name))->data);
5204 #endif
5205
5206 UNBLOCK_INPUT;
5207 }
5208
5209
5210 static void
5211 x_make_gc (f)
5212 struct frame *f;
5213 {
5214 XGCValues gc_values;
5215
5216 BLOCK_INPUT;
5217
5218 /* Create the GC's of this frame.
5219 Note that many default values are used. */
5220
5221 /* Normal video */
5222 gc_values.font = f->output_data.w32->font;
5223
5224 /* Cursor has cursor-color background, background-color foreground. */
5225 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
5226 gc_values.background = f->output_data.w32->cursor_pixel;
5227 f->output_data.w32->cursor_gc
5228 = XCreateGC (NULL, FRAME_W32_WINDOW (f),
5229 (GCFont | GCForeground | GCBackground),
5230 &gc_values);
5231
5232 /* Reliefs. */
5233 f->output_data.w32->white_relief.gc = 0;
5234 f->output_data.w32->black_relief.gc = 0;
5235
5236 UNBLOCK_INPUT;
5237 }
5238
5239
5240 /* Handler for signals raised during x_create_frame and
5241 x_create_top_frame. FRAME is the frame which is partially
5242 constructed. */
5243
5244 static Lisp_Object
5245 unwind_create_frame (frame)
5246 Lisp_Object frame;
5247 {
5248 struct frame *f = XFRAME (frame);
5249
5250 /* If frame is ``official'', nothing to do. */
5251 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
5252 {
5253 #ifdef GLYPH_DEBUG
5254 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5255 #endif
5256
5257 x_free_frame_resources (f);
5258
5259 /* Check that reference counts are indeed correct. */
5260 xassert (dpyinfo->reference_count == dpyinfo_refcount);
5261 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
5262
5263 return Qt;
5264 }
5265
5266 return Qnil;
5267 }
5268
5269
5270 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
5271 1, 1, 0,
5272 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
5273 Returns an Emacs frame object.
5274 ALIST is an alist of frame parameters.
5275 If the parameters specify that the frame should not have a minibuffer,
5276 and do not specify a specific minibuffer window to use,
5277 then `default-minibuffer-frame' must be a frame whose minibuffer can
5278 be shared by the new frame.
5279
5280 This function is an internal primitive--use `make-frame' instead. */)
5281 (parms)
5282 Lisp_Object parms;
5283 {
5284 struct frame *f;
5285 Lisp_Object frame, tem;
5286 Lisp_Object name;
5287 int minibuffer_only = 0;
5288 long window_prompting = 0;
5289 int width, height;
5290 int count = BINDING_STACK_SIZE ();
5291 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5292 Lisp_Object display;
5293 struct w32_display_info *dpyinfo = NULL;
5294 Lisp_Object parent;
5295 struct kboard *kb;
5296
5297 check_w32 ();
5298
5299 /* Use this general default value to start with
5300 until we know if this frame has a specified name. */
5301 Vx_resource_name = Vinvocation_name;
5302
5303 display = w32_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
5304 if (EQ (display, Qunbound))
5305 display = Qnil;
5306 dpyinfo = check_x_display_info (display);
5307 #ifdef MULTI_KBOARD
5308 kb = dpyinfo->kboard;
5309 #else
5310 kb = &the_only_kboard;
5311 #endif
5312
5313 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
5314 if (!STRINGP (name)
5315 && ! EQ (name, Qunbound)
5316 && ! NILP (name))
5317 error ("Invalid frame name--not a string or nil");
5318
5319 if (STRINGP (name))
5320 Vx_resource_name = name;
5321
5322 /* See if parent window is specified. */
5323 parent = w32_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
5324 if (EQ (parent, Qunbound))
5325 parent = Qnil;
5326 if (! NILP (parent))
5327 CHECK_NUMBER (parent);
5328
5329 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
5330 /* No need to protect DISPLAY because that's not used after passing
5331 it to make_frame_without_minibuffer. */
5332 frame = Qnil;
5333 GCPRO4 (parms, parent, name, frame);
5334 tem = w32_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
5335 RES_TYPE_SYMBOL);
5336 if (EQ (tem, Qnone) || NILP (tem))
5337 f = make_frame_without_minibuffer (Qnil, kb, display);
5338 else if (EQ (tem, Qonly))
5339 {
5340 f = make_minibuffer_frame ();
5341 minibuffer_only = 1;
5342 }
5343 else if (WINDOWP (tem))
5344 f = make_frame_without_minibuffer (tem, kb, display);
5345 else
5346 f = make_frame (1);
5347
5348 XSETFRAME (frame, f);
5349
5350 /* Note that Windows does support scroll bars. */
5351 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
5352 /* By default, make scrollbars the system standard width. */
5353 f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL);
5354
5355 f->output_method = output_w32;
5356 f->output_data.w32 =
5357 (struct w32_output *) xmalloc (sizeof (struct w32_output));
5358 bzero (f->output_data.w32, sizeof (struct w32_output));
5359 FRAME_FONTSET (f) = -1;
5360 record_unwind_protect (unwind_create_frame, frame);
5361
5362 f->icon_name
5363 = w32_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
5364 if (! STRINGP (f->icon_name))
5365 f->icon_name = Qnil;
5366
5367 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
5368 #ifdef MULTI_KBOARD
5369 FRAME_KBOARD (f) = kb;
5370 #endif
5371
5372 /* Specify the parent under which to make this window. */
5373
5374 if (!NILP (parent))
5375 {
5376 f->output_data.w32->parent_desc = (Window) XFASTINT (parent);
5377 f->output_data.w32->explicit_parent = 1;
5378 }
5379 else
5380 {
5381 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5382 f->output_data.w32->explicit_parent = 0;
5383 }
5384
5385 /* Set the name; the functions to which we pass f expect the name to
5386 be set. */
5387 if (EQ (name, Qunbound) || NILP (name))
5388 {
5389 f->name = build_string (dpyinfo->w32_id_name);
5390 f->explicit_name = 0;
5391 }
5392 else
5393 {
5394 f->name = name;
5395 f->explicit_name = 1;
5396 /* use the frame's title when getting resources for this frame. */
5397 specbind (Qx_resource_name, name);
5398 }
5399
5400 /* Extract the window parameters from the supplied values
5401 that are needed to determine window geometry. */
5402 {
5403 Lisp_Object font;
5404
5405 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
5406
5407 BLOCK_INPUT;
5408 /* First, try whatever font the caller has specified. */
5409 if (STRINGP (font))
5410 {
5411 tem = Fquery_fontset (font, Qnil);
5412 if (STRINGP (tem))
5413 font = x_new_fontset (f, XSTRING (tem)->data);
5414 else
5415 font = x_new_font (f, XSTRING (font)->data);
5416 }
5417 /* Try out a font which we hope has bold and italic variations. */
5418 if (!STRINGP (font))
5419 font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
5420 if (! STRINGP (font))
5421 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
5422 /* If those didn't work, look for something which will at least work. */
5423 if (! STRINGP (font))
5424 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
5425 UNBLOCK_INPUT;
5426 if (! STRINGP (font))
5427 font = build_string ("Fixedsys");
5428
5429 x_default_parameter (f, parms, Qfont, font,
5430 "font", "Font", RES_TYPE_STRING);
5431 }
5432
5433 x_default_parameter (f, parms, Qborder_width, make_number (2),
5434 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
5435 /* This defaults to 2 in order to match xterm. We recognize either
5436 internalBorderWidth or internalBorder (which is what xterm calls
5437 it). */
5438 if (NILP (Fassq (Qinternal_border_width, parms)))
5439 {
5440 Lisp_Object value;
5441
5442 value = w32_get_arg (parms, Qinternal_border_width,
5443 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
5444 if (! EQ (value, Qunbound))
5445 parms = Fcons (Fcons (Qinternal_border_width, value),
5446 parms);
5447 }
5448 /* Default internalBorderWidth to 0 on Windows to match other programs. */
5449 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
5450 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
5451 x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
5452 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
5453
5454 /* Also do the stuff which must be set before the window exists. */
5455 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5456 "foreground", "Foreground", RES_TYPE_STRING);
5457 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5458 "background", "Background", RES_TYPE_STRING);
5459 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5460 "pointerColor", "Foreground", RES_TYPE_STRING);
5461 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
5462 "cursorColor", "Foreground", RES_TYPE_STRING);
5463 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5464 "borderColor", "BorderColor", RES_TYPE_STRING);
5465 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
5466 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
5467 x_default_parameter (f, parms, Qline_spacing, Qnil,
5468 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
5469 x_default_parameter (f, parms, Qleft_fringe, Qnil,
5470 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
5471 x_default_parameter (f, parms, Qright_fringe, Qnil,
5472 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
5473
5474
5475 /* Init faces before x_default_parameter is called for scroll-bar
5476 parameters because that function calls x_set_scroll_bar_width,
5477 which calls change_frame_size, which calls Fset_window_buffer,
5478 which runs hooks, which call Fvertical_motion. At the end, we
5479 end up in init_iterator with a null face cache, which should not
5480 happen. */
5481 init_frame_faces (f);
5482
5483 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
5484 "menuBar", "MenuBar", RES_TYPE_NUMBER);
5485 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
5486 "toolBar", "ToolBar", RES_TYPE_NUMBER);
5487 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
5488 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
5489 x_default_parameter (f, parms, Qtitle, Qnil,
5490 "title", "Title", RES_TYPE_STRING);
5491
5492 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
5493 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5494
5495 /* Add the tool-bar height to the initial frame height so that the
5496 user gets a text display area of the size he specified with -g or
5497 via .Xdefaults. Later changes of the tool-bar height don't
5498 change the frame size. This is done so that users can create
5499 tall Emacs frames without having to guess how tall the tool-bar
5500 will get. */
5501 if (FRAME_TOOL_BAR_LINES (f))
5502 {
5503 int margin, relief, bar_height;
5504
5505 relief = (tool_bar_button_relief >= 0
5506 ? tool_bar_button_relief
5507 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
5508
5509 if (INTEGERP (Vtool_bar_button_margin)
5510 && XINT (Vtool_bar_button_margin) > 0)
5511 margin = XFASTINT (Vtool_bar_button_margin);
5512 else if (CONSP (Vtool_bar_button_margin)
5513 && INTEGERP (XCDR (Vtool_bar_button_margin))
5514 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
5515 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
5516 else
5517 margin = 0;
5518
5519 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5520 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
5521 }
5522
5523 window_prompting = x_figure_window_size (f, parms);
5524
5525 if (window_prompting & XNegative)
5526 {
5527 if (window_prompting & YNegative)
5528 f->output_data.w32->win_gravity = SouthEastGravity;
5529 else
5530 f->output_data.w32->win_gravity = NorthEastGravity;
5531 }
5532 else
5533 {
5534 if (window_prompting & YNegative)
5535 f->output_data.w32->win_gravity = SouthWestGravity;
5536 else
5537 f->output_data.w32->win_gravity = NorthWestGravity;
5538 }
5539
5540 f->output_data.w32->size_hint_flags = window_prompting;
5541
5542 tem = w32_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
5543 f->no_split = minibuffer_only || EQ (tem, Qt);
5544
5545 w32_window (f, window_prompting, minibuffer_only);
5546 x_icon (f, parms);
5547
5548 x_make_gc (f);
5549
5550 /* Now consider the frame official. */
5551 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
5552 Vframe_list = Fcons (frame, Vframe_list);
5553
5554 /* We need to do this after creating the window, so that the
5555 icon-creation functions can say whose icon they're describing. */
5556 x_default_parameter (f, parms, Qicon_type, Qnil,
5557 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
5558
5559 x_default_parameter (f, parms, Qauto_raise, Qnil,
5560 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5561 x_default_parameter (f, parms, Qauto_lower, Qnil,
5562 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5563 x_default_parameter (f, parms, Qcursor_type, Qbox,
5564 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5565 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
5566 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
5567
5568 /* Dimensions, especially f->height, must be done via change_frame_size.
5569 Change will not be effected unless different from the current
5570 f->height. */
5571 width = f->width;
5572 height = f->height;
5573
5574 f->height = 0;
5575 SET_FRAME_WIDTH (f, 0);
5576 change_frame_size (f, height, width, 1, 0, 0);
5577
5578 /* Tell the server what size and position, etc, we want, and how
5579 badly we want them. This should be done after we have the menu
5580 bar so that its size can be taken into account. */
5581 BLOCK_INPUT;
5582 x_wm_set_size_hint (f, window_prompting, 0);
5583 UNBLOCK_INPUT;
5584
5585 /* Set up faces after all frame parameters are known. This call
5586 also merges in face attributes specified for new frames. If we
5587 don't do this, the `menu' face for instance won't have the right
5588 colors, and the menu bar won't appear in the specified colors for
5589 new frames. */
5590 call1 (Qface_set_after_frame_default, frame);
5591
5592 /* Make the window appear on the frame and enable display, unless
5593 the caller says not to. However, with explicit parent, Emacs
5594 cannot control visibility, so don't try. */
5595 if (! f->output_data.w32->explicit_parent)
5596 {
5597 Lisp_Object visibility;
5598
5599 visibility = w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
5600 if (EQ (visibility, Qunbound))
5601 visibility = Qt;
5602
5603 if (EQ (visibility, Qicon))
5604 x_iconify_frame (f);
5605 else if (! NILP (visibility))
5606 x_make_frame_visible (f);
5607 else
5608 /* Must have been Qnil. */
5609 ;
5610 }
5611 UNGCPRO;
5612
5613 /* Make sure windows on this frame appear in calls to next-window
5614 and similar functions. */
5615 Vwindow_list = Qnil;
5616
5617 return unbind_to (count, frame);
5618 }
5619
5620 /* FRAME is used only to get a handle on the X display. We don't pass the
5621 display info directly because we're called from frame.c, which doesn't
5622 know about that structure. */
5623 Lisp_Object
5624 x_get_focus_frame (frame)
5625 struct frame *frame;
5626 {
5627 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
5628 Lisp_Object xfocus;
5629 if (! dpyinfo->w32_focus_frame)
5630 return Qnil;
5631
5632 XSETFRAME (xfocus, dpyinfo->w32_focus_frame);
5633 return xfocus;
5634 }
5635
5636 DEFUN ("w32-focus-frame", Fw32_focus_frame, Sw32_focus_frame, 1, 1, 0,
5637 doc: /* Give FRAME input focus, raising to foreground if necessary. */)
5638 (frame)
5639 Lisp_Object frame;
5640 {
5641 x_focus_on_frame (check_x_frame (frame));
5642 return Qnil;
5643 }
5644
5645 \f
5646 /* Return the charset portion of a font name. */
5647 char * xlfd_charset_of_font (char * fontname)
5648 {
5649 char *charset, *encoding;
5650
5651 encoding = strrchr(fontname, '-');
5652 if (!encoding || encoding == fontname)
5653 return NULL;
5654
5655 for (charset = encoding - 1; charset >= fontname; charset--)
5656 if (*charset == '-')
5657 break;
5658
5659 if (charset == fontname || strcmp(charset, "-*-*") == 0)
5660 return NULL;
5661
5662 return charset + 1;
5663 }
5664
5665 struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
5666 int size, char* filename);
5667 static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names);
5668 static BOOL w32_to_x_font (LOGFONT * lplf, char * lpxstr, int len,
5669 char * charset);
5670 static BOOL x_to_w32_font (char *lpxstr, LOGFONT *lplogfont);
5671
5672 static struct font_info *
5673 w32_load_system_font (f,fontname,size)
5674 struct frame *f;
5675 char * fontname;
5676 int size;
5677 {
5678 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5679 Lisp_Object font_names;
5680
5681 /* Get a list of all the fonts that match this name. Once we
5682 have a list of matching fonts, we compare them against the fonts
5683 we already have loaded by comparing names. */
5684 font_names = w32_list_fonts (f, build_string (fontname), size, 100);
5685
5686 if (!NILP (font_names))
5687 {
5688 Lisp_Object tail;
5689 int i;
5690
5691 /* First check if any are already loaded, as that is cheaper
5692 than loading another one. */
5693 for (i = 0; i < dpyinfo->n_fonts; i++)
5694 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
5695 if (dpyinfo->font_table[i].name
5696 && (!strcmp (dpyinfo->font_table[i].name,
5697 XSTRING (XCAR (tail))->data)
5698 || !strcmp (dpyinfo->font_table[i].full_name,
5699 XSTRING (XCAR (tail))->data)))
5700 return (dpyinfo->font_table + i);
5701
5702 fontname = (char *) XSTRING (XCAR (font_names))->data;
5703 }
5704 else if (w32_strict_fontnames)
5705 {
5706 /* If EnumFontFamiliesEx was available, we got a full list of
5707 fonts back so stop now to avoid the possibility of loading a
5708 random font. If we had to fall back to EnumFontFamilies, the
5709 list is incomplete, so continue whether the font we want was
5710 listed or not. */
5711 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
5712 FARPROC enum_font_families_ex
5713 = GetProcAddress (gdi32, "EnumFontFamiliesExA");
5714 if (enum_font_families_ex)
5715 return NULL;
5716 }
5717
5718 /* Load the font and add it to the table. */
5719 {
5720 char *full_name, *encoding, *charset;
5721 XFontStruct *font;
5722 struct font_info *fontp;
5723 LOGFONT lf;
5724 BOOL ok;
5725 int codepage;
5726 int i;
5727
5728 if (!fontname || !x_to_w32_font (fontname, &lf))
5729 return (NULL);
5730
5731 if (!*lf.lfFaceName)
5732 /* If no name was specified for the font, we get a random font
5733 from CreateFontIndirect - this is not particularly
5734 desirable, especially since CreateFontIndirect does not
5735 fill out the missing name in lf, so we never know what we
5736 ended up with. */
5737 return NULL;
5738
5739 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
5740 bzero (font, sizeof (*font));
5741
5742 /* Set bdf to NULL to indicate that this is a Windows font. */
5743 font->bdf = NULL;
5744
5745 BLOCK_INPUT;
5746
5747 font->hfont = CreateFontIndirect (&lf);
5748
5749 if (font->hfont == NULL)
5750 {
5751 ok = FALSE;
5752 }
5753 else
5754 {
5755 HDC hdc;
5756 HANDLE oldobj;
5757
5758 codepage = w32_codepage_for_font (fontname);
5759
5760 hdc = GetDC (dpyinfo->root_window);
5761 oldobj = SelectObject (hdc, font->hfont);
5762
5763 ok = GetTextMetrics (hdc, &font->tm);
5764 if (codepage == CP_UNICODE)
5765 font->double_byte_p = 1;
5766 else
5767 {
5768 /* Unfortunately, some fonts (eg. MingLiU, a big5 ttf font)
5769 don't report themselves as double byte fonts, when
5770 patently they are. So instead of trusting
5771 GetFontLanguageInfo, we check the properties of the
5772 codepage directly, since that is ultimately what we are
5773 working from anyway. */
5774 /* font->double_byte_p = GetFontLanguageInfo(hdc) & GCP_DBCS; */
5775 CPINFO cpi = {0};
5776 GetCPInfo (codepage, &cpi);
5777 font->double_byte_p = cpi.MaxCharSize > 1;
5778 }
5779
5780 SelectObject (hdc, oldobj);
5781 ReleaseDC (dpyinfo->root_window, hdc);
5782 /* Fill out details in lf according to the font that was
5783 actually loaded. */
5784 lf.lfHeight = font->tm.tmInternalLeading - font->tm.tmHeight;
5785 lf.lfWidth = font->tm.tmAveCharWidth;
5786 lf.lfWeight = font->tm.tmWeight;
5787 lf.lfItalic = font->tm.tmItalic;
5788 lf.lfCharSet = font->tm.tmCharSet;
5789 lf.lfPitchAndFamily = ((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
5790 ? VARIABLE_PITCH : FIXED_PITCH);
5791 lf.lfOutPrecision = ((font->tm.tmPitchAndFamily & TMPF_VECTOR)
5792 ? OUT_STROKE_PRECIS : OUT_STRING_PRECIS);
5793
5794 w32_cache_char_metrics (font);
5795 }
5796
5797 UNBLOCK_INPUT;
5798
5799 if (!ok)
5800 {
5801 w32_unload_font (dpyinfo, font);
5802 return (NULL);
5803 }
5804
5805 /* Find a free slot in the font table. */
5806 for (i = 0; i < dpyinfo->n_fonts; ++i)
5807 if (dpyinfo->font_table[i].name == NULL)
5808 break;
5809
5810 /* If no free slot found, maybe enlarge the font table. */
5811 if (i == dpyinfo->n_fonts
5812 && dpyinfo->n_fonts == dpyinfo->font_table_size)
5813 {
5814 int sz;
5815 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
5816 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
5817 dpyinfo->font_table
5818 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
5819 }
5820
5821 fontp = dpyinfo->font_table + i;
5822 if (i == dpyinfo->n_fonts)
5823 ++dpyinfo->n_fonts;
5824
5825 /* Now fill in the slots of *FONTP. */
5826 BLOCK_INPUT;
5827 fontp->font = font;
5828 fontp->font_idx = i;
5829 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
5830 bcopy (fontname, fontp->name, strlen (fontname) + 1);
5831
5832 charset = xlfd_charset_of_font (fontname);
5833
5834 /* Cache the W32 codepage for a font. This makes w32_encode_char
5835 (called for every glyph during redisplay) much faster. */
5836 fontp->codepage = codepage;
5837
5838 /* Work out the font's full name. */
5839 full_name = (char *)xmalloc (100);
5840 if (full_name && w32_to_x_font (&lf, full_name, 100, charset))
5841 fontp->full_name = full_name;
5842 else
5843 {
5844 /* If all else fails - just use the name we used to load it. */
5845 xfree (full_name);
5846 fontp->full_name = fontp->name;
5847 }
5848
5849 fontp->size = FONT_WIDTH (font);
5850 fontp->height = FONT_HEIGHT (font);
5851
5852 /* The slot `encoding' specifies how to map a character
5853 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
5854 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
5855 (0:0x20..0x7F, 1:0xA0..0xFF,
5856 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
5857 2:0xA020..0xFF7F). For the moment, we don't know which charset
5858 uses this font. So, we set information in fontp->encoding[1]
5859 which is never used by any charset. If mapping can't be
5860 decided, set FONT_ENCODING_NOT_DECIDED. */
5861
5862 /* SJIS fonts need to be set to type 4, all others seem to work as
5863 type FONT_ENCODING_NOT_DECIDED. */
5864 encoding = strrchr (fontp->name, '-');
5865 if (encoding && stricmp (encoding+1, "sjis") == 0)
5866 fontp->encoding[1] = 4;
5867 else
5868 fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
5869
5870 /* The following three values are set to 0 under W32, which is
5871 what they get set to if XGetFontProperty fails under X. */
5872 fontp->baseline_offset = 0;
5873 fontp->relative_compose = 0;
5874 fontp->default_ascent = 0;
5875
5876 /* Set global flag fonts_changed_p to non-zero if the font loaded
5877 has a character with a smaller width than any other character
5878 before, or if the font loaded has a smalle>r height than any
5879 other font loaded before. If this happens, it will make a
5880 glyph matrix reallocation necessary. */
5881 fonts_changed_p = x_compute_min_glyph_bounds (f);
5882 UNBLOCK_INPUT;
5883 return fontp;
5884 }
5885 }
5886
5887 /* Load font named FONTNAME of size SIZE for frame F, and return a
5888 pointer to the structure font_info while allocating it dynamically.
5889 If loading fails, return NULL. */
5890 struct font_info *
5891 w32_load_font (f,fontname,size)
5892 struct frame *f;
5893 char * fontname;
5894 int size;
5895 {
5896 Lisp_Object bdf_fonts;
5897 struct font_info *retval = NULL;
5898
5899 bdf_fonts = w32_list_bdf_fonts (build_string (fontname), 1);
5900
5901 while (!retval && CONSP (bdf_fonts))
5902 {
5903 char *bdf_name, *bdf_file;
5904 Lisp_Object bdf_pair;
5905
5906 bdf_name = XSTRING (XCAR (bdf_fonts))->data;
5907 bdf_pair = Fassoc (XCAR (bdf_fonts), Vw32_bdf_filename_alist);
5908 bdf_file = XSTRING (XCDR (bdf_pair))->data;
5909
5910 retval = w32_load_bdf_font (f, bdf_name, size, bdf_file);
5911
5912 bdf_fonts = XCDR (bdf_fonts);
5913 }
5914
5915 if (retval)
5916 return retval;
5917
5918 return w32_load_system_font(f, fontname, size);
5919 }
5920
5921
5922 void
5923 w32_unload_font (dpyinfo, font)
5924 struct w32_display_info *dpyinfo;
5925 XFontStruct * font;
5926 {
5927 if (font)
5928 {
5929 if (font->per_char) xfree (font->per_char);
5930 if (font->bdf) w32_free_bdf_font (font->bdf);
5931
5932 if (font->hfont) DeleteObject(font->hfont);
5933 xfree (font);
5934 }
5935 }
5936
5937 /* The font conversion stuff between x and w32 */
5938
5939 /* X font string is as follows (from faces.el)
5940 * (let ((- "[-?]")
5941 * (foundry "[^-]+")
5942 * (family "[^-]+")
5943 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
5944 * (weight\? "\\([^-]*\\)") ; 1
5945 * (slant "\\([ior]\\)") ; 2
5946 * (slant\? "\\([^-]?\\)") ; 2
5947 * (swidth "\\([^-]*\\)") ; 3
5948 * (adstyle "[^-]*") ; 4
5949 * (pixelsize "[0-9]+")
5950 * (pointsize "[0-9][0-9]+")
5951 * (resx "[0-9][0-9]+")
5952 * (resy "[0-9][0-9]+")
5953 * (spacing "[cmp?*]")
5954 * (avgwidth "[0-9]+")
5955 * (registry "[^-]+")
5956 * (encoding "[^-]+")
5957 * )
5958 */
5959
5960 static LONG
5961 x_to_w32_weight (lpw)
5962 char * lpw;
5963 {
5964 if (!lpw) return (FW_DONTCARE);
5965
5966 if (stricmp (lpw,"heavy") == 0) return FW_HEAVY;
5967 else if (stricmp (lpw,"extrabold") == 0) return FW_EXTRABOLD;
5968 else if (stricmp (lpw,"bold") == 0) return FW_BOLD;
5969 else if (stricmp (lpw,"demibold") == 0) return FW_SEMIBOLD;
5970 else if (stricmp (lpw,"semibold") == 0) return FW_SEMIBOLD;
5971 else if (stricmp (lpw,"medium") == 0) return FW_MEDIUM;
5972 else if (stricmp (lpw,"normal") == 0) return FW_NORMAL;
5973 else if (stricmp (lpw,"light") == 0) return FW_LIGHT;
5974 else if (stricmp (lpw,"extralight") == 0) return FW_EXTRALIGHT;
5975 else if (stricmp (lpw,"thin") == 0) return FW_THIN;
5976 else
5977 return FW_DONTCARE;
5978 }
5979
5980
5981 static char *
5982 w32_to_x_weight (fnweight)
5983 int fnweight;
5984 {
5985 if (fnweight >= FW_HEAVY) return "heavy";
5986 if (fnweight >= FW_EXTRABOLD) return "extrabold";
5987 if (fnweight >= FW_BOLD) return "bold";
5988 if (fnweight >= FW_SEMIBOLD) return "demibold";
5989 if (fnweight >= FW_MEDIUM) return "medium";
5990 if (fnweight >= FW_NORMAL) return "normal";
5991 if (fnweight >= FW_LIGHT) return "light";
5992 if (fnweight >= FW_EXTRALIGHT) return "extralight";
5993 if (fnweight >= FW_THIN) return "thin";
5994 else
5995 return "*";
5996 }
5997
5998 static LONG
5999 x_to_w32_charset (lpcs)
6000 char * lpcs;
6001 {
6002 Lisp_Object this_entry, w32_charset;
6003 char *charset;
6004 int len = strlen (lpcs);
6005
6006 /* Support "*-#nnn" format for unknown charsets. */
6007 if (strncmp (lpcs, "*-#", 3) == 0)
6008 return atoi (lpcs + 3);
6009
6010 /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5". */
6011 charset = alloca (len + 1);
6012 strcpy (charset, lpcs);
6013 lpcs = strchr (charset, '*');
6014 if (lpcs)
6015 *lpcs = 0;
6016
6017 /* Look through w32-charset-info-alist for the character set.
6018 Format of each entry is
6019 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
6020 */
6021 this_entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
6022
6023 if (NILP(this_entry))
6024 {
6025 /* At startup, we want iso8859-1 fonts to come up properly. */
6026 if (stricmp(charset, "iso8859-1") == 0)
6027 return ANSI_CHARSET;
6028 else
6029 return DEFAULT_CHARSET;
6030 }
6031
6032 w32_charset = Fcar (Fcdr (this_entry));
6033
6034 // Translate Lisp symbol to number.
6035 if (w32_charset == Qw32_charset_ansi)
6036 return ANSI_CHARSET;
6037 if (w32_charset == Qw32_charset_symbol)
6038 return SYMBOL_CHARSET;
6039 if (w32_charset == Qw32_charset_shiftjis)
6040 return SHIFTJIS_CHARSET;
6041 if (w32_charset == Qw32_charset_hangeul)
6042 return HANGEUL_CHARSET;
6043 if (w32_charset == Qw32_charset_chinesebig5)
6044 return CHINESEBIG5_CHARSET;
6045 if (w32_charset == Qw32_charset_gb2312)
6046 return GB2312_CHARSET;
6047 if (w32_charset == Qw32_charset_oem)
6048 return OEM_CHARSET;
6049 #ifdef JOHAB_CHARSET
6050 if (w32_charset == Qw32_charset_johab)
6051 return JOHAB_CHARSET;
6052 if (w32_charset == Qw32_charset_easteurope)
6053 return EASTEUROPE_CHARSET;
6054 if (w32_charset == Qw32_charset_turkish)
6055 return TURKISH_CHARSET;
6056 if (w32_charset == Qw32_charset_baltic)
6057 return BALTIC_CHARSET;
6058 if (w32_charset == Qw32_charset_russian)
6059 return RUSSIAN_CHARSET;
6060 if (w32_charset == Qw32_charset_arabic)
6061 return ARABIC_CHARSET;
6062 if (w32_charset == Qw32_charset_greek)
6063 return GREEK_CHARSET;
6064 if (w32_charset == Qw32_charset_hebrew)
6065 return HEBREW_CHARSET;
6066 if (w32_charset == Qw32_charset_vietnamese)
6067 return VIETNAMESE_CHARSET;
6068 if (w32_charset == Qw32_charset_thai)
6069 return THAI_CHARSET;
6070 if (w32_charset == Qw32_charset_mac)
6071 return MAC_CHARSET;
6072 #endif /* JOHAB_CHARSET */
6073 #ifdef UNICODE_CHARSET
6074 if (w32_charset == Qw32_charset_unicode)
6075 return UNICODE_CHARSET;
6076 #endif
6077
6078 return DEFAULT_CHARSET;
6079 }
6080
6081
6082 static char *
6083 w32_to_x_charset (fncharset)
6084 int fncharset;
6085 {
6086 static char buf[32];
6087 Lisp_Object charset_type;
6088
6089 switch (fncharset)
6090 {
6091 case ANSI_CHARSET:
6092 /* Handle startup case of w32-charset-info-alist not
6093 being set up yet. */
6094 if (NILP(Vw32_charset_info_alist))
6095 return "iso8859-1";
6096 charset_type = Qw32_charset_ansi;
6097 break;
6098 case DEFAULT_CHARSET:
6099 charset_type = Qw32_charset_default;
6100 break;
6101 case SYMBOL_CHARSET:
6102 charset_type = Qw32_charset_symbol;
6103 break;
6104 case SHIFTJIS_CHARSET:
6105 charset_type = Qw32_charset_shiftjis;
6106 break;
6107 case HANGEUL_CHARSET:
6108 charset_type = Qw32_charset_hangeul;
6109 break;
6110 case GB2312_CHARSET:
6111 charset_type = Qw32_charset_gb2312;
6112 break;
6113 case CHINESEBIG5_CHARSET:
6114 charset_type = Qw32_charset_chinesebig5;
6115 break;
6116 case OEM_CHARSET:
6117 charset_type = Qw32_charset_oem;
6118 break;
6119
6120 /* More recent versions of Windows (95 and NT4.0) define more
6121 character sets. */
6122 #ifdef EASTEUROPE_CHARSET
6123 case EASTEUROPE_CHARSET:
6124 charset_type = Qw32_charset_easteurope;
6125 break;
6126 case TURKISH_CHARSET:
6127 charset_type = Qw32_charset_turkish;
6128 break;
6129 case BALTIC_CHARSET:
6130 charset_type = Qw32_charset_baltic;
6131 break;
6132 case RUSSIAN_CHARSET:
6133 charset_type = Qw32_charset_russian;
6134 break;
6135 case ARABIC_CHARSET:
6136 charset_type = Qw32_charset_arabic;
6137 break;
6138 case GREEK_CHARSET:
6139 charset_type = Qw32_charset_greek;
6140 break;
6141 case HEBREW_CHARSET:
6142 charset_type = Qw32_charset_hebrew;
6143 break;
6144 case VIETNAMESE_CHARSET:
6145 charset_type = Qw32_charset_vietnamese;
6146 break;
6147 case THAI_CHARSET:
6148 charset_type = Qw32_charset_thai;
6149 break;
6150 case MAC_CHARSET:
6151 charset_type = Qw32_charset_mac;
6152 break;
6153 case JOHAB_CHARSET:
6154 charset_type = Qw32_charset_johab;
6155 break;
6156 #endif
6157
6158 #ifdef UNICODE_CHARSET
6159 case UNICODE_CHARSET:
6160 charset_type = Qw32_charset_unicode;
6161 break;
6162 #endif
6163 default:
6164 /* Encode numerical value of unknown charset. */
6165 sprintf (buf, "*-#%u", fncharset);
6166 return buf;
6167 }
6168
6169 {
6170 Lisp_Object rest;
6171 char * best_match = NULL;
6172
6173 /* Look through w32-charset-info-alist for the character set.
6174 Prefer ISO codepages, and prefer lower numbers in the ISO
6175 range. Only return charsets for codepages which are installed.
6176
6177 Format of each entry is
6178 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
6179 */
6180 for (rest = Vw32_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6181 {
6182 char * x_charset;
6183 Lisp_Object w32_charset;
6184 Lisp_Object codepage;
6185
6186 Lisp_Object this_entry = XCAR (rest);
6187
6188 /* Skip invalid entries in alist. */
6189 if (!CONSP (this_entry) || !STRINGP (XCAR (this_entry))
6190 || !CONSP (XCDR (this_entry))
6191 || !SYMBOLP (XCAR (XCDR (this_entry))))
6192 continue;
6193
6194 x_charset = XSTRING (XCAR (this_entry))->data;
6195 w32_charset = XCAR (XCDR (this_entry));
6196 codepage = XCDR (XCDR (this_entry));
6197
6198 /* Look for Same charset and a valid codepage (or non-int
6199 which means ignore). */
6200 if (w32_charset == charset_type
6201 && (!INTEGERP (codepage) || codepage == CP_DEFAULT
6202 || IsValidCodePage (XINT (codepage))))
6203 {
6204 /* If we don't have a match already, then this is the
6205 best. */
6206 if (!best_match)
6207 best_match = x_charset;
6208 /* If this is an ISO codepage, and the best so far isn't,
6209 then this is better. */
6210 else if (stricmp (best_match, "iso") != 0
6211 && stricmp (x_charset, "iso") == 0)
6212 best_match = x_charset;
6213 /* If both are ISO8859 codepages, choose the one with the
6214 lowest number in the encoding field. */
6215 else if (stricmp (best_match, "iso8859-") == 0
6216 && stricmp (x_charset, "iso8859-") == 0)
6217 {
6218 int best_enc = atoi (best_match + 8);
6219 int this_enc = atoi (x_charset + 8);
6220 if (this_enc > 0 && this_enc < best_enc)
6221 best_match = x_charset;
6222 }
6223 }
6224 }
6225
6226 /* If no match, encode the numeric value. */
6227 if (!best_match)
6228 {
6229 sprintf (buf, "*-#%u", fncharset);
6230 return buf;
6231 }
6232
6233 strncpy(buf, best_match, 31);
6234 buf[31] = '\0';
6235 return buf;
6236 }
6237 }
6238
6239
6240 /* Get the Windows codepage corresponding to the specified font. The
6241 charset info in the font name is used to look up
6242 w32-charset-to-codepage-alist. */
6243 int
6244 w32_codepage_for_font (char *fontname)
6245 {
6246 Lisp_Object codepage, entry;
6247 char *charset_str, *charset, *end;
6248
6249 if (NILP (Vw32_charset_info_alist))
6250 return CP_DEFAULT;
6251
6252 /* Extract charset part of font string. */
6253 charset = xlfd_charset_of_font (fontname);
6254
6255 if (!charset)
6256 return CP_UNKNOWN;
6257
6258 charset_str = (char *) alloca (strlen (charset) + 1);
6259 strcpy (charset_str, charset);
6260
6261 #if 0
6262 /* Remove leading "*-". */
6263 if (strncmp ("*-", charset_str, 2) == 0)
6264 charset = charset_str + 2;
6265 else
6266 #endif
6267 charset = charset_str;
6268
6269 /* Stop match at wildcard (including preceding '-'). */
6270 if (end = strchr (charset, '*'))
6271 {
6272 if (end > charset && *(end-1) == '-')
6273 end--;
6274 *end = '\0';
6275 }
6276
6277 entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
6278 if (NILP (entry))
6279 return CP_UNKNOWN;
6280
6281 codepage = Fcdr (Fcdr (entry));
6282
6283 if (NILP (codepage))
6284 return CP_8BIT;
6285 else if (XFASTINT (codepage) == XFASTINT (Qt))
6286 return CP_UNICODE;
6287 else if (INTEGERP (codepage))
6288 return XINT (codepage);
6289 else
6290 return CP_UNKNOWN;
6291 }
6292
6293
6294 static BOOL
6295 w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
6296 LOGFONT * lplogfont;
6297 char * lpxstr;
6298 int len;
6299 char * specific_charset;
6300 {
6301 char* fonttype;
6302 char *fontname;
6303 char height_pixels[8];
6304 char height_dpi[8];
6305 char width_pixels[8];
6306 char *fontname_dash;
6307 int display_resy = one_w32_display_info.resy;
6308 int display_resx = one_w32_display_info.resx;
6309 int bufsz;
6310 struct coding_system coding;
6311
6312 if (!lpxstr) abort ();
6313
6314 if (!lplogfont)
6315 return FALSE;
6316
6317 if (lplogfont->lfOutPrecision == OUT_STRING_PRECIS)
6318 fonttype = "raster";
6319 else if (lplogfont->lfOutPrecision == OUT_STROKE_PRECIS)
6320 fonttype = "outline";
6321 else
6322 fonttype = "unknown";
6323
6324 setup_coding_system (Fcheck_coding_system (Vlocale_coding_system),
6325 &coding);
6326 coding.src_multibyte = 0;
6327 coding.dst_multibyte = 1;
6328 coding.mode |= CODING_MODE_LAST_BLOCK;
6329 bufsz = decoding_buffer_size (&coding, LF_FACESIZE);
6330
6331 fontname = alloca(sizeof(*fontname) * bufsz);
6332 decode_coding (&coding, lplogfont->lfFaceName, fontname,
6333 strlen(lplogfont->lfFaceName), bufsz - 1);
6334 *(fontname + coding.produced) = '\0';
6335
6336 /* Replace dashes with underscores so the dashes are not
6337 misinterpreted. */
6338 fontname_dash = fontname;
6339 while (fontname_dash = strchr (fontname_dash, '-'))
6340 *fontname_dash = '_';
6341
6342 if (lplogfont->lfHeight)
6343 {
6344 sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
6345 sprintf (height_dpi, "%u",
6346 abs (lplogfont->lfHeight) * 720 / display_resy);
6347 }
6348 else
6349 {
6350 strcpy (height_pixels, "*");
6351 strcpy (height_dpi, "*");
6352 }
6353 if (lplogfont->lfWidth)
6354 sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
6355 else
6356 strcpy (width_pixels, "*");
6357
6358 _snprintf (lpxstr, len - 1,
6359 "-%s-%s-%s-%c-normal-normal-%s-%s-%d-%d-%c-%s-%s",
6360 fonttype, /* foundry */
6361 fontname, /* family */
6362 w32_to_x_weight (lplogfont->lfWeight), /* weight */
6363 lplogfont->lfItalic?'i':'r', /* slant */
6364 /* setwidth name */
6365 /* add style name */
6366 height_pixels, /* pixel size */
6367 height_dpi, /* point size */
6368 display_resx, /* resx */
6369 display_resy, /* resy */
6370 ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH)
6371 ? 'p' : 'c', /* spacing */
6372 width_pixels, /* avg width */
6373 specific_charset ? specific_charset
6374 : w32_to_x_charset (lplogfont->lfCharSet)
6375 /* charset registry and encoding */
6376 );
6377
6378 lpxstr[len - 1] = 0; /* just to be sure */
6379 return (TRUE);
6380 }
6381
6382 static BOOL
6383 x_to_w32_font (lpxstr, lplogfont)
6384 char * lpxstr;
6385 LOGFONT * lplogfont;
6386 {
6387 struct coding_system coding;
6388
6389 if (!lplogfont) return (FALSE);
6390
6391 memset (lplogfont, 0, sizeof (*lplogfont));
6392
6393 /* Set default value for each field. */
6394 #if 1
6395 lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
6396 lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
6397 lplogfont->lfQuality = DEFAULT_QUALITY;
6398 #else
6399 /* go for maximum quality */
6400 lplogfont->lfOutPrecision = OUT_STROKE_PRECIS;
6401 lplogfont->lfClipPrecision = CLIP_STROKE_PRECIS;
6402 lplogfont->lfQuality = PROOF_QUALITY;
6403 #endif
6404
6405 lplogfont->lfCharSet = DEFAULT_CHARSET;
6406 lplogfont->lfWeight = FW_DONTCARE;
6407 lplogfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
6408
6409 if (!lpxstr)
6410 return FALSE;
6411
6412 /* Provide a simple escape mechanism for specifying Windows font names
6413 * directly -- if font spec does not beginning with '-', assume this
6414 * format:
6415 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
6416 */
6417
6418 if (*lpxstr == '-')
6419 {
6420 int fields, tem;
6421 char name[50], weight[20], slant, pitch, pixels[10], height[10],
6422 width[10], resy[10], remainder[50];
6423 char * encoding;
6424 int dpi = one_w32_display_info.resy;
6425
6426 fields = sscanf (lpxstr,
6427 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
6428 name, weight, &slant, pixels, height, resy, &pitch, width, remainder);
6429 if (fields == EOF)
6430 return (FALSE);
6431
6432 /* In the general case when wildcards cover more than one field,
6433 we don't know which field is which, so don't fill any in.
6434 However, we need to cope with this particular form, which is
6435 generated by font_list_1 (invoked by try_font_list):
6436 "-raster-6x10-*-gb2312*-*"
6437 and make sure to correctly parse the charset field. */
6438 if (fields == 3)
6439 {
6440 fields = sscanf (lpxstr,
6441 "-%*[^-]-%49[^-]-*-%49s",
6442 name, remainder);
6443 }
6444 else if (fields < 9)
6445 {
6446 fields = 0;
6447 remainder[0] = 0;
6448 }
6449
6450 if (fields > 0 && name[0] != '*')
6451 {
6452 int bufsize;
6453 unsigned char *buf;
6454
6455 setup_coding_system
6456 (Fcheck_coding_system (Vlocale_coding_system), &coding);
6457 coding.src_multibyte = 1;
6458 coding.dst_multibyte = 1;
6459 bufsize = encoding_buffer_size (&coding, strlen (name));
6460 buf = (unsigned char *) alloca (bufsize);
6461 coding.mode |= CODING_MODE_LAST_BLOCK;
6462 encode_coding (&coding, name, buf, strlen (name), bufsize);
6463 if (coding.produced >= LF_FACESIZE)
6464 coding.produced = LF_FACESIZE - 1;
6465 buf[coding.produced] = 0;
6466 strcpy (lplogfont->lfFaceName, buf);
6467 }
6468 else
6469 {
6470 lplogfont->lfFaceName[0] = '\0';
6471 }
6472
6473 fields--;
6474
6475 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
6476
6477 fields--;
6478
6479 lplogfont->lfItalic = (fields > 0 && slant == 'i');
6480
6481 fields--;
6482
6483 if (fields > 0 && pixels[0] != '*')
6484 lplogfont->lfHeight = atoi (pixels);
6485
6486 fields--;
6487 fields--;
6488 if (fields > 0 && resy[0] != '*')
6489 {
6490 tem = atoi (resy);
6491 if (tem > 0) dpi = tem;
6492 }
6493
6494 if (fields > -1 && lplogfont->lfHeight == 0 && height[0] != '*')
6495 lplogfont->lfHeight = atoi (height) * dpi / 720;
6496
6497 if (fields > 0)
6498 lplogfont->lfPitchAndFamily =
6499 (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
6500
6501 fields--;
6502
6503 if (fields > 0 && width[0] != '*')
6504 lplogfont->lfWidth = atoi (width) / 10;
6505
6506 fields--;
6507
6508 /* Strip the trailing '-' if present. (it shouldn't be, as it
6509 fails the test against xlfd-tight-regexp in fontset.el). */
6510 {
6511 int len = strlen (remainder);
6512 if (len > 0 && remainder[len-1] == '-')
6513 remainder[len-1] = 0;
6514 }
6515 encoding = remainder;
6516 #if 0
6517 if (strncmp (encoding, "*-", 2) == 0)
6518 encoding += 2;
6519 #endif
6520 lplogfont->lfCharSet = x_to_w32_charset (encoding);
6521 }
6522 else
6523 {
6524 int fields;
6525 char name[100], height[10], width[10], weight[20];
6526
6527 fields = sscanf (lpxstr,
6528 "%99[^:]:%9[^:]:%9[^:]:%19s",
6529 name, height, width, weight);
6530
6531 if (fields == EOF) return (FALSE);
6532
6533 if (fields > 0)
6534 {
6535 strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
6536 lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
6537 }
6538 else
6539 {
6540 lplogfont->lfFaceName[0] = 0;
6541 }
6542
6543 fields--;
6544
6545 if (fields > 0)
6546 lplogfont->lfHeight = atoi (height);
6547
6548 fields--;
6549
6550 if (fields > 0)
6551 lplogfont->lfWidth = atoi (width);
6552
6553 fields--;
6554
6555 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
6556 }
6557
6558 /* This makes TrueType fonts work better. */
6559 lplogfont->lfHeight = - abs (lplogfont->lfHeight);
6560
6561 return (TRUE);
6562 }
6563
6564 /* Strip the pixel height and point height from the given xlfd, and
6565 return the pixel height. If no pixel height is specified, calculate
6566 one from the point height, or if that isn't defined either, return
6567 0 (which usually signifies a scalable font).
6568 */
6569 static int
6570 xlfd_strip_height (char *fontname)
6571 {
6572 int pixel_height, field_number;
6573 char *read_from, *write_to;
6574
6575 xassert (fontname);
6576
6577 pixel_height = field_number = 0;
6578 write_to = NULL;
6579
6580 /* Look for height fields. */
6581 for (read_from = fontname; *read_from; read_from++)
6582 {
6583 if (*read_from == '-')
6584 {
6585 field_number++;
6586 if (field_number == 7) /* Pixel height. */
6587 {
6588 read_from++;
6589 write_to = read_from;
6590
6591 /* Find end of field. */
6592 for (;*read_from && *read_from != '-'; read_from++)
6593 ;
6594
6595 /* Split the fontname at end of field. */
6596 if (*read_from)
6597 {
6598 *read_from = '\0';
6599 read_from++;
6600 }
6601 pixel_height = atoi (write_to);
6602 /* Blank out field. */
6603 if (read_from > write_to)
6604 {
6605 *write_to = '-';
6606 write_to++;
6607 }
6608 /* If the pixel height field is at the end (partial xlfd),
6609 return now. */
6610 else
6611 return pixel_height;
6612
6613 /* If we got a pixel height, the point height can be
6614 ignored. Just blank it out and break now. */
6615 if (pixel_height)
6616 {
6617 /* Find end of point size field. */
6618 for (; *read_from && *read_from != '-'; read_from++)
6619 ;
6620
6621 if (*read_from)
6622 read_from++;
6623
6624 /* Blank out the point size field. */
6625 if (read_from > write_to)
6626 {
6627 *write_to = '-';
6628 write_to++;
6629 }
6630 else
6631 return pixel_height;
6632
6633 break;
6634 }
6635 /* If the point height is already blank, break now. */
6636 if (*read_from == '-')
6637 {
6638 read_from++;
6639 break;
6640 }
6641 }
6642 else if (field_number == 8)
6643 {
6644 /* If we didn't get a pixel height, try to get the point
6645 height and convert that. */
6646 int point_size;
6647 char *point_size_start = read_from++;
6648
6649 /* Find end of field. */
6650 for (; *read_from && *read_from != '-'; read_from++)
6651 ;
6652
6653 if (*read_from)
6654 {
6655 *read_from = '\0';
6656 read_from++;
6657 }
6658
6659 point_size = atoi (point_size_start);
6660
6661 /* Convert to pixel height. */
6662 pixel_height = point_size
6663 * one_w32_display_info.height_in / 720;
6664
6665 /* Blank out this field and break. */
6666 *write_to = '-';
6667 write_to++;
6668 break;
6669 }
6670 }
6671 }
6672
6673 /* Shift the rest of the font spec into place. */
6674 if (write_to && read_from > write_to)
6675 {
6676 for (; *read_from; read_from++, write_to++)
6677 *write_to = *read_from;
6678 *write_to = '\0';
6679 }
6680
6681 return pixel_height;
6682 }
6683
6684 /* Assume parameter 1 is fully qualified, no wildcards. */
6685 static BOOL
6686 w32_font_match (fontname, pattern)
6687 char * fontname;
6688 char * pattern;
6689 {
6690 char *regex = alloca (strlen (pattern) * 2 + 3);
6691 char *font_name_copy = alloca (strlen (fontname) + 1);
6692 char *ptr;
6693
6694 /* Copy fontname so we can modify it during comparison. */
6695 strcpy (font_name_copy, fontname);
6696
6697 ptr = regex;
6698 *ptr++ = '^';
6699
6700 /* Turn pattern into a regexp and do a regexp match. */
6701 for (; *pattern; pattern++)
6702 {
6703 if (*pattern == '?')
6704 *ptr++ = '.';
6705 else if (*pattern == '*')
6706 {
6707 *ptr++ = '.';
6708 *ptr++ = '*';
6709 }
6710 else
6711 *ptr++ = *pattern;
6712 }
6713 *ptr = '$';
6714 *(ptr + 1) = '\0';
6715
6716 /* Strip out font heights and compare them seperately, since
6717 rounding error can cause mismatches. This also allows a
6718 comparison between a font that declares only a pixel height and a
6719 pattern that declares the point height.
6720 */
6721 {
6722 int font_height, pattern_height;
6723
6724 font_height = xlfd_strip_height (font_name_copy);
6725 pattern_height = xlfd_strip_height (regex);
6726
6727 /* Compare now, and don't bother doing expensive regexp matching
6728 if the heights differ. */
6729 if (font_height && pattern_height && (font_height != pattern_height))
6730 return FALSE;
6731 }
6732
6733 return (fast_c_string_match_ignore_case (build_string (regex),
6734 font_name_copy) >= 0);
6735 }
6736
6737 /* Callback functions, and a structure holding info they need, for
6738 listing system fonts on W32. We need one set of functions to do the
6739 job properly, but these don't work on NT 3.51 and earlier, so we
6740 have a second set which don't handle character sets properly to
6741 fall back on.
6742
6743 In both cases, there are two passes made. The first pass gets one
6744 font from each family, the second pass lists all the fonts from
6745 each family. */
6746
6747 typedef struct enumfont_t
6748 {
6749 HDC hdc;
6750 int numFonts;
6751 LOGFONT logfont;
6752 XFontStruct *size_ref;
6753 Lisp_Object *pattern;
6754 Lisp_Object *tail;
6755 } enumfont_t;
6756
6757 static int CALLBACK
6758 enum_font_cb2 (lplf, lptm, FontType, lpef)
6759 ENUMLOGFONT * lplf;
6760 NEWTEXTMETRIC * lptm;
6761 int FontType;
6762 enumfont_t * lpef;
6763 {
6764 /* Ignore struck out and underlined versions of fonts. */
6765 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline)
6766 return 1;
6767
6768 /* Only return fonts with names starting with @ if they were
6769 explicitly specified, since Microsoft uses an initial @ to
6770 denote fonts for vertical writing, without providing a more
6771 convenient way of identifying them. */
6772 if (lplf->elfLogFont.lfFaceName[0] == '@'
6773 && lpef->logfont.lfFaceName[0] != '@')
6774 return 1;
6775
6776 /* Check that the character set matches if it was specified */
6777 if (lpef->logfont.lfCharSet != DEFAULT_CHARSET &&
6778 lplf->elfLogFont.lfCharSet != lpef->logfont.lfCharSet)
6779 return 1;
6780
6781 {
6782 char buf[100];
6783 Lisp_Object width = Qnil;
6784 char *charset = NULL;
6785
6786 /* Truetype fonts do not report their true metrics until loaded */
6787 if (FontType != RASTER_FONTTYPE)
6788 {
6789 if (!NILP (*(lpef->pattern)))
6790 {
6791 /* Scalable fonts are as big as you want them to be. */
6792 lplf->elfLogFont.lfHeight = lpef->logfont.lfHeight;
6793 lplf->elfLogFont.lfWidth = lpef->logfont.lfWidth;
6794 width = make_number (lpef->logfont.lfWidth);
6795 }
6796 else
6797 {
6798 lplf->elfLogFont.lfHeight = 0;
6799 lplf->elfLogFont.lfWidth = 0;
6800 }
6801 }
6802
6803 /* Make sure the height used here is the same as everywhere
6804 else (ie character height, not cell height). */
6805 if (lplf->elfLogFont.lfHeight > 0)
6806 {
6807 /* lptm can be trusted for RASTER fonts, but not scalable ones. */
6808 if (FontType == RASTER_FONTTYPE)
6809 lplf->elfLogFont.lfHeight = lptm->tmInternalLeading - lptm->tmHeight;
6810 else
6811 lplf->elfLogFont.lfHeight = -lplf->elfLogFont.lfHeight;
6812 }
6813
6814 if (!NILP (*(lpef->pattern)))
6815 {
6816 charset = xlfd_charset_of_font (XSTRING(*(lpef->pattern))->data);
6817
6818 /* Ensure that charset is valid for this font. */
6819 if (charset
6820 && (x_to_w32_charset (charset) != lplf->elfLogFont.lfCharSet))
6821 charset = NULL;
6822 }
6823
6824 /* TODO: List all relevant charsets if charset not specified. */
6825 if (!w32_to_x_font (&(lplf->elfLogFont), buf, 100, charset))
6826 return 1;
6827
6828 if (NILP (*(lpef->pattern))
6829 || w32_font_match (buf, XSTRING (*(lpef->pattern))->data))
6830 {
6831 *lpef->tail = Fcons (Fcons (build_string (buf), width), Qnil);
6832 lpef->tail = &(XCDR (*lpef->tail));
6833 lpef->numFonts++;
6834 }
6835 }
6836
6837 return 1;
6838 }
6839
6840 static int CALLBACK
6841 enum_font_cb1 (lplf, lptm, FontType, lpef)
6842 ENUMLOGFONT * lplf;
6843 NEWTEXTMETRIC * lptm;
6844 int FontType;
6845 enumfont_t * lpef;
6846 {
6847 return EnumFontFamilies (lpef->hdc,
6848 lplf->elfLogFont.lfFaceName,
6849 (FONTENUMPROC) enum_font_cb2,
6850 (LPARAM) lpef);
6851 }
6852
6853
6854 static int CALLBACK
6855 enum_fontex_cb2 (lplf, lptm, font_type, lpef)
6856 ENUMLOGFONTEX * lplf;
6857 NEWTEXTMETRICEX * lptm;
6858 int font_type;
6859 enumfont_t * lpef;
6860 {
6861 /* We are not interested in the extra info we get back from the 'Ex
6862 version - only the fact that we get character set variations
6863 enumerated seperately. */
6864 return enum_font_cb2 ((ENUMLOGFONT *) lplf, (NEWTEXTMETRIC *) lptm,
6865 font_type, lpef);
6866 }
6867
6868 static int CALLBACK
6869 enum_fontex_cb1 (lplf, lptm, font_type, lpef)
6870 ENUMLOGFONTEX * lplf;
6871 NEWTEXTMETRICEX * lptm;
6872 int font_type;
6873 enumfont_t * lpef;
6874 {
6875 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
6876 FARPROC enum_font_families_ex
6877 = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
6878 /* We don't really expect EnumFontFamiliesEx to disappear once we
6879 get here, so don't bother handling it gracefully. */
6880 if (enum_font_families_ex == NULL)
6881 error ("gdi32.dll has disappeared!");
6882 return enum_font_families_ex (lpef->hdc,
6883 &lplf->elfLogFont,
6884 (FONTENUMPROC) enum_fontex_cb2,
6885 (LPARAM) lpef, 0);
6886 }
6887
6888 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
6889 and xterm.c in Emacs 20.3) */
6890
6891 static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names)
6892 {
6893 char *fontname, *ptnstr;
6894 Lisp_Object list, tem, newlist = Qnil;
6895 int n_fonts = 0;
6896
6897 list = Vw32_bdf_filename_alist;
6898 ptnstr = XSTRING (pattern)->data;
6899
6900 for ( ; CONSP (list); list = XCDR (list))
6901 {
6902 tem = XCAR (list);
6903 if (CONSP (tem))
6904 fontname = XSTRING (XCAR (tem))->data;
6905 else if (STRINGP (tem))
6906 fontname = XSTRING (tem)->data;
6907 else
6908 continue;
6909
6910 if (w32_font_match (fontname, ptnstr))
6911 {
6912 newlist = Fcons (XCAR (tem), newlist);
6913 n_fonts++;
6914 if (n_fonts >= max_names)
6915 break;
6916 }
6917 }
6918
6919 return newlist;
6920 }
6921
6922 static Lisp_Object w32_list_synthesized_fonts (FRAME_PTR f,
6923 Lisp_Object pattern,
6924 int size, int max_names);
6925
6926 /* Return a list of names of available fonts matching PATTERN on frame
6927 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6928 to be listed. Frame F NULL means we have not yet created any
6929 frame, which means we can't get proper size info, as we don't have
6930 a device context to use for GetTextMetrics.
6931 MAXNAMES sets a limit on how many fonts to match. */
6932
6933 Lisp_Object
6934 w32_list_fonts (f, pattern, size, maxnames)
6935 struct frame *f;
6936 Lisp_Object pattern;
6937 int size;
6938 int maxnames;
6939 {
6940 Lisp_Object patterns, key = Qnil, tem, tpat;
6941 Lisp_Object list = Qnil, newlist = Qnil, second_best = Qnil;
6942 struct w32_display_info *dpyinfo = &one_w32_display_info;
6943 int n_fonts = 0;
6944
6945 patterns = Fassoc (pattern, Valternate_fontname_alist);
6946 if (NILP (patterns))
6947 patterns = Fcons (pattern, Qnil);
6948
6949 for (; CONSP (patterns); patterns = XCDR (patterns))
6950 {
6951 enumfont_t ef;
6952 int codepage;
6953
6954 tpat = XCAR (patterns);
6955
6956 if (!STRINGP (tpat))
6957 continue;
6958
6959 /* Avoid expensive EnumFontFamilies functions if we are not
6960 going to be able to output one of these anyway. */
6961 codepage = w32_codepage_for_font (XSTRING (tpat)->data);
6962 if (codepage != CP_8BIT && codepage != CP_UNICODE
6963 && codepage != CP_DEFAULT && codepage != CP_UNKNOWN
6964 && !IsValidCodePage(codepage))
6965 continue;
6966
6967 /* See if we cached the result for this particular query.
6968 The cache is an alist of the form:
6969 ((PATTERN (FONTNAME . WIDTH) ...) ...)
6970 */
6971 if (tem = XCDR (dpyinfo->name_list_element),
6972 !NILP (list = Fassoc (tpat, tem)))
6973 {
6974 list = Fcdr_safe (list);
6975 /* We have a cached list. Don't have to get the list again. */
6976 goto label_cached;
6977 }
6978
6979 BLOCK_INPUT;
6980 /* At first, put PATTERN in the cache. */
6981 list = Qnil;
6982 ef.pattern = &tpat;
6983 ef.tail = &list;
6984 ef.numFonts = 0;
6985
6986 /* Use EnumFontFamiliesEx where it is available, as it knows
6987 about character sets. Fall back to EnumFontFamilies for
6988 older versions of NT that don't support the 'Ex function. */
6989 x_to_w32_font (XSTRING (tpat)->data, &ef.logfont);
6990 {
6991 LOGFONT font_match_pattern;
6992 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
6993 FARPROC enum_font_families_ex
6994 = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
6995
6996 /* We do our own pattern matching so we can handle wildcards. */
6997 font_match_pattern.lfFaceName[0] = 0;
6998 font_match_pattern.lfPitchAndFamily = 0;
6999 /* We can use the charset, because if it is a wildcard it will
7000 be DEFAULT_CHARSET anyway. */
7001 font_match_pattern.lfCharSet = ef.logfont.lfCharSet;
7002
7003 ef.hdc = GetDC (dpyinfo->root_window);
7004
7005 if (enum_font_families_ex)
7006 enum_font_families_ex (ef.hdc,
7007 &font_match_pattern,
7008 (FONTENUMPROC) enum_fontex_cb1,
7009 (LPARAM) &ef, 0);
7010 else
7011 EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1,
7012 (LPARAM)&ef);
7013
7014 ReleaseDC (dpyinfo->root_window, ef.hdc);
7015 }
7016
7017 UNBLOCK_INPUT;
7018
7019 /* Make a list of the fonts we got back.
7020 Store that in the font cache for the display. */
7021 XSETCDR (dpyinfo->name_list_element,
7022 Fcons (Fcons (tpat, list),
7023 XCDR (dpyinfo->name_list_element)));
7024
7025 label_cached:
7026 if (NILP (list)) continue; /* Try the remaining alternatives. */
7027
7028 newlist = second_best = Qnil;
7029
7030 /* Make a list of the fonts that have the right width. */
7031 for (; CONSP (list); list = XCDR (list))
7032 {
7033 int found_size;
7034 tem = XCAR (list);
7035
7036 if (!CONSP (tem))
7037 continue;
7038 if (NILP (XCAR (tem)))
7039 continue;
7040 if (!size)
7041 {
7042 newlist = Fcons (XCAR (tem), newlist);
7043 n_fonts++;
7044 if (n_fonts >= maxnames)
7045 break;
7046 else
7047 continue;
7048 }
7049 if (!INTEGERP (XCDR (tem)))
7050 {
7051 /* Since we don't yet know the size of the font, we must
7052 load it and try GetTextMetrics. */
7053 W32FontStruct thisinfo;
7054 LOGFONT lf;
7055 HDC hdc;
7056 HANDLE oldobj;
7057
7058 if (!x_to_w32_font (XSTRING (XCAR (tem))->data, &lf))
7059 continue;
7060
7061 BLOCK_INPUT;
7062 thisinfo.bdf = NULL;
7063 thisinfo.hfont = CreateFontIndirect (&lf);
7064 if (thisinfo.hfont == NULL)
7065 continue;
7066
7067 hdc = GetDC (dpyinfo->root_window);
7068 oldobj = SelectObject (hdc, thisinfo.hfont);
7069 if (GetTextMetrics (hdc, &thisinfo.tm))
7070 XSETCDR (tem, make_number (FONT_WIDTH (&thisinfo)));
7071 else
7072 XSETCDR (tem, make_number (0));
7073 SelectObject (hdc, oldobj);
7074 ReleaseDC (dpyinfo->root_window, hdc);
7075 DeleteObject(thisinfo.hfont);
7076 UNBLOCK_INPUT;
7077 }
7078 found_size = XINT (XCDR (tem));
7079 if (found_size == size)
7080 {
7081 newlist = Fcons (XCAR (tem), newlist);
7082 n_fonts++;
7083 if (n_fonts >= maxnames)
7084 break;
7085 }
7086 /* keep track of the closest matching size in case
7087 no exact match is found. */
7088 else if (found_size > 0)
7089 {
7090 if (NILP (second_best))
7091 second_best = tem;
7092
7093 else if (found_size < size)
7094 {
7095 if (XINT (XCDR (second_best)) > size
7096 || XINT (XCDR (second_best)) < found_size)
7097 second_best = tem;
7098 }
7099 else
7100 {
7101 if (XINT (XCDR (second_best)) > size
7102 && XINT (XCDR (second_best)) >
7103 found_size)
7104 second_best = tem;
7105 }
7106 }
7107 }
7108
7109 if (!NILP (newlist))
7110 break;
7111 else if (!NILP (second_best))
7112 {
7113 newlist = Fcons (XCAR (second_best), Qnil);
7114 break;
7115 }
7116 }
7117
7118 /* Include any bdf fonts. */
7119 if (n_fonts < maxnames)
7120 {
7121 Lisp_Object combined[2];
7122 combined[0] = w32_list_bdf_fonts (pattern, maxnames - n_fonts);
7123 combined[1] = newlist;
7124 newlist = Fnconc(2, combined);
7125 }
7126
7127 /* If we can't find a font that matches, check if Windows would be
7128 able to synthesize it from a different style. */
7129 if (NILP (newlist) && !NILP (Vw32_enable_synthesized_fonts))
7130 newlist = w32_list_synthesized_fonts (f, pattern, size, maxnames);
7131
7132 return newlist;
7133 }
7134
7135 static Lisp_Object
7136 w32_list_synthesized_fonts (f, pattern, size, max_names)
7137 FRAME_PTR f;
7138 Lisp_Object pattern;
7139 int size;
7140 int max_names;
7141 {
7142 int fields;
7143 char *full_pattn, *new_pattn, foundary[50], family[50], *pattn_part2;
7144 char style[20], slant;
7145 Lisp_Object matches, tem, synthed_matches = Qnil;
7146
7147 full_pattn = XSTRING (pattern)->data;
7148
7149 pattn_part2 = alloca (XSTRING (pattern)->size + 1);
7150 /* Allow some space for wildcard expansion. */
7151 new_pattn = alloca (XSTRING (pattern)->size + 100);
7152
7153 fields = sscanf (full_pattn, "-%49[^-]-%49[^-]-%19[^-]-%c-%s",
7154 foundary, family, style, &slant, pattn_part2);
7155 if (fields == EOF || fields < 5)
7156 return Qnil;
7157
7158 /* If the style and slant are wildcards already there is no point
7159 checking again (and we don't want to keep recursing). */
7160 if (*style == '*' && slant == '*')
7161 return Qnil;
7162
7163 sprintf (new_pattn, "-%s-%s-*-*-%s", foundary, family, pattn_part2);
7164
7165 matches = w32_list_fonts (f, build_string (new_pattn), size, max_names);
7166
7167 for ( ; CONSP (matches); matches = XCDR (matches))
7168 {
7169 tem = XCAR (matches);
7170 if (!STRINGP (tem))
7171 continue;
7172
7173 full_pattn = XSTRING (tem)->data;
7174 fields = sscanf (full_pattn, "-%49[^-]-%49[^-]-%*[^-]-%*c-%s",
7175 foundary, family, pattn_part2);
7176 if (fields == EOF || fields < 3)
7177 continue;
7178
7179 sprintf (new_pattn, "-%s-%s-%s-%c-%s", foundary, family, style,
7180 slant, pattn_part2);
7181
7182 synthed_matches = Fcons (build_string (new_pattn),
7183 synthed_matches);
7184 }
7185
7186 return synthed_matches;
7187 }
7188
7189
7190 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7191 struct font_info *
7192 w32_get_font_info (f, font_idx)
7193 FRAME_PTR f;
7194 int font_idx;
7195 {
7196 return (FRAME_W32_FONT_TABLE (f) + font_idx);
7197 }
7198
7199
7200 struct font_info*
7201 w32_query_font (struct frame *f, char *fontname)
7202 {
7203 int i;
7204 struct font_info *pfi;
7205
7206 pfi = FRAME_W32_FONT_TABLE (f);
7207
7208 for (i = 0; i < one_w32_display_info.n_fonts ;i++, pfi++)
7209 {
7210 if (strcmp(pfi->name, fontname) == 0) return pfi;
7211 }
7212
7213 return NULL;
7214 }
7215
7216 /* Find a CCL program for a font specified by FONTP, and set the member
7217 `encoder' of the structure. */
7218
7219 void
7220 w32_find_ccl_program (fontp)
7221 struct font_info *fontp;
7222 {
7223 Lisp_Object list, elt;
7224
7225 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7226 {
7227 elt = XCAR (list);
7228 if (CONSP (elt)
7229 && STRINGP (XCAR (elt))
7230 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7231 >= 0))
7232 break;
7233 }
7234 if (! NILP (list))
7235 {
7236 struct ccl_program *ccl
7237 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7238
7239 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7240 xfree (ccl);
7241 else
7242 fontp->font_encoder = ccl;
7243 }
7244 }
7245
7246 \f
7247 /* Find BDF files in a specified directory. (use GCPRO when calling,
7248 as this calls lisp to get a directory listing). */
7249 static Lisp_Object
7250 w32_find_bdf_fonts_in_dir (Lisp_Object directory)
7251 {
7252 Lisp_Object filelist, list = Qnil;
7253 char fontname[100];
7254
7255 if (!STRINGP(directory))
7256 return Qnil;
7257
7258 filelist = Fdirectory_files (directory, Qt,
7259 build_string (".*\\.[bB][dD][fF]"), Qt);
7260
7261 for ( ; CONSP(filelist); filelist = XCDR (filelist))
7262 {
7263 Lisp_Object filename = XCAR (filelist);
7264 if (w32_BDF_to_x_font (XSTRING (filename)->data, fontname, 100))
7265 store_in_alist (&list, build_string (fontname), filename);
7266 }
7267 return list;
7268 }
7269
7270 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts, Sw32_find_bdf_fonts,
7271 1, 1, 0,
7272 doc: /* Return a list of BDF fonts in DIR.
7273 The list is suitable for appending to w32-bdf-filename-alist. Fonts
7274 which do not contain an xlfd description will not be included in the
7275 list. DIR may be a list of directories. */)
7276 (directory)
7277 Lisp_Object directory;
7278 {
7279 Lisp_Object list = Qnil;
7280 struct gcpro gcpro1, gcpro2;
7281
7282 if (!CONSP (directory))
7283 return w32_find_bdf_fonts_in_dir (directory);
7284
7285 for ( ; CONSP (directory); directory = XCDR (directory))
7286 {
7287 Lisp_Object pair[2];
7288 pair[0] = list;
7289 pair[1] = Qnil;
7290 GCPRO2 (directory, list);
7291 pair[1] = w32_find_bdf_fonts_in_dir( XCAR (directory) );
7292 list = Fnconc( 2, pair );
7293 UNGCPRO;
7294 }
7295 return list;
7296 }
7297
7298 \f
7299 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
7300 doc: /* Internal function called by `color-defined-p', which see. */)
7301 (color, frame)
7302 Lisp_Object color, frame;
7303 {
7304 XColor foo;
7305 FRAME_PTR f = check_x_frame (frame);
7306
7307 CHECK_STRING (color);
7308
7309 if (w32_defined_color (f, XSTRING (color)->data, &foo, 0))
7310 return Qt;
7311 else
7312 return Qnil;
7313 }
7314
7315 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
7316 doc: /* Internal function called by `color-values', which see. */)
7317 (color, frame)
7318 Lisp_Object color, frame;
7319 {
7320 XColor foo;
7321 FRAME_PTR f = check_x_frame (frame);
7322
7323 CHECK_STRING (color);
7324
7325 if (w32_defined_color (f, XSTRING (color)->data, &foo, 0))
7326 {
7327 Lisp_Object rgb[3];
7328
7329 rgb[0] = make_number ((GetRValue (foo.pixel) << 8)
7330 | GetRValue (foo.pixel));
7331 rgb[1] = make_number ((GetGValue (foo.pixel) << 8)
7332 | GetGValue (foo.pixel));
7333 rgb[2] = make_number ((GetBValue (foo.pixel) << 8)
7334 | GetBValue (foo.pixel));
7335 return Flist (3, rgb);
7336 }
7337 else
7338 return Qnil;
7339 }
7340
7341 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
7342 doc: /* Internal function called by `display-color-p', which see. */)
7343 (display)
7344 Lisp_Object display;
7345 {
7346 struct w32_display_info *dpyinfo = check_x_display_info (display);
7347
7348 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
7349 return Qnil;
7350
7351 return Qt;
7352 }
7353
7354 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
7355 Sx_display_grayscale_p, 0, 1, 0,
7356 doc: /* Return t if the X display supports shades of gray.
7357 Note that color displays do support shades of gray.
7358 The optional argument DISPLAY specifies which display to ask about.
7359 DISPLAY should be either a frame or a display name (a string).
7360 If omitted or nil, that stands for the selected frame's display. */)
7361 (display)
7362 Lisp_Object display;
7363 {
7364 struct w32_display_info *dpyinfo = check_x_display_info (display);
7365
7366 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
7367 return Qnil;
7368
7369 return Qt;
7370 }
7371
7372 DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
7373 Sx_display_pixel_width, 0, 1, 0,
7374 doc: /* Returns the width in pixels of DISPLAY.
7375 The optional argument DISPLAY specifies which display to ask about.
7376 DISPLAY should be either a frame or a display name (a string).
7377 If omitted or nil, that stands for the selected frame's display. */)
7378 (display)
7379 Lisp_Object display;
7380 {
7381 struct w32_display_info *dpyinfo = check_x_display_info (display);
7382
7383 return make_number (dpyinfo->width);
7384 }
7385
7386 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
7387 Sx_display_pixel_height, 0, 1, 0,
7388 doc: /* Returns the height in pixels of DISPLAY.
7389 The optional argument DISPLAY specifies which display to ask about.
7390 DISPLAY should be either a frame or a display name (a string).
7391 If omitted or nil, that stands for the selected frame's display. */)
7392 (display)
7393 Lisp_Object display;
7394 {
7395 struct w32_display_info *dpyinfo = check_x_display_info (display);
7396
7397 return make_number (dpyinfo->height);
7398 }
7399
7400 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
7401 0, 1, 0,
7402 doc: /* Returns the number of bitplanes of DISPLAY.
7403 The optional argument DISPLAY specifies which display to ask about.
7404 DISPLAY should be either a frame or a display name (a string).
7405 If omitted or nil, that stands for the selected frame's display. */)
7406 (display)
7407 Lisp_Object display;
7408 {
7409 struct w32_display_info *dpyinfo = check_x_display_info (display);
7410
7411 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
7412 }
7413
7414 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
7415 0, 1, 0,
7416 doc: /* Returns the number of color cells of DISPLAY.
7417 The optional argument DISPLAY specifies which display to ask about.
7418 DISPLAY should be either a frame or a display name (a string).
7419 If omitted or nil, that stands for the selected frame's display. */)
7420 (display)
7421 Lisp_Object display;
7422 {
7423 struct w32_display_info *dpyinfo = check_x_display_info (display);
7424 HDC hdc;
7425 int cap;
7426
7427 hdc = GetDC (dpyinfo->root_window);
7428 if (dpyinfo->has_palette)
7429 cap = GetDeviceCaps (hdc,SIZEPALETTE);
7430 else
7431 cap = GetDeviceCaps (hdc,NUMCOLORS);
7432
7433 if (cap < 0)
7434 cap = 1 << (dpyinfo->n_planes * dpyinfo->n_cbits);
7435
7436 ReleaseDC (dpyinfo->root_window, hdc);
7437
7438 return make_number (cap);
7439 }
7440
7441 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
7442 Sx_server_max_request_size,
7443 0, 1, 0,
7444 doc: /* Returns the maximum request size of the server of DISPLAY.
7445 The optional argument DISPLAY specifies which display to ask about.
7446 DISPLAY should be either a frame or a display name (a string).
7447 If omitted or nil, that stands for the selected frame's display. */)
7448 (display)
7449 Lisp_Object display;
7450 {
7451 struct w32_display_info *dpyinfo = check_x_display_info (display);
7452
7453 return make_number (1);
7454 }
7455
7456 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
7457 doc: /* Returns the vendor ID string of the W32 system (Microsoft).
7458 The optional argument DISPLAY specifies which display to ask about.
7459 DISPLAY should be either a frame or a display name (a string).
7460 If omitted or nil, that stands for the selected frame's display. */)
7461 (display)
7462 Lisp_Object display;
7463 {
7464 return build_string ("Microsoft Corp.");
7465 }
7466
7467 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
7468 doc: /* Returns the version numbers of the server of DISPLAY.
7469 The value is a list of three integers: the major and minor
7470 version numbers, and the vendor-specific release
7471 number. See also the function `x-server-vendor'.
7472
7473 The optional argument DISPLAY specifies which display to ask about.
7474 DISPLAY should be either a frame or a display name (a string).
7475 If omitted or nil, that stands for the selected frame's display. */)
7476 (display)
7477 Lisp_Object display;
7478 {
7479 return Fcons (make_number (w32_major_version),
7480 Fcons (make_number (w32_minor_version),
7481 Fcons (make_number (w32_build_number), Qnil)));
7482 }
7483
7484 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
7485 doc: /* Returns the number of screens on the server of DISPLAY.
7486 The optional argument DISPLAY specifies which display to ask about.
7487 DISPLAY should be either a frame or a display name (a string).
7488 If omitted or nil, that stands for the selected frame's display. */)
7489 (display)
7490 Lisp_Object display;
7491 {
7492 return make_number (1);
7493 }
7494
7495 DEFUN ("x-display-mm-height", Fx_display_mm_height,
7496 Sx_display_mm_height, 0, 1, 0,
7497 doc: /* Returns the height in millimeters of DISPLAY.
7498 The optional argument DISPLAY specifies which display to ask about.
7499 DISPLAY should be either a frame or a display name (a string).
7500 If omitted or nil, that stands for the selected frame's display. */)
7501 (display)
7502 Lisp_Object display;
7503 {
7504 struct w32_display_info *dpyinfo = check_x_display_info (display);
7505 HDC hdc;
7506 int cap;
7507
7508 hdc = GetDC (dpyinfo->root_window);
7509
7510 cap = GetDeviceCaps (hdc, VERTSIZE);
7511
7512 ReleaseDC (dpyinfo->root_window, hdc);
7513
7514 return make_number (cap);
7515 }
7516
7517 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
7518 doc: /* Returns the width in millimeters of DISPLAY.
7519 The optional argument DISPLAY specifies which display to ask about.
7520 DISPLAY should be either a frame or a display name (a string).
7521 If omitted or nil, that stands for the selected frame's display. */)
7522 (display)
7523 Lisp_Object display;
7524 {
7525 struct w32_display_info *dpyinfo = check_x_display_info (display);
7526
7527 HDC hdc;
7528 int cap;
7529
7530 hdc = GetDC (dpyinfo->root_window);
7531
7532 cap = GetDeviceCaps (hdc, HORZSIZE);
7533
7534 ReleaseDC (dpyinfo->root_window, hdc);
7535
7536 return make_number (cap);
7537 }
7538
7539 DEFUN ("x-display-backing-store", Fx_display_backing_store,
7540 Sx_display_backing_store, 0, 1, 0,
7541 doc: /* Returns an indication of whether DISPLAY does backing store.
7542 The value may be `always', `when-mapped', or `not-useful'.
7543 The optional argument DISPLAY specifies which display to ask about.
7544 DISPLAY should be either a frame or a display name (a string).
7545 If omitted or nil, that stands for the selected frame's display. */)
7546 (display)
7547 Lisp_Object display;
7548 {
7549 return intern ("not-useful");
7550 }
7551
7552 DEFUN ("x-display-visual-class", Fx_display_visual_class,
7553 Sx_display_visual_class, 0, 1, 0,
7554 doc: /* Returns the visual class of DISPLAY.
7555 The value is one of the symbols `static-gray', `gray-scale',
7556 `static-color', `pseudo-color', `true-color', or `direct-color'.
7557
7558 The optional argument DISPLAY specifies which display to ask about.
7559 DISPLAY should be either a frame or a display name (a string).
7560 If omitted or nil, that stands for the selected frame's display. */)
7561 (display)
7562 Lisp_Object display;
7563 {
7564 struct w32_display_info *dpyinfo = check_x_display_info (display);
7565 Lisp_Object result = Qnil;
7566
7567 if (dpyinfo->has_palette)
7568 result = intern ("pseudo-color");
7569 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 1)
7570 result = intern ("static-grey");
7571 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 4)
7572 result = intern ("static-color");
7573 else if (dpyinfo->n_planes * dpyinfo->n_cbits > 8)
7574 result = intern ("true-color");
7575
7576 return result;
7577 }
7578
7579 DEFUN ("x-display-save-under", Fx_display_save_under,
7580 Sx_display_save_under, 0, 1, 0,
7581 doc: /* Returns t if DISPLAY supports the save-under feature.
7582 The optional argument DISPLAY specifies which display to ask about.
7583 DISPLAY should be either a frame or a display name (a string).
7584 If omitted or nil, that stands for the selected frame's display. */)
7585 (display)
7586 Lisp_Object display;
7587 {
7588 return Qnil;
7589 }
7590 \f
7591 int
7592 x_pixel_width (f)
7593 register struct frame *f;
7594 {
7595 return PIXEL_WIDTH (f);
7596 }
7597
7598 int
7599 x_pixel_height (f)
7600 register struct frame *f;
7601 {
7602 return PIXEL_HEIGHT (f);
7603 }
7604
7605 int
7606 x_char_width (f)
7607 register struct frame *f;
7608 {
7609 return FONT_WIDTH (f->output_data.w32->font);
7610 }
7611
7612 int
7613 x_char_height (f)
7614 register struct frame *f;
7615 {
7616 return f->output_data.w32->line_height;
7617 }
7618
7619 int
7620 x_screen_planes (f)
7621 register struct frame *f;
7622 {
7623 return FRAME_W32_DISPLAY_INFO (f)->n_planes;
7624 }
7625 \f
7626 /* Return the display structure for the display named NAME.
7627 Open a new connection if necessary. */
7628
7629 struct w32_display_info *
7630 x_display_info_for_name (name)
7631 Lisp_Object name;
7632 {
7633 Lisp_Object names;
7634 struct w32_display_info *dpyinfo;
7635
7636 CHECK_STRING (name);
7637
7638 for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
7639 dpyinfo;
7640 dpyinfo = dpyinfo->next, names = XCDR (names))
7641 {
7642 Lisp_Object tem;
7643 tem = Fstring_equal (XCAR (XCAR (names)), name);
7644 if (!NILP (tem))
7645 return dpyinfo;
7646 }
7647
7648 /* Use this general default value to start with. */
7649 Vx_resource_name = Vinvocation_name;
7650
7651 validate_x_resource_name ();
7652
7653 dpyinfo = w32_term_init (name, (unsigned char *)0,
7654 (char *) XSTRING (Vx_resource_name)->data);
7655
7656 if (dpyinfo == 0)
7657 error ("Cannot connect to server %s", XSTRING (name)->data);
7658
7659 w32_in_use = 1;
7660 XSETFASTINT (Vwindow_system_version, 3);
7661
7662 return dpyinfo;
7663 }
7664
7665 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
7666 1, 3, 0, doc: /* Open a connection to a server.
7667 DISPLAY is the name of the display to connect to.
7668 Optional second arg XRM-STRING is a string of resources in xrdb format.
7669 If the optional third arg MUST-SUCCEED is non-nil,
7670 terminate Emacs if we can't open the connection. */)
7671 (display, xrm_string, must_succeed)
7672 Lisp_Object display, xrm_string, must_succeed;
7673 {
7674 unsigned char *xrm_option;
7675 struct w32_display_info *dpyinfo;
7676
7677 /* If initialization has already been done, return now to avoid
7678 overwriting critical parts of one_w32_display_info. */
7679 if (w32_in_use)
7680 return Qnil;
7681
7682 CHECK_STRING (display);
7683 if (! NILP (xrm_string))
7684 CHECK_STRING (xrm_string);
7685
7686 if (! EQ (Vwindow_system, intern ("w32")))
7687 error ("Not using Microsoft Windows");
7688
7689 /* Allow color mapping to be defined externally; first look in user's
7690 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
7691 {
7692 Lisp_Object color_file;
7693 struct gcpro gcpro1;
7694
7695 color_file = build_string("~/rgb.txt");
7696
7697 GCPRO1 (color_file);
7698
7699 if (NILP (Ffile_readable_p (color_file)))
7700 color_file =
7701 Fexpand_file_name (build_string ("rgb.txt"),
7702 Fsymbol_value (intern ("data-directory")));
7703
7704 Vw32_color_map = Fw32_load_color_file (color_file);
7705
7706 UNGCPRO;
7707 }
7708 if (NILP (Vw32_color_map))
7709 Vw32_color_map = Fw32_default_color_map ();
7710
7711 if (! NILP (xrm_string))
7712 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
7713 else
7714 xrm_option = (unsigned char *) 0;
7715
7716 /* Use this general default value to start with. */
7717 /* First remove .exe suffix from invocation-name - it looks ugly. */
7718 {
7719 char basename[ MAX_PATH ], *str;
7720
7721 strcpy (basename, XSTRING (Vinvocation_name)->data);
7722 str = strrchr (basename, '.');
7723 if (str) *str = 0;
7724 Vinvocation_name = build_string (basename);
7725 }
7726 Vx_resource_name = Vinvocation_name;
7727
7728 validate_x_resource_name ();
7729
7730 /* This is what opens the connection and sets x_current_display.
7731 This also initializes many symbols, such as those used for input. */
7732 dpyinfo = w32_term_init (display, xrm_option,
7733 (char *) XSTRING (Vx_resource_name)->data);
7734
7735 if (dpyinfo == 0)
7736 {
7737 if (!NILP (must_succeed))
7738 fatal ("Cannot connect to server %s.\n",
7739 XSTRING (display)->data);
7740 else
7741 error ("Cannot connect to server %s", XSTRING (display)->data);
7742 }
7743
7744 w32_in_use = 1;
7745
7746 XSETFASTINT (Vwindow_system_version, 3);
7747 return Qnil;
7748 }
7749
7750 DEFUN ("x-close-connection", Fx_close_connection,
7751 Sx_close_connection, 1, 1, 0,
7752 doc: /* Close the connection to DISPLAY's server.
7753 For DISPLAY, specify either a frame or a display name (a string).
7754 If DISPLAY is nil, that stands for the selected frame's display. */)
7755 (display)
7756 Lisp_Object display;
7757 {
7758 struct w32_display_info *dpyinfo = check_x_display_info (display);
7759 int i;
7760
7761 if (dpyinfo->reference_count > 0)
7762 error ("Display still has frames on it");
7763
7764 BLOCK_INPUT;
7765 /* Free the fonts in the font table. */
7766 for (i = 0; i < dpyinfo->n_fonts; i++)
7767 if (dpyinfo->font_table[i].name)
7768 {
7769 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
7770 xfree (dpyinfo->font_table[i].full_name);
7771 xfree (dpyinfo->font_table[i].name);
7772 w32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
7773 }
7774 x_destroy_all_bitmaps (dpyinfo);
7775
7776 x_delete_display (dpyinfo);
7777 UNBLOCK_INPUT;
7778
7779 return Qnil;
7780 }
7781
7782 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
7783 doc: /* Return the list of display names that Emacs has connections to. */)
7784 ()
7785 {
7786 Lisp_Object tail, result;
7787
7788 result = Qnil;
7789 for (tail = w32_display_name_list; ! NILP (tail); tail = XCDR (tail))
7790 result = Fcons (XCAR (XCAR (tail)), result);
7791
7792 return result;
7793 }
7794
7795 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
7796 doc: /* This is a noop on W32 systems. */)
7797 (on, display)
7798 Lisp_Object display, on;
7799 {
7800 return Qnil;
7801 }
7802
7803 \f
7804 \f
7805 /***********************************************************************
7806 Image types
7807 ***********************************************************************/
7808
7809 /* Value is the number of elements of vector VECTOR. */
7810
7811 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
7812
7813 /* List of supported image types. Use define_image_type to add new
7814 types. Use lookup_image_type to find a type for a given symbol. */
7815
7816 static struct image_type *image_types;
7817
7818 /* The symbol `image' which is the car of the lists used to represent
7819 images in Lisp. */
7820
7821 extern Lisp_Object Qimage;
7822
7823 /* The symbol `xbm' which is used as the type symbol for XBM images. */
7824
7825 Lisp_Object Qxbm;
7826
7827 /* Keywords. */
7828
7829 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
7830 extern Lisp_Object QCdata;
7831 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
7832 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
7833 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
7834
7835 /* Other symbols. */
7836
7837 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
7838
7839 /* Time in seconds after which images should be removed from the cache
7840 if not displayed. */
7841
7842 Lisp_Object Vimage_cache_eviction_delay;
7843
7844 /* Function prototypes. */
7845
7846 static void define_image_type P_ ((struct image_type *type));
7847 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
7848 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
7849 static void x_laplace P_ ((struct frame *, struct image *));
7850 static void x_emboss P_ ((struct frame *, struct image *));
7851 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
7852 Lisp_Object));
7853
7854
7855 /* Define a new image type from TYPE. This adds a copy of TYPE to
7856 image_types and adds the symbol *TYPE->type to Vimage_types. */
7857
7858 static void
7859 define_image_type (type)
7860 struct image_type *type;
7861 {
7862 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
7863 The initialized data segment is read-only. */
7864 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
7865 bcopy (type, p, sizeof *p);
7866 p->next = image_types;
7867 image_types = p;
7868 Vimage_types = Fcons (*p->type, Vimage_types);
7869 }
7870
7871
7872 /* Look up image type SYMBOL, and return a pointer to its image_type
7873 structure. Value is null if SYMBOL is not a known image type. */
7874
7875 static INLINE struct image_type *
7876 lookup_image_type (symbol)
7877 Lisp_Object symbol;
7878 {
7879 struct image_type *type;
7880
7881 for (type = image_types; type; type = type->next)
7882 if (EQ (symbol, *type->type))
7883 break;
7884
7885 return type;
7886 }
7887
7888
7889 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
7890 valid image specification is a list whose car is the symbol
7891 `image', and whose rest is a property list. The property list must
7892 contain a value for key `:type'. That value must be the name of a
7893 supported image type. The rest of the property list depends on the
7894 image type. */
7895
7896 int
7897 valid_image_p (object)
7898 Lisp_Object object;
7899 {
7900 int valid_p = 0;
7901
7902 if (CONSP (object) && EQ (XCAR (object), Qimage))
7903 {
7904 Lisp_Object tem;
7905
7906 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
7907 if (EQ (XCAR (tem), QCtype))
7908 {
7909 tem = XCDR (tem);
7910 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
7911 {
7912 struct image_type *type;
7913 type = lookup_image_type (XCAR (tem));
7914 if (type)
7915 valid_p = type->valid_p (object);
7916 }
7917
7918 break;
7919 }
7920 }
7921
7922 return valid_p;
7923 }
7924
7925
7926 /* Log error message with format string FORMAT and argument ARG.
7927 Signaling an error, e.g. when an image cannot be loaded, is not a
7928 good idea because this would interrupt redisplay, and the error
7929 message display would lead to another redisplay. This function
7930 therefore simply displays a message. */
7931
7932 static void
7933 image_error (format, arg1, arg2)
7934 char *format;
7935 Lisp_Object arg1, arg2;
7936 {
7937 add_to_log (format, arg1, arg2);
7938 }
7939
7940
7941 \f
7942 /***********************************************************************
7943 Image specifications
7944 ***********************************************************************/
7945
7946 enum image_value_type
7947 {
7948 IMAGE_DONT_CHECK_VALUE_TYPE,
7949 IMAGE_STRING_VALUE,
7950 IMAGE_STRING_OR_NIL_VALUE,
7951 IMAGE_SYMBOL_VALUE,
7952 IMAGE_POSITIVE_INTEGER_VALUE,
7953 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
7954 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
7955 IMAGE_ASCENT_VALUE,
7956 IMAGE_INTEGER_VALUE,
7957 IMAGE_FUNCTION_VALUE,
7958 IMAGE_NUMBER_VALUE,
7959 IMAGE_BOOL_VALUE
7960 };
7961
7962 /* Structure used when parsing image specifications. */
7963
7964 struct image_keyword
7965 {
7966 /* Name of keyword. */
7967 char *name;
7968
7969 /* The type of value allowed. */
7970 enum image_value_type type;
7971
7972 /* Non-zero means key must be present. */
7973 int mandatory_p;
7974
7975 /* Used to recognize duplicate keywords in a property list. */
7976 int count;
7977
7978 /* The value that was found. */
7979 Lisp_Object value;
7980 };
7981
7982
7983 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
7984 int, Lisp_Object));
7985 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
7986
7987
7988 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
7989 has the format (image KEYWORD VALUE ...). One of the keyword/
7990 value pairs must be `:type TYPE'. KEYWORDS is a vector of
7991 image_keywords structures of size NKEYWORDS describing other
7992 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
7993
7994 static int
7995 parse_image_spec (spec, keywords, nkeywords, type)
7996 Lisp_Object spec;
7997 struct image_keyword *keywords;
7998 int nkeywords;
7999 Lisp_Object type;
8000 {
8001 int i;
8002 Lisp_Object plist;
8003
8004 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
8005 return 0;
8006
8007 plist = XCDR (spec);
8008 while (CONSP (plist))
8009 {
8010 Lisp_Object key, value;
8011
8012 /* First element of a pair must be a symbol. */
8013 key = XCAR (plist);
8014 plist = XCDR (plist);
8015 if (!SYMBOLP (key))
8016 return 0;
8017
8018 /* There must follow a value. */
8019 if (!CONSP (plist))
8020 return 0;
8021 value = XCAR (plist);
8022 plist = XCDR (plist);
8023
8024 /* Find key in KEYWORDS. Error if not found. */
8025 for (i = 0; i < nkeywords; ++i)
8026 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
8027 break;
8028
8029 if (i == nkeywords)
8030 continue;
8031
8032 /* Record that we recognized the keyword. If a keywords
8033 was found more than once, it's an error. */
8034 keywords[i].value = value;
8035 ++keywords[i].count;
8036
8037 if (keywords[i].count > 1)
8038 return 0;
8039
8040 /* Check type of value against allowed type. */
8041 switch (keywords[i].type)
8042 {
8043 case IMAGE_STRING_VALUE:
8044 if (!STRINGP (value))
8045 return 0;
8046 break;
8047
8048 case IMAGE_STRING_OR_NIL_VALUE:
8049 if (!STRINGP (value) && !NILP (value))
8050 return 0;
8051 break;
8052
8053 case IMAGE_SYMBOL_VALUE:
8054 if (!SYMBOLP (value))
8055 return 0;
8056 break;
8057
8058 case IMAGE_POSITIVE_INTEGER_VALUE:
8059 if (!INTEGERP (value) || XINT (value) <= 0)
8060 return 0;
8061 break;
8062
8063 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
8064 if (INTEGERP (value) && XINT (value) >= 0)
8065 break;
8066 if (CONSP (value)
8067 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
8068 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
8069 break;
8070 return 0;
8071
8072 case IMAGE_ASCENT_VALUE:
8073 if (SYMBOLP (value) && EQ (value, Qcenter))
8074 break;
8075 else if (INTEGERP (value)
8076 && XINT (value) >= 0
8077 && XINT (value) <= 100)
8078 break;
8079 return 0;
8080
8081 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
8082 if (!INTEGERP (value) || XINT (value) < 0)
8083 return 0;
8084 break;
8085
8086 case IMAGE_DONT_CHECK_VALUE_TYPE:
8087 break;
8088
8089 case IMAGE_FUNCTION_VALUE:
8090 value = indirect_function (value);
8091 if (SUBRP (value)
8092 || COMPILEDP (value)
8093 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
8094 break;
8095 return 0;
8096
8097 case IMAGE_NUMBER_VALUE:
8098 if (!INTEGERP (value) && !FLOATP (value))
8099 return 0;
8100 break;
8101
8102 case IMAGE_INTEGER_VALUE:
8103 if (!INTEGERP (value))
8104 return 0;
8105 break;
8106
8107 case IMAGE_BOOL_VALUE:
8108 if (!NILP (value) && !EQ (value, Qt))
8109 return 0;
8110 break;
8111
8112 default:
8113 abort ();
8114 break;
8115 }
8116
8117 if (EQ (key, QCtype) && !EQ (type, value))
8118 return 0;
8119 }
8120
8121 /* Check that all mandatory fields are present. */
8122 for (i = 0; i < nkeywords; ++i)
8123 if (keywords[i].mandatory_p && keywords[i].count == 0)
8124 return 0;
8125
8126 return NILP (plist);
8127 }
8128
8129
8130 /* Return the value of KEY in image specification SPEC. Value is nil
8131 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
8132 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
8133
8134 static Lisp_Object
8135 image_spec_value (spec, key, found)
8136 Lisp_Object spec, key;
8137 int *found;
8138 {
8139 Lisp_Object tail;
8140
8141 xassert (valid_image_p (spec));
8142
8143 for (tail = XCDR (spec);
8144 CONSP (tail) && CONSP (XCDR (tail));
8145 tail = XCDR (XCDR (tail)))
8146 {
8147 if (EQ (XCAR (tail), key))
8148 {
8149 if (found)
8150 *found = 1;
8151 return XCAR (XCDR (tail));
8152 }
8153 }
8154
8155 if (found)
8156 *found = 0;
8157 return Qnil;
8158 }
8159
8160
8161
8162 \f
8163 /***********************************************************************
8164 Image type independent image structures
8165 ***********************************************************************/
8166
8167 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
8168 static void free_image P_ ((struct frame *f, struct image *img));
8169
8170
8171 /* Allocate and return a new image structure for image specification
8172 SPEC. SPEC has a hash value of HASH. */
8173
8174 static struct image *
8175 make_image (spec, hash)
8176 Lisp_Object spec;
8177 unsigned hash;
8178 {
8179 struct image *img = (struct image *) xmalloc (sizeof *img);
8180
8181 xassert (valid_image_p (spec));
8182 bzero (img, sizeof *img);
8183 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
8184 xassert (img->type != NULL);
8185 img->spec = spec;
8186 img->data.lisp_val = Qnil;
8187 img->ascent = DEFAULT_IMAGE_ASCENT;
8188 img->hash = hash;
8189 return img;
8190 }
8191
8192
8193 /* Free image IMG which was used on frame F, including its resources. */
8194
8195 static void
8196 free_image (f, img)
8197 struct frame *f;
8198 struct image *img;
8199 {
8200 if (img)
8201 {
8202 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8203
8204 /* Remove IMG from the hash table of its cache. */
8205 if (img->prev)
8206 img->prev->next = img->next;
8207 else
8208 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
8209
8210 if (img->next)
8211 img->next->prev = img->prev;
8212
8213 c->images[img->id] = NULL;
8214
8215 /* Free resources, then free IMG. */
8216 img->type->free (f, img);
8217 xfree (img);
8218 }
8219 }
8220
8221
8222 /* Prepare image IMG for display on frame F. Must be called before
8223 drawing an image. */
8224
8225 void
8226 prepare_image_for_display (f, img)
8227 struct frame *f;
8228 struct image *img;
8229 {
8230 EMACS_TIME t;
8231
8232 /* We're about to display IMG, so set its timestamp to `now'. */
8233 EMACS_GET_TIME (t);
8234 img->timestamp = EMACS_SECS (t);
8235
8236 /* If IMG doesn't have a pixmap yet, load it now, using the image
8237 type dependent loader function. */
8238 if (img->pixmap == 0 && !img->load_failed_p)
8239 img->load_failed_p = img->type->load (f, img) == 0;
8240 }
8241
8242
8243 /* Value is the number of pixels for the ascent of image IMG when
8244 drawn in face FACE. */
8245
8246 int
8247 image_ascent (img, face)
8248 struct image *img;
8249 struct face *face;
8250 {
8251 int height = img->height + img->vmargin;
8252 int ascent;
8253
8254 if (img->ascent == CENTERED_IMAGE_ASCENT)
8255 {
8256 if (face->font)
8257 ascent = height / 2 - (FONT_DESCENT(face->font)
8258 - FONT_BASE(face->font)) / 2;
8259 else
8260 ascent = height / 2;
8261 }
8262 else
8263 ascent = height * img->ascent / 100.0;
8264
8265 return ascent;
8266 }
8267
8268
8269 \f
8270 /* Image background colors. */
8271
8272 static unsigned long
8273 four_corners_best (ximg, width, height)
8274 XImage *ximg;
8275 unsigned long width, height;
8276 {
8277 #if 0 /* TODO: Image support. */
8278 unsigned long corners[4], best;
8279 int i, best_count;
8280
8281 /* Get the colors at the corners of ximg. */
8282 corners[0] = XGetPixel (ximg, 0, 0);
8283 corners[1] = XGetPixel (ximg, width - 1, 0);
8284 corners[2] = XGetPixel (ximg, width - 1, height - 1);
8285 corners[3] = XGetPixel (ximg, 0, height - 1);
8286
8287 /* Choose the most frequently found color as background. */
8288 for (i = best_count = 0; i < 4; ++i)
8289 {
8290 int j, n;
8291
8292 for (j = n = 0; j < 4; ++j)
8293 if (corners[i] == corners[j])
8294 ++n;
8295
8296 if (n > best_count)
8297 best = corners[i], best_count = n;
8298 }
8299
8300 return best;
8301 #else
8302 return 0;
8303 #endif
8304 }
8305
8306 /* Return the `background' field of IMG. If IMG doesn't have one yet,
8307 it is guessed heuristically. If non-zero, XIMG is an existing XImage
8308 object to use for the heuristic. */
8309
8310 unsigned long
8311 image_background (img, f, ximg)
8312 struct image *img;
8313 struct frame *f;
8314 XImage *ximg;
8315 {
8316 if (! img->background_valid)
8317 /* IMG doesn't have a background yet, try to guess a reasonable value. */
8318 {
8319 #if 0 /* TODO: Image support. */
8320 int free_ximg = !ximg;
8321
8322 if (! ximg)
8323 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8324 0, 0, img->width, img->height, ~0, ZPixmap);
8325
8326 img->background = four_corners_best (ximg, img->width, img->height);
8327
8328 if (free_ximg)
8329 XDestroyImage (ximg);
8330
8331 img->background_valid = 1;
8332 #endif
8333 }
8334
8335 return img->background;
8336 }
8337
8338 /* Return the `background_transparent' field of IMG. If IMG doesn't
8339 have one yet, it is guessed heuristically. If non-zero, MASK is an
8340 existing XImage object to use for the heuristic. */
8341
8342 int
8343 image_background_transparent (img, f, mask)
8344 struct image *img;
8345 struct frame *f;
8346 XImage *mask;
8347 {
8348 if (! img->background_transparent_valid)
8349 /* IMG doesn't have a background yet, try to guess a reasonable value. */
8350 {
8351 #if 0 /* TODO: Image support. */
8352 if (img->mask)
8353 {
8354 int free_mask = !mask;
8355
8356 if (! mask)
8357 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
8358 0, 0, img->width, img->height, ~0, ZPixmap);
8359
8360 img->background_transparent
8361 = !four_corners_best (mask, img->width, img->height);
8362
8363 if (free_mask)
8364 XDestroyImage (mask);
8365 }
8366 else
8367 #endif
8368 img->background_transparent = 0;
8369
8370 img->background_transparent_valid = 1;
8371 }
8372
8373 return img->background_transparent;
8374 }
8375
8376 \f
8377 /***********************************************************************
8378 Helper functions for X image types
8379 ***********************************************************************/
8380
8381 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
8382 int, int));
8383 static void x_clear_image P_ ((struct frame *f, struct image *img));
8384 static unsigned long x_alloc_image_color P_ ((struct frame *f,
8385 struct image *img,
8386 Lisp_Object color_name,
8387 unsigned long dflt));
8388
8389
8390 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
8391 free the pixmap if any. MASK_P non-zero means clear the mask
8392 pixmap if any. COLORS_P non-zero means free colors allocated for
8393 the image, if any. */
8394
8395 static void
8396 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
8397 struct frame *f;
8398 struct image *img;
8399 int pixmap_p, mask_p, colors_p;
8400 {
8401 #if 0
8402 if (pixmap_p && img->pixmap)
8403 {
8404 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8405 img->pixmap = None;
8406 img->background_valid = 0;
8407 }
8408
8409 if (mask_p && img->mask)
8410 {
8411 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8412 img->mask = None;
8413 img->background_transparent_valid = 0;
8414 }
8415
8416 if (colors_p && img->ncolors)
8417 {
8418 x_free_colors (f, img->colors, img->ncolors);
8419 xfree (img->colors);
8420 img->colors = NULL;
8421 img->ncolors = 0;
8422 }
8423 #endif
8424 }
8425
8426 /* Free X resources of image IMG which is used on frame F. */
8427
8428 static void
8429 x_clear_image (f, img)
8430 struct frame *f;
8431 struct image *img;
8432 {
8433 #if 0 /* TODO: W32 image support */
8434
8435 if (img->pixmap)
8436 {
8437 BLOCK_INPUT;
8438 XFreePixmap (NULL, img->pixmap);
8439 img->pixmap = 0;
8440 UNBLOCK_INPUT;
8441 }
8442
8443 if (img->ncolors)
8444 {
8445 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
8446
8447 /* If display has an immutable color map, freeing colors is not
8448 necessary and some servers don't allow it. So don't do it. */
8449 if (class != StaticColor
8450 && class != StaticGray
8451 && class != TrueColor)
8452 {
8453 Colormap cmap;
8454 BLOCK_INPUT;
8455 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
8456 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
8457 img->ncolors, 0);
8458 UNBLOCK_INPUT;
8459 }
8460
8461 xfree (img->colors);
8462 img->colors = NULL;
8463 img->ncolors = 0;
8464 }
8465 #endif
8466 }
8467
8468
8469 /* Allocate color COLOR_NAME for image IMG on frame F. If color
8470 cannot be allocated, use DFLT. Add a newly allocated color to
8471 IMG->colors, so that it can be freed again. Value is the pixel
8472 color. */
8473
8474 static unsigned long
8475 x_alloc_image_color (f, img, color_name, dflt)
8476 struct frame *f;
8477 struct image *img;
8478 Lisp_Object color_name;
8479 unsigned long dflt;
8480 {
8481 #if 0 /* TODO: allocing colors. */
8482 XColor color;
8483 unsigned long result;
8484
8485 xassert (STRINGP (color_name));
8486
8487 if (w32_defined_color (f, XSTRING (color_name)->data, &color, 1))
8488 {
8489 /* This isn't called frequently so we get away with simply
8490 reallocating the color vector to the needed size, here. */
8491 ++img->ncolors;
8492 img->colors =
8493 (unsigned long *) xrealloc (img->colors,
8494 img->ncolors * sizeof *img->colors);
8495 img->colors[img->ncolors - 1] = color.pixel;
8496 result = color.pixel;
8497 }
8498 else
8499 result = dflt;
8500 return result;
8501 #endif
8502 return 0;
8503 }
8504
8505
8506 \f
8507 /***********************************************************************
8508 Image Cache
8509 ***********************************************************************/
8510
8511 static void cache_image P_ ((struct frame *f, struct image *img));
8512 static void postprocess_image P_ ((struct frame *, struct image *));
8513
8514
8515 /* Return a new, initialized image cache that is allocated from the
8516 heap. Call free_image_cache to free an image cache. */
8517
8518 struct image_cache *
8519 make_image_cache ()
8520 {
8521 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
8522 int size;
8523
8524 bzero (c, sizeof *c);
8525 c->size = 50;
8526 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
8527 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
8528 c->buckets = (struct image **) xmalloc (size);
8529 bzero (c->buckets, size);
8530 return c;
8531 }
8532
8533
8534 /* Free image cache of frame F. Be aware that X frames share images
8535 caches. */
8536
8537 void
8538 free_image_cache (f)
8539 struct frame *f;
8540 {
8541 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8542 if (c)
8543 {
8544 int i;
8545
8546 /* Cache should not be referenced by any frame when freed. */
8547 xassert (c->refcount == 0);
8548
8549 for (i = 0; i < c->used; ++i)
8550 free_image (f, c->images[i]);
8551 xfree (c->images);
8552 xfree (c);
8553 xfree (c->buckets);
8554 FRAME_X_IMAGE_CACHE (f) = NULL;
8555 }
8556 }
8557
8558
8559 /* Clear image cache of frame F. FORCE_P non-zero means free all
8560 images. FORCE_P zero means clear only images that haven't been
8561 displayed for some time. Should be called from time to time to
8562 reduce the number of loaded images. If image-eviction-seconds is
8563 non-nil, this frees images in the cache which weren't displayed for
8564 at least that many seconds. */
8565
8566 void
8567 clear_image_cache (f, force_p)
8568 struct frame *f;
8569 int force_p;
8570 {
8571 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8572
8573 if (c && INTEGERP (Vimage_cache_eviction_delay))
8574 {
8575 EMACS_TIME t;
8576 unsigned long old;
8577 int i, any_freed_p = 0;
8578
8579 EMACS_GET_TIME (t);
8580 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
8581
8582 for (i = 0; i < c->used; ++i)
8583 {
8584 struct image *img = c->images[i];
8585 if (img != NULL
8586 && (force_p
8587 || (img->timestamp > old)))
8588 {
8589 free_image (f, img);
8590 any_freed_p = 1;
8591 }
8592 }
8593
8594 /* We may be clearing the image cache because, for example,
8595 Emacs was iconified for a longer period of time. In that
8596 case, current matrices may still contain references to
8597 images freed above. So, clear these matrices. */
8598 if (any_freed_p)
8599 {
8600 clear_current_matrices (f);
8601 ++windows_or_buffers_changed;
8602 }
8603 }
8604 }
8605
8606
8607 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
8608 0, 1, 0,
8609 doc: /* Clear the image cache of FRAME.
8610 FRAME nil or omitted means use the selected frame.
8611 FRAME t means clear the image caches of all frames. */)
8612 (frame)
8613 Lisp_Object frame;
8614 {
8615 if (EQ (frame, Qt))
8616 {
8617 Lisp_Object tail;
8618
8619 FOR_EACH_FRAME (tail, frame)
8620 if (FRAME_W32_P (XFRAME (frame)))
8621 clear_image_cache (XFRAME (frame), 1);
8622 }
8623 else
8624 clear_image_cache (check_x_frame (frame), 1);
8625
8626 return Qnil;
8627 }
8628
8629
8630 /* Compute masks and transform image IMG on frame F, as specified
8631 by the image's specification, */
8632
8633 static void
8634 postprocess_image (f, img)
8635 struct frame *f;
8636 struct image *img;
8637 {
8638 #if 0 /* TODO: image support. */
8639 /* Manipulation of the image's mask. */
8640 if (img->pixmap)
8641 {
8642 Lisp_Object conversion, spec;
8643 Lisp_Object mask;
8644
8645 spec = img->spec;
8646
8647 /* `:heuristic-mask t'
8648 `:mask heuristic'
8649 means build a mask heuristically.
8650 `:heuristic-mask (R G B)'
8651 `:mask (heuristic (R G B))'
8652 means build a mask from color (R G B) in the
8653 image.
8654 `:mask nil'
8655 means remove a mask, if any. */
8656
8657 mask = image_spec_value (spec, QCheuristic_mask, NULL);
8658 if (!NILP (mask))
8659 x_build_heuristic_mask (f, img, mask);
8660 else
8661 {
8662 int found_p;
8663
8664 mask = image_spec_value (spec, QCmask, &found_p);
8665
8666 if (EQ (mask, Qheuristic))
8667 x_build_heuristic_mask (f, img, Qt);
8668 else if (CONSP (mask)
8669 && EQ (XCAR (mask), Qheuristic))
8670 {
8671 if (CONSP (XCDR (mask)))
8672 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
8673 else
8674 x_build_heuristic_mask (f, img, XCDR (mask));
8675 }
8676 else if (NILP (mask) && found_p && img->mask)
8677 {
8678 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8679 img->mask = NULL;
8680 }
8681 }
8682
8683
8684 /* Should we apply an image transformation algorithm? */
8685 conversion = image_spec_value (spec, QCconversion, NULL);
8686 if (EQ (conversion, Qdisabled))
8687 x_disable_image (f, img);
8688 else if (EQ (conversion, Qlaplace))
8689 x_laplace (f, img);
8690 else if (EQ (conversion, Qemboss))
8691 x_emboss (f, img);
8692 else if (CONSP (conversion)
8693 && EQ (XCAR (conversion), Qedge_detection))
8694 {
8695 Lisp_Object tem;
8696 tem = XCDR (conversion);
8697 if (CONSP (tem))
8698 x_edge_detection (f, img,
8699 Fplist_get (tem, QCmatrix),
8700 Fplist_get (tem, QCcolor_adjustment));
8701 }
8702 }
8703 #endif
8704 }
8705
8706
8707 /* Return the id of image with Lisp specification SPEC on frame F.
8708 SPEC must be a valid Lisp image specification (see valid_image_p). */
8709
8710 int
8711 lookup_image (f, spec)
8712 struct frame *f;
8713 Lisp_Object spec;
8714 {
8715 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8716 struct image *img;
8717 int i;
8718 unsigned hash;
8719 struct gcpro gcpro1;
8720 EMACS_TIME now;
8721
8722 /* F must be a window-system frame, and SPEC must be a valid image
8723 specification. */
8724 xassert (FRAME_WINDOW_P (f));
8725 xassert (valid_image_p (spec));
8726
8727 GCPRO1 (spec);
8728
8729 /* Look up SPEC in the hash table of the image cache. */
8730 hash = sxhash (spec, 0);
8731 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
8732
8733 for (img = c->buckets[i]; img; img = img->next)
8734 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
8735 break;
8736
8737 /* If not found, create a new image and cache it. */
8738 if (img == NULL)
8739 {
8740 extern Lisp_Object Qpostscript;
8741
8742 BLOCK_INPUT;
8743 img = make_image (spec, hash);
8744 cache_image (f, img);
8745 img->load_failed_p = img->type->load (f, img) == 0;
8746
8747 /* If we can't load the image, and we don't have a width and
8748 height, use some arbitrary width and height so that we can
8749 draw a rectangle for it. */
8750 if (img->load_failed_p)
8751 {
8752 Lisp_Object value;
8753
8754 value = image_spec_value (spec, QCwidth, NULL);
8755 img->width = (INTEGERP (value)
8756 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
8757 value = image_spec_value (spec, QCheight, NULL);
8758 img->height = (INTEGERP (value)
8759 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
8760 }
8761 else
8762 {
8763 /* Handle image type independent image attributes
8764 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF',
8765 `:background COLOR'. */
8766 Lisp_Object ascent, margin, relief, bg;
8767
8768 ascent = image_spec_value (spec, QCascent, NULL);
8769 if (INTEGERP (ascent))
8770 img->ascent = XFASTINT (ascent);
8771 else if (EQ (ascent, Qcenter))
8772 img->ascent = CENTERED_IMAGE_ASCENT;
8773
8774 margin = image_spec_value (spec, QCmargin, NULL);
8775 if (INTEGERP (margin) && XINT (margin) >= 0)
8776 img->vmargin = img->hmargin = XFASTINT (margin);
8777 else if (CONSP (margin) && INTEGERP (XCAR (margin))
8778 && INTEGERP (XCDR (margin)))
8779 {
8780 if (XINT (XCAR (margin)) > 0)
8781 img->hmargin = XFASTINT (XCAR (margin));
8782 if (XINT (XCDR (margin)) > 0)
8783 img->vmargin = XFASTINT (XCDR (margin));
8784 }
8785
8786 relief = image_spec_value (spec, QCrelief, NULL);
8787 if (INTEGERP (relief))
8788 {
8789 img->relief = XINT (relief);
8790 img->hmargin += abs (img->relief);
8791 img->vmargin += abs (img->relief);
8792 }
8793
8794 if (! img->background_valid)
8795 {
8796 bg = image_spec_value (img->spec, QCbackground, NULL);
8797 if (!NILP (bg))
8798 {
8799 img->background
8800 = x_alloc_image_color (f, img, bg,
8801 FRAME_BACKGROUND_PIXEL (f));
8802 img->background_valid = 1;
8803 }
8804 }
8805
8806 /* Do image transformations and compute masks, unless we
8807 don't have the image yet. */
8808 if (!EQ (*img->type->type, Qpostscript))
8809 postprocess_image (f, img);
8810 }
8811
8812 UNBLOCK_INPUT;
8813 xassert (!interrupt_input_blocked);
8814 }
8815
8816 /* We're using IMG, so set its timestamp to `now'. */
8817 EMACS_GET_TIME (now);
8818 img->timestamp = EMACS_SECS (now);
8819
8820 UNGCPRO;
8821
8822 /* Value is the image id. */
8823 return img->id;
8824 }
8825
8826
8827 /* Cache image IMG in the image cache of frame F. */
8828
8829 static void
8830 cache_image (f, img)
8831 struct frame *f;
8832 struct image *img;
8833 {
8834 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8835 int i;
8836
8837 /* Find a free slot in c->images. */
8838 for (i = 0; i < c->used; ++i)
8839 if (c->images[i] == NULL)
8840 break;
8841
8842 /* If no free slot found, maybe enlarge c->images. */
8843 if (i == c->used && c->used == c->size)
8844 {
8845 c->size *= 2;
8846 c->images = (struct image **) xrealloc (c->images,
8847 c->size * sizeof *c->images);
8848 }
8849
8850 /* Add IMG to c->images, and assign IMG an id. */
8851 c->images[i] = img;
8852 img->id = i;
8853 if (i == c->used)
8854 ++c->used;
8855
8856 /* Add IMG to the cache's hash table. */
8857 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
8858 img->next = c->buckets[i];
8859 if (img->next)
8860 img->next->prev = img;
8861 img->prev = NULL;
8862 c->buckets[i] = img;
8863 }
8864
8865
8866 /* Call FN on every image in the image cache of frame F. Used to mark
8867 Lisp Objects in the image cache. */
8868
8869 void
8870 forall_images_in_image_cache (f, fn)
8871 struct frame *f;
8872 void (*fn) P_ ((struct image *img));
8873 {
8874 if (FRAME_LIVE_P (f) && FRAME_W32_P (f))
8875 {
8876 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8877 if (c)
8878 {
8879 int i;
8880 for (i = 0; i < c->used; ++i)
8881 if (c->images[i])
8882 fn (c->images[i]);
8883 }
8884 }
8885 }
8886
8887
8888 \f
8889 /***********************************************************************
8890 W32 support code
8891 ***********************************************************************/
8892
8893 #if 0 /* TODO: W32 specific image code. */
8894
8895 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
8896 XImage **, Pixmap *));
8897 static void x_destroy_x_image P_ ((XImage *));
8898 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
8899
8900
8901 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
8902 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
8903 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
8904 via xmalloc. Print error messages via image_error if an error
8905 occurs. Value is non-zero if successful. */
8906
8907 static int
8908 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
8909 struct frame *f;
8910 int width, height, depth;
8911 XImage **ximg;
8912 Pixmap *pixmap;
8913 {
8914 #if 0 /* TODO: Image support for W32 */
8915 Display *display = FRAME_W32_DISPLAY (f);
8916 Screen *screen = FRAME_X_SCREEN (f);
8917 Window window = FRAME_W32_WINDOW (f);
8918
8919 xassert (interrupt_input_blocked);
8920
8921 if (depth <= 0)
8922 depth = one_w32_display_info.n_cbits;
8923 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
8924 depth, ZPixmap, 0, NULL, width, height,
8925 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
8926 if (*ximg == NULL)
8927 {
8928 image_error ("Unable to allocate X image", Qnil, Qnil);
8929 return 0;
8930 }
8931
8932 /* Allocate image raster. */
8933 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
8934
8935 /* Allocate a pixmap of the same size. */
8936 *pixmap = XCreatePixmap (display, window, width, height, depth);
8937 if (*pixmap == 0)
8938 {
8939 x_destroy_x_image (*ximg);
8940 *ximg = NULL;
8941 image_error ("Unable to create X pixmap", Qnil, Qnil);
8942 return 0;
8943 }
8944 #endif
8945 return 1;
8946 }
8947
8948
8949 /* Destroy XImage XIMG. Free XIMG->data. */
8950
8951 static void
8952 x_destroy_x_image (ximg)
8953 XImage *ximg;
8954 {
8955 xassert (interrupt_input_blocked);
8956 if (ximg)
8957 {
8958 xfree (ximg->data);
8959 ximg->data = NULL;
8960 XDestroyImage (ximg);
8961 }
8962 }
8963
8964
8965 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
8966 are width and height of both the image and pixmap. */
8967
8968 static void
8969 x_put_x_image (f, ximg, pixmap, width, height)
8970 struct frame *f;
8971 XImage *ximg;
8972 Pixmap pixmap;
8973 {
8974 GC gc;
8975
8976 xassert (interrupt_input_blocked);
8977 gc = XCreateGC (NULL, pixmap, 0, NULL);
8978 XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
8979 XFreeGC (NULL, gc);
8980 }
8981
8982 #endif
8983
8984 \f
8985 /***********************************************************************
8986 File Handling
8987 ***********************************************************************/
8988
8989 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
8990 static char *slurp_file P_ ((char *, int *));
8991
8992
8993 /* Find image file FILE. Look in data-directory, then
8994 x-bitmap-file-path. Value is the full name of the file found, or
8995 nil if not found. */
8996
8997 static Lisp_Object
8998 x_find_image_file (file)
8999 Lisp_Object file;
9000 {
9001 Lisp_Object file_found, search_path;
9002 struct gcpro gcpro1, gcpro2;
9003 int fd;
9004
9005 file_found = Qnil;
9006 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
9007 GCPRO2 (file_found, search_path);
9008
9009 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
9010 fd = openp (search_path, file, Qnil, &file_found, 0);
9011
9012 if (fd == -1)
9013 file_found = Qnil;
9014 else
9015 close (fd);
9016
9017 UNGCPRO;
9018 return file_found;
9019 }
9020
9021
9022 /* Read FILE into memory. Value is a pointer to a buffer allocated
9023 with xmalloc holding FILE's contents. Value is null if an error
9024 occurred. *SIZE is set to the size of the file. */
9025
9026 static char *
9027 slurp_file (file, size)
9028 char *file;
9029 int *size;
9030 {
9031 FILE *fp = NULL;
9032 char *buf = NULL;
9033 struct stat st;
9034
9035 if (stat (file, &st) == 0
9036 && (fp = fopen (file, "r")) != NULL
9037 && (buf = (char *) xmalloc (st.st_size),
9038 fread (buf, 1, st.st_size, fp) == st.st_size))
9039 {
9040 *size = st.st_size;
9041 fclose (fp);
9042 }
9043 else
9044 {
9045 if (fp)
9046 fclose (fp);
9047 if (buf)
9048 {
9049 xfree (buf);
9050 buf = NULL;
9051 }
9052 }
9053
9054 return buf;
9055 }
9056
9057
9058 \f
9059 /***********************************************************************
9060 XBM images
9061 ***********************************************************************/
9062
9063 static int xbm_load P_ ((struct frame *f, struct image *img));
9064 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
9065 Lisp_Object file));
9066 static int xbm_image_p P_ ((Lisp_Object object));
9067 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
9068 unsigned char **));
9069
9070
9071 /* Indices of image specification fields in xbm_format, below. */
9072
9073 enum xbm_keyword_index
9074 {
9075 XBM_TYPE,
9076 XBM_FILE,
9077 XBM_WIDTH,
9078 XBM_HEIGHT,
9079 XBM_DATA,
9080 XBM_FOREGROUND,
9081 XBM_BACKGROUND,
9082 XBM_ASCENT,
9083 XBM_MARGIN,
9084 XBM_RELIEF,
9085 XBM_ALGORITHM,
9086 XBM_HEURISTIC_MASK,
9087 XBM_MASK,
9088 XBM_LAST
9089 };
9090
9091 /* Vector of image_keyword structures describing the format
9092 of valid XBM image specifications. */
9093
9094 static struct image_keyword xbm_format[XBM_LAST] =
9095 {
9096 {":type", IMAGE_SYMBOL_VALUE, 1},
9097 {":file", IMAGE_STRING_VALUE, 0},
9098 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9099 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9100 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9101 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
9102 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
9103 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9104 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9105 {":relief", IMAGE_INTEGER_VALUE, 0},
9106 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9107 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9108 };
9109
9110 /* Structure describing the image type XBM. */
9111
9112 static struct image_type xbm_type =
9113 {
9114 &Qxbm,
9115 xbm_image_p,
9116 xbm_load,
9117 x_clear_image,
9118 NULL
9119 };
9120
9121 /* Tokens returned from xbm_scan. */
9122
9123 enum xbm_token
9124 {
9125 XBM_TK_IDENT = 256,
9126 XBM_TK_NUMBER
9127 };
9128
9129
9130 /* Return non-zero if OBJECT is a valid XBM-type image specification.
9131 A valid specification is a list starting with the symbol `image'
9132 The rest of the list is a property list which must contain an
9133 entry `:type xbm..
9134
9135 If the specification specifies a file to load, it must contain
9136 an entry `:file FILENAME' where FILENAME is a string.
9137
9138 If the specification is for a bitmap loaded from memory it must
9139 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
9140 WIDTH and HEIGHT are integers > 0. DATA may be:
9141
9142 1. a string large enough to hold the bitmap data, i.e. it must
9143 have a size >= (WIDTH + 7) / 8 * HEIGHT
9144
9145 2. a bool-vector of size >= WIDTH * HEIGHT
9146
9147 3. a vector of strings or bool-vectors, one for each line of the
9148 bitmap.
9149
9150 Both the file and data forms may contain the additional entries
9151 `:background COLOR' and `:foreground COLOR'. If not present,
9152 foreground and background of the frame on which the image is
9153 displayed, is used. */
9154
9155 static int
9156 xbm_image_p (object)
9157 Lisp_Object object;
9158 {
9159 struct image_keyword kw[XBM_LAST];
9160
9161 bcopy (xbm_format, kw, sizeof kw);
9162 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
9163 return 0;
9164
9165 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
9166
9167 if (kw[XBM_FILE].count)
9168 {
9169 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
9170 return 0;
9171 }
9172 else
9173 {
9174 Lisp_Object data;
9175 int width, height;
9176
9177 /* Entries for `:width', `:height' and `:data' must be present. */
9178 if (!kw[XBM_WIDTH].count
9179 || !kw[XBM_HEIGHT].count
9180 || !kw[XBM_DATA].count)
9181 return 0;
9182
9183 data = kw[XBM_DATA].value;
9184 width = XFASTINT (kw[XBM_WIDTH].value);
9185 height = XFASTINT (kw[XBM_HEIGHT].value);
9186
9187 /* Check type of data, and width and height against contents of
9188 data. */
9189 if (VECTORP (data))
9190 {
9191 int i;
9192
9193 /* Number of elements of the vector must be >= height. */
9194 if (XVECTOR (data)->size < height)
9195 return 0;
9196
9197 /* Each string or bool-vector in data must be large enough
9198 for one line of the image. */
9199 for (i = 0; i < height; ++i)
9200 {
9201 Lisp_Object elt = XVECTOR (data)->contents[i];
9202
9203 if (STRINGP (elt))
9204 {
9205 if (XSTRING (elt)->size
9206 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
9207 return 0;
9208 }
9209 else if (BOOL_VECTOR_P (elt))
9210 {
9211 if (XBOOL_VECTOR (elt)->size < width)
9212 return 0;
9213 }
9214 else
9215 return 0;
9216 }
9217 }
9218 else if (STRINGP (data))
9219 {
9220 if (XSTRING (data)->size
9221 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
9222 return 0;
9223 }
9224 else if (BOOL_VECTOR_P (data))
9225 {
9226 if (XBOOL_VECTOR (data)->size < width * height)
9227 return 0;
9228 }
9229 else
9230 return 0;
9231 }
9232
9233 /* Baseline must be a value between 0 and 100 (a percentage). */
9234 if (kw[XBM_ASCENT].count
9235 && XFASTINT (kw[XBM_ASCENT].value) > 100)
9236 return 0;
9237
9238 return 1;
9239 }
9240
9241
9242 /* Scan a bitmap file. FP is the stream to read from. Value is
9243 either an enumerator from enum xbm_token, or a character for a
9244 single-character token, or 0 at end of file. If scanning an
9245 identifier, store the lexeme of the identifier in SVAL. If
9246 scanning a number, store its value in *IVAL. */
9247
9248 static int
9249 xbm_scan (s, end, sval, ival)
9250 char **s, *end;
9251 char *sval;
9252 int *ival;
9253 {
9254 int c;
9255
9256 loop:
9257
9258 /* Skip white space. */
9259 while (*s < end &&(c = *(*s)++, isspace (c)))
9260 ;
9261
9262 if (*s >= end)
9263 c = 0;
9264 else if (isdigit (c))
9265 {
9266 int value = 0, digit;
9267
9268 if (c == '0' && *s < end)
9269 {
9270 c = *(*s)++;
9271 if (c == 'x' || c == 'X')
9272 {
9273 while (*s < end)
9274 {
9275 c = *(*s)++;
9276 if (isdigit (c))
9277 digit = c - '0';
9278 else if (c >= 'a' && c <= 'f')
9279 digit = c - 'a' + 10;
9280 else if (c >= 'A' && c <= 'F')
9281 digit = c - 'A' + 10;
9282 else
9283 break;
9284 value = 16 * value + digit;
9285 }
9286 }
9287 else if (isdigit (c))
9288 {
9289 value = c - '0';
9290 while (*s < end
9291 && (c = *(*s)++, isdigit (c)))
9292 value = 8 * value + c - '0';
9293 }
9294 }
9295 else
9296 {
9297 value = c - '0';
9298 while (*s < end
9299 && (c = *(*s)++, isdigit (c)))
9300 value = 10 * value + c - '0';
9301 }
9302
9303 if (*s < end)
9304 *s = *s - 1;
9305 *ival = value;
9306 c = XBM_TK_NUMBER;
9307 }
9308 else if (isalpha (c) || c == '_')
9309 {
9310 *sval++ = c;
9311 while (*s < end
9312 && (c = *(*s)++, (isalnum (c) || c == '_')))
9313 *sval++ = c;
9314 *sval = 0;
9315 if (*s < end)
9316 *s = *s - 1;
9317 c = XBM_TK_IDENT;
9318 }
9319 else if (c == '/' && **s == '*')
9320 {
9321 /* C-style comment. */
9322 ++*s;
9323 while (**s && (**s != '*' || *(*s + 1) != '/'))
9324 ++*s;
9325 if (**s)
9326 {
9327 *s += 2;
9328 goto loop;
9329 }
9330 }
9331
9332 return c;
9333 }
9334
9335
9336 /* Replacement for XReadBitmapFileData which isn't available under old
9337 X versions. CONTENTS is a pointer to a buffer to parse; END is the
9338 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
9339 the image. Return in *DATA the bitmap data allocated with xmalloc.
9340 Value is non-zero if successful. DATA null means just test if
9341 CONTENTS looks like an in-memory XBM file. */
9342
9343 static int
9344 xbm_read_bitmap_data (contents, end, width, height, data)
9345 char *contents, *end;
9346 int *width, *height;
9347 unsigned char **data;
9348 {
9349 char *s = contents;
9350 char buffer[BUFSIZ];
9351 int padding_p = 0;
9352 int v10 = 0;
9353 int bytes_per_line, i, nbytes;
9354 unsigned char *p;
9355 int value;
9356 int LA1;
9357
9358 #define match() \
9359 LA1 = xbm_scan (contents, end, buffer, &value)
9360
9361 #define expect(TOKEN) \
9362 if (LA1 != (TOKEN)) \
9363 goto failure; \
9364 else \
9365 match ()
9366
9367 #define expect_ident(IDENT) \
9368 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
9369 match (); \
9370 else \
9371 goto failure
9372
9373 *width = *height = -1;
9374 if (data)
9375 *data = NULL;
9376 LA1 = xbm_scan (&s, end, buffer, &value);
9377
9378 /* Parse defines for width, height and hot-spots. */
9379 while (LA1 == '#')
9380 {
9381 match ();
9382 expect_ident ("define");
9383 expect (XBM_TK_IDENT);
9384
9385 if (LA1 == XBM_TK_NUMBER);
9386 {
9387 char *p = strrchr (buffer, '_');
9388 p = p ? p + 1 : buffer;
9389 if (strcmp (p, "width") == 0)
9390 *width = value;
9391 else if (strcmp (p, "height") == 0)
9392 *height = value;
9393 }
9394 expect (XBM_TK_NUMBER);
9395 }
9396
9397 if (*width < 0 || *height < 0)
9398 goto failure;
9399 else if (data == NULL)
9400 goto success;
9401
9402 /* Parse bits. Must start with `static'. */
9403 expect_ident ("static");
9404 if (LA1 == XBM_TK_IDENT)
9405 {
9406 if (strcmp (buffer, "unsigned") == 0)
9407 {
9408 match ();
9409 expect_ident ("char");
9410 }
9411 else if (strcmp (buffer, "short") == 0)
9412 {
9413 match ();
9414 v10 = 1;
9415 if (*width % 16 && *width % 16 < 9)
9416 padding_p = 1;
9417 }
9418 else if (strcmp (buffer, "char") == 0)
9419 match ();
9420 else
9421 goto failure;
9422 }
9423 else
9424 goto failure;
9425
9426 expect (XBM_TK_IDENT);
9427 expect ('[');
9428 expect (']');
9429 expect ('=');
9430 expect ('{');
9431
9432 bytes_per_line = (*width + 7) / 8 + padding_p;
9433 nbytes = bytes_per_line * *height;
9434 p = *data = (char *) xmalloc (nbytes);
9435
9436 if (v10)
9437 {
9438
9439 for (i = 0; i < nbytes; i += 2)
9440 {
9441 int val = value;
9442 expect (XBM_TK_NUMBER);
9443
9444 *p++ = val;
9445 if (!padding_p || ((i + 2) % bytes_per_line))
9446 *p++ = value >> 8;
9447
9448 if (LA1 == ',' || LA1 == '}')
9449 match ();
9450 else
9451 goto failure;
9452 }
9453 }
9454 else
9455 {
9456 for (i = 0; i < nbytes; ++i)
9457 {
9458 int val = value;
9459 expect (XBM_TK_NUMBER);
9460
9461 *p++ = val;
9462
9463 if (LA1 == ',' || LA1 == '}')
9464 match ();
9465 else
9466 goto failure;
9467 }
9468 }
9469
9470 success:
9471 return 1;
9472
9473 failure:
9474
9475 if (data && *data)
9476 {
9477 xfree (*data);
9478 *data = NULL;
9479 }
9480 return 0;
9481
9482 #undef match
9483 #undef expect
9484 #undef expect_ident
9485 }
9486
9487
9488 /* Load XBM image IMG which will be displayed on frame F from buffer
9489 CONTENTS. END is the end of the buffer. Value is non-zero if
9490 successful. */
9491
9492 static int
9493 xbm_load_image (f, img, contents, end)
9494 struct frame *f;
9495 struct image *img;
9496 char *contents, *end;
9497 {
9498 int rc;
9499 unsigned char *data;
9500 int success_p = 0;
9501
9502 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
9503 if (rc)
9504 {
9505 int depth = one_w32_display_info.n_cbits;
9506 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
9507 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9508 Lisp_Object value;
9509
9510 xassert (img->width > 0 && img->height > 0);
9511
9512 /* Get foreground and background colors, maybe allocate colors. */
9513 value = image_spec_value (img->spec, QCforeground, NULL);
9514 if (!NILP (value))
9515 foreground = x_alloc_image_color (f, img, value, foreground);
9516 value = image_spec_value (img->spec, QCbackground, NULL);
9517 if (!NILP (value))
9518 {
9519 background = x_alloc_image_color (f, img, value, background);
9520 img->background = background;
9521 img->background_valid = 1;
9522 }
9523
9524 #if 0 /* TODO : Port image display to W32 */
9525 img->pixmap
9526 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
9527 FRAME_W32_WINDOW (f),
9528 data,
9529 img->width, img->height,
9530 foreground, background,
9531 depth);
9532 #endif
9533 xfree (data);
9534
9535 if (img->pixmap == 0)
9536 {
9537 x_clear_image (f, img);
9538 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
9539 }
9540 else
9541 success_p = 1;
9542 }
9543 else
9544 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
9545
9546 return success_p;
9547 }
9548
9549
9550 /* Value is non-zero if DATA looks like an in-memory XBM file. */
9551
9552 static int
9553 xbm_file_p (data)
9554 Lisp_Object data;
9555 {
9556 int w, h;
9557 return (STRINGP (data)
9558 && xbm_read_bitmap_data (XSTRING (data)->data,
9559 (XSTRING (data)->data
9560 + STRING_BYTES (XSTRING (data))),
9561 &w, &h, NULL));
9562 }
9563
9564
9565 /* Fill image IMG which is used on frame F with pixmap data. Value is
9566 non-zero if successful. */
9567
9568 static int
9569 xbm_load (f, img)
9570 struct frame *f;
9571 struct image *img;
9572 {
9573 int success_p = 0;
9574 Lisp_Object file_name;
9575
9576 xassert (xbm_image_p (img->spec));
9577
9578 /* If IMG->spec specifies a file name, create a non-file spec from it. */
9579 file_name = image_spec_value (img->spec, QCfile, NULL);
9580 if (STRINGP (file_name))
9581 {
9582 Lisp_Object file;
9583 char *contents;
9584 int size;
9585 struct gcpro gcpro1;
9586
9587 file = x_find_image_file (file_name);
9588 GCPRO1 (file);
9589 if (!STRINGP (file))
9590 {
9591 image_error ("Cannot find image file `%s'", file_name, Qnil);
9592 UNGCPRO;
9593 return 0;
9594 }
9595
9596 contents = slurp_file (XSTRING (file)->data, &size);
9597 if (contents == NULL)
9598 {
9599 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
9600 UNGCPRO;
9601 return 0;
9602 }
9603
9604 success_p = xbm_load_image (f, img, contents, contents + size);
9605 UNGCPRO;
9606 }
9607 else
9608 {
9609 struct image_keyword fmt[XBM_LAST];
9610 Lisp_Object data;
9611 int depth;
9612 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
9613 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9614 char *bits;
9615 int parsed_p;
9616 int in_memory_file_p = 0;
9617
9618 /* See if data looks like an in-memory XBM file. */
9619 data = image_spec_value (img->spec, QCdata, NULL);
9620 in_memory_file_p = xbm_file_p (data);
9621
9622 /* Parse the list specification. */
9623 bcopy (xbm_format, fmt, sizeof fmt);
9624 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
9625 xassert (parsed_p);
9626
9627 /* Get specified width, and height. */
9628 if (!in_memory_file_p)
9629 {
9630 img->width = XFASTINT (fmt[XBM_WIDTH].value);
9631 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
9632 xassert (img->width > 0 && img->height > 0);
9633 }
9634 /* Get foreground and background colors, maybe allocate colors. */
9635 if (fmt[XBM_FOREGROUND].count
9636 && STRINGP (fmt[XBM_FOREGROUND].value))
9637 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
9638 foreground);
9639 if (fmt[XBM_BACKGROUND].count
9640 && STRINGP (fmt[XBM_BACKGROUND].value))
9641 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
9642 background);
9643
9644 if (in_memory_file_p)
9645 success_p = xbm_load_image (f, img, XSTRING (data)->data,
9646 (XSTRING (data)->data
9647 + STRING_BYTES (XSTRING (data))));
9648 else
9649 {
9650 if (VECTORP (data))
9651 {
9652 int i;
9653 char *p;
9654 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
9655
9656 p = bits = (char *) alloca (nbytes * img->height);
9657 for (i = 0; i < img->height; ++i, p += nbytes)
9658 {
9659 Lisp_Object line = XVECTOR (data)->contents[i];
9660 if (STRINGP (line))
9661 bcopy (XSTRING (line)->data, p, nbytes);
9662 else
9663 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
9664 }
9665 }
9666 else if (STRINGP (data))
9667 bits = XSTRING (data)->data;
9668 else
9669 bits = XBOOL_VECTOR (data)->data;
9670 #ifdef TODO /* image support. */
9671 /* Create the pixmap. */
9672 depth = one_w32_display_info.n_cbits;
9673 img->pixmap
9674 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
9675 FRAME_X_WINDOW (f),
9676 bits,
9677 img->width, img->height,
9678 foreground, background,
9679 depth);
9680 #endif
9681 if (img->pixmap)
9682 success_p = 1;
9683 else
9684 {
9685 image_error ("Unable to create pixmap for XBM image `%s'",
9686 img->spec, Qnil);
9687 x_clear_image (f, img);
9688 }
9689 }
9690 }
9691
9692 return success_p;
9693 }
9694
9695
9696 \f
9697 /***********************************************************************
9698 XPM images
9699 ***********************************************************************/
9700
9701 #if HAVE_XPM
9702
9703 static int xpm_image_p P_ ((Lisp_Object object));
9704 static int xpm_load P_ ((struct frame *f, struct image *img));
9705 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
9706
9707 #include "X11/xpm.h"
9708
9709 /* The symbol `xpm' identifying XPM-format images. */
9710
9711 Lisp_Object Qxpm;
9712
9713 /* Indices of image specification fields in xpm_format, below. */
9714
9715 enum xpm_keyword_index
9716 {
9717 XPM_TYPE,
9718 XPM_FILE,
9719 XPM_DATA,
9720 XPM_ASCENT,
9721 XPM_MARGIN,
9722 XPM_RELIEF,
9723 XPM_ALGORITHM,
9724 XPM_HEURISTIC_MASK,
9725 XPM_MASK,
9726 XPM_COLOR_SYMBOLS,
9727 XPM_BACKGROUND,
9728 XPM_LAST
9729 };
9730
9731 /* Vector of image_keyword structures describing the format
9732 of valid XPM image specifications. */
9733
9734 static struct image_keyword xpm_format[XPM_LAST] =
9735 {
9736 {":type", IMAGE_SYMBOL_VALUE, 1},
9737 {":file", IMAGE_STRING_VALUE, 0},
9738 {":data", IMAGE_STRING_VALUE, 0},
9739 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9740 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9741 {":relief", IMAGE_INTEGER_VALUE, 0},
9742 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9743 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9744 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9745 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9746 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9747 };
9748
9749 /* Structure describing the image type XBM. */
9750
9751 static struct image_type xpm_type =
9752 {
9753 &Qxpm,
9754 xpm_image_p,
9755 xpm_load,
9756 x_clear_image,
9757 NULL
9758 };
9759
9760
9761 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
9762 for XPM images. Such a list must consist of conses whose car and
9763 cdr are strings. */
9764
9765 static int
9766 xpm_valid_color_symbols_p (color_symbols)
9767 Lisp_Object color_symbols;
9768 {
9769 while (CONSP (color_symbols))
9770 {
9771 Lisp_Object sym = XCAR (color_symbols);
9772 if (!CONSP (sym)
9773 || !STRINGP (XCAR (sym))
9774 || !STRINGP (XCDR (sym)))
9775 break;
9776 color_symbols = XCDR (color_symbols);
9777 }
9778
9779 return NILP (color_symbols);
9780 }
9781
9782
9783 /* Value is non-zero if OBJECT is a valid XPM image specification. */
9784
9785 static int
9786 xpm_image_p (object)
9787 Lisp_Object object;
9788 {
9789 struct image_keyword fmt[XPM_LAST];
9790 bcopy (xpm_format, fmt, sizeof fmt);
9791 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
9792 /* Either `:file' or `:data' must be present. */
9793 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
9794 /* Either no `:color-symbols' or it's a list of conses
9795 whose car and cdr are strings. */
9796 && (fmt[XPM_COLOR_SYMBOLS].count == 0
9797 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
9798 && (fmt[XPM_ASCENT].count == 0
9799 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
9800 }
9801
9802
9803 /* Load image IMG which will be displayed on frame F. Value is
9804 non-zero if successful. */
9805
9806 static int
9807 xpm_load (f, img)
9808 struct frame *f;
9809 struct image *img;
9810 {
9811 int rc, i;
9812 XpmAttributes attrs;
9813 Lisp_Object specified_file, color_symbols;
9814
9815 /* Configure the XPM lib. Use the visual of frame F. Allocate
9816 close colors. Return colors allocated. */
9817 bzero (&attrs, sizeof attrs);
9818 attrs.visual = FRAME_X_VISUAL (f);
9819 attrs.colormap = FRAME_X_COLORMAP (f);
9820 attrs.valuemask |= XpmVisual;
9821 attrs.valuemask |= XpmColormap;
9822 attrs.valuemask |= XpmReturnAllocPixels;
9823 #ifdef XpmAllocCloseColors
9824 attrs.alloc_close_colors = 1;
9825 attrs.valuemask |= XpmAllocCloseColors;
9826 #else
9827 attrs.closeness = 600;
9828 attrs.valuemask |= XpmCloseness;
9829 #endif
9830
9831 /* If image specification contains symbolic color definitions, add
9832 these to `attrs'. */
9833 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
9834 if (CONSP (color_symbols))
9835 {
9836 Lisp_Object tail;
9837 XpmColorSymbol *xpm_syms;
9838 int i, size;
9839
9840 attrs.valuemask |= XpmColorSymbols;
9841
9842 /* Count number of symbols. */
9843 attrs.numsymbols = 0;
9844 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
9845 ++attrs.numsymbols;
9846
9847 /* Allocate an XpmColorSymbol array. */
9848 size = attrs.numsymbols * sizeof *xpm_syms;
9849 xpm_syms = (XpmColorSymbol *) alloca (size);
9850 bzero (xpm_syms, size);
9851 attrs.colorsymbols = xpm_syms;
9852
9853 /* Fill the color symbol array. */
9854 for (tail = color_symbols, i = 0;
9855 CONSP (tail);
9856 ++i, tail = XCDR (tail))
9857 {
9858 Lisp_Object name = XCAR (XCAR (tail));
9859 Lisp_Object color = XCDR (XCAR (tail));
9860 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
9861 strcpy (xpm_syms[i].name, XSTRING (name)->data);
9862 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
9863 strcpy (xpm_syms[i].value, XSTRING (color)->data);
9864 }
9865 }
9866
9867 /* Create a pixmap for the image, either from a file, or from a
9868 string buffer containing data in the same format as an XPM file. */
9869 BLOCK_INPUT;
9870 specified_file = image_spec_value (img->spec, QCfile, NULL);
9871 if (STRINGP (specified_file))
9872 {
9873 Lisp_Object file = x_find_image_file (specified_file);
9874 if (!STRINGP (file))
9875 {
9876 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9877 UNBLOCK_INPUT;
9878 return 0;
9879 }
9880
9881 rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
9882 XSTRING (file)->data, &img->pixmap, &img->mask,
9883 &attrs);
9884 }
9885 else
9886 {
9887 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
9888 rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
9889 XSTRING (buffer)->data,
9890 &img->pixmap, &img->mask,
9891 &attrs);
9892 }
9893 UNBLOCK_INPUT;
9894
9895 if (rc == XpmSuccess)
9896 {
9897 /* Remember allocated colors. */
9898 img->ncolors = attrs.nalloc_pixels;
9899 img->colors = (unsigned long *) xmalloc (img->ncolors
9900 * sizeof *img->colors);
9901 for (i = 0; i < attrs.nalloc_pixels; ++i)
9902 img->colors[i] = attrs.alloc_pixels[i];
9903
9904 img->width = attrs.width;
9905 img->height = attrs.height;
9906 xassert (img->width > 0 && img->height > 0);
9907
9908 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
9909 BLOCK_INPUT;
9910 XpmFreeAttributes (&attrs);
9911 UNBLOCK_INPUT;
9912 }
9913 else
9914 {
9915 switch (rc)
9916 {
9917 case XpmOpenFailed:
9918 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
9919 break;
9920
9921 case XpmFileInvalid:
9922 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
9923 break;
9924
9925 case XpmNoMemory:
9926 image_error ("Out of memory (%s)", img->spec, Qnil);
9927 break;
9928
9929 case XpmColorFailed:
9930 image_error ("Color allocation error (%s)", img->spec, Qnil);
9931 break;
9932
9933 default:
9934 image_error ("Unknown error (%s)", img->spec, Qnil);
9935 break;
9936 }
9937 }
9938
9939 return rc == XpmSuccess;
9940 }
9941
9942 #endif /* HAVE_XPM != 0 */
9943
9944 \f
9945 #if 0 /* TODO : Color tables on W32. */
9946 /***********************************************************************
9947 Color table
9948 ***********************************************************************/
9949
9950 /* An entry in the color table mapping an RGB color to a pixel color. */
9951
9952 struct ct_color
9953 {
9954 int r, g, b;
9955 unsigned long pixel;
9956
9957 /* Next in color table collision list. */
9958 struct ct_color *next;
9959 };
9960
9961 /* The bucket vector size to use. Must be prime. */
9962
9963 #define CT_SIZE 101
9964
9965 /* Value is a hash of the RGB color given by R, G, and B. */
9966
9967 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
9968
9969 /* The color hash table. */
9970
9971 struct ct_color **ct_table;
9972
9973 /* Number of entries in the color table. */
9974
9975 int ct_colors_allocated;
9976
9977 /* Function prototypes. */
9978
9979 static void init_color_table P_ ((void));
9980 static void free_color_table P_ ((void));
9981 static unsigned long *colors_in_color_table P_ ((int *n));
9982 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
9983 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
9984
9985
9986 /* Initialize the color table. */
9987
9988 static void
9989 init_color_table ()
9990 {
9991 int size = CT_SIZE * sizeof (*ct_table);
9992 ct_table = (struct ct_color **) xmalloc (size);
9993 bzero (ct_table, size);
9994 ct_colors_allocated = 0;
9995 }
9996
9997
9998 /* Free memory associated with the color table. */
9999
10000 static void
10001 free_color_table ()
10002 {
10003 int i;
10004 struct ct_color *p, *next;
10005
10006 for (i = 0; i < CT_SIZE; ++i)
10007 for (p = ct_table[i]; p; p = next)
10008 {
10009 next = p->next;
10010 xfree (p);
10011 }
10012
10013 xfree (ct_table);
10014 ct_table = NULL;
10015 }
10016
10017
10018 /* Value is a pixel color for RGB color R, G, B on frame F. If an
10019 entry for that color already is in the color table, return the
10020 pixel color of that entry. Otherwise, allocate a new color for R,
10021 G, B, and make an entry in the color table. */
10022
10023 static unsigned long
10024 lookup_rgb_color (f, r, g, b)
10025 struct frame *f;
10026 int r, g, b;
10027 {
10028 unsigned hash = CT_HASH_RGB (r, g, b);
10029 int i = hash % CT_SIZE;
10030 struct ct_color *p;
10031
10032 for (p = ct_table[i]; p; p = p->next)
10033 if (p->r == r && p->g == g && p->b == b)
10034 break;
10035
10036 if (p == NULL)
10037 {
10038 COLORREF color;
10039 Colormap cmap;
10040 int rc;
10041
10042 color = PALETTERGB (r, g, b);
10043
10044 ++ct_colors_allocated;
10045
10046 p = (struct ct_color *) xmalloc (sizeof *p);
10047 p->r = r;
10048 p->g = g;
10049 p->b = b;
10050 p->pixel = color;
10051 p->next = ct_table[i];
10052 ct_table[i] = p;
10053 }
10054
10055 return p->pixel;
10056 }
10057
10058
10059 /* Look up pixel color PIXEL which is used on frame F in the color
10060 table. If not already present, allocate it. Value is PIXEL. */
10061
10062 static unsigned long
10063 lookup_pixel_color (f, pixel)
10064 struct frame *f;
10065 unsigned long pixel;
10066 {
10067 int i = pixel % CT_SIZE;
10068 struct ct_color *p;
10069
10070 for (p = ct_table[i]; p; p = p->next)
10071 if (p->pixel == pixel)
10072 break;
10073
10074 if (p == NULL)
10075 {
10076 XColor color;
10077 Colormap cmap;
10078 int rc;
10079
10080 BLOCK_INPUT;
10081
10082 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
10083 color.pixel = pixel;
10084 XQueryColor (NULL, cmap, &color);
10085 rc = x_alloc_nearest_color (f, cmap, &color);
10086 UNBLOCK_INPUT;
10087
10088 if (rc)
10089 {
10090 ++ct_colors_allocated;
10091
10092 p = (struct ct_color *) xmalloc (sizeof *p);
10093 p->r = color.red;
10094 p->g = color.green;
10095 p->b = color.blue;
10096 p->pixel = pixel;
10097 p->next = ct_table[i];
10098 ct_table[i] = p;
10099 }
10100 else
10101 return FRAME_FOREGROUND_PIXEL (f);
10102 }
10103 return p->pixel;
10104 }
10105
10106
10107 /* Value is a vector of all pixel colors contained in the color table,
10108 allocated via xmalloc. Set *N to the number of colors. */
10109
10110 static unsigned long *
10111 colors_in_color_table (n)
10112 int *n;
10113 {
10114 int i, j;
10115 struct ct_color *p;
10116 unsigned long *colors;
10117
10118 if (ct_colors_allocated == 0)
10119 {
10120 *n = 0;
10121 colors = NULL;
10122 }
10123 else
10124 {
10125 colors = (unsigned long *) xmalloc (ct_colors_allocated
10126 * sizeof *colors);
10127 *n = ct_colors_allocated;
10128
10129 for (i = j = 0; i < CT_SIZE; ++i)
10130 for (p = ct_table[i]; p; p = p->next)
10131 colors[j++] = p->pixel;
10132 }
10133
10134 return colors;
10135 }
10136
10137 #endif /* TODO */
10138
10139 \f
10140 /***********************************************************************
10141 Algorithms
10142 ***********************************************************************/
10143 #if 0 /* TODO: image support. */
10144 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
10145 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
10146 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
10147
10148 /* Non-zero means draw a cross on images having `:conversion
10149 disabled'. */
10150
10151 int cross_disabled_images;
10152
10153 /* Edge detection matrices for different edge-detection
10154 strategies. */
10155
10156 static int emboss_matrix[9] = {
10157 /* x - 1 x x + 1 */
10158 2, -1, 0, /* y - 1 */
10159 -1, 0, 1, /* y */
10160 0, 1, -2 /* y + 1 */
10161 };
10162
10163 static int laplace_matrix[9] = {
10164 /* x - 1 x x + 1 */
10165 1, 0, 0, /* y - 1 */
10166 0, 0, 0, /* y */
10167 0, 0, -1 /* y + 1 */
10168 };
10169
10170 /* Value is the intensity of the color whose red/green/blue values
10171 are R, G, and B. */
10172
10173 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
10174
10175
10176 /* On frame F, return an array of XColor structures describing image
10177 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
10178 non-zero means also fill the red/green/blue members of the XColor
10179 structures. Value is a pointer to the array of XColors structures,
10180 allocated with xmalloc; it must be freed by the caller. */
10181
10182 static XColor *
10183 x_to_xcolors (f, img, rgb_p)
10184 struct frame *f;
10185 struct image *img;
10186 int rgb_p;
10187 {
10188 int x, y;
10189 XColor *colors, *p;
10190 XImage *ximg;
10191
10192 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
10193
10194 /* Get the X image IMG->pixmap. */
10195 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10196 0, 0, img->width, img->height, ~0, ZPixmap);
10197
10198 /* Fill the `pixel' members of the XColor array. I wished there
10199 were an easy and portable way to circumvent XGetPixel. */
10200 p = colors;
10201 for (y = 0; y < img->height; ++y)
10202 {
10203 XColor *row = p;
10204
10205 for (x = 0; x < img->width; ++x, ++p)
10206 p->pixel = XGetPixel (ximg, x, y);
10207
10208 if (rgb_p)
10209 x_query_colors (f, row, img->width);
10210 }
10211
10212 XDestroyImage (ximg);
10213 return colors;
10214 }
10215
10216
10217 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
10218 RGB members are set. F is the frame on which this all happens.
10219 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
10220
10221 static void
10222 x_from_xcolors (f, img, colors)
10223 struct frame *f;
10224 struct image *img;
10225 XColor *colors;
10226 {
10227 int x, y;
10228 XImage *oimg;
10229 Pixmap pixmap;
10230 XColor *p;
10231
10232 init_color_table ();
10233
10234 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
10235 &oimg, &pixmap);
10236 p = colors;
10237 for (y = 0; y < img->height; ++y)
10238 for (x = 0; x < img->width; ++x, ++p)
10239 {
10240 unsigned long pixel;
10241 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
10242 XPutPixel (oimg, x, y, pixel);
10243 }
10244
10245 xfree (colors);
10246 x_clear_image_1 (f, img, 1, 0, 1);
10247
10248 x_put_x_image (f, oimg, pixmap, img->width, img->height);
10249 x_destroy_x_image (oimg);
10250 img->pixmap = pixmap;
10251 img->colors = colors_in_color_table (&img->ncolors);
10252 free_color_table ();
10253 }
10254
10255
10256 /* On frame F, perform edge-detection on image IMG.
10257
10258 MATRIX is a nine-element array specifying the transformation
10259 matrix. See emboss_matrix for an example.
10260
10261 COLOR_ADJUST is a color adjustment added to each pixel of the
10262 outgoing image. */
10263
10264 static void
10265 x_detect_edges (f, img, matrix, color_adjust)
10266 struct frame *f;
10267 struct image *img;
10268 int matrix[9], color_adjust;
10269 {
10270 XColor *colors = x_to_xcolors (f, img, 1);
10271 XColor *new, *p;
10272 int x, y, i, sum;
10273
10274 for (i = sum = 0; i < 9; ++i)
10275 sum += abs (matrix[i]);
10276
10277 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
10278
10279 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
10280
10281 for (y = 0; y < img->height; ++y)
10282 {
10283 p = COLOR (new, 0, y);
10284 p->red = p->green = p->blue = 0xffff/2;
10285 p = COLOR (new, img->width - 1, y);
10286 p->red = p->green = p->blue = 0xffff/2;
10287 }
10288
10289 for (x = 1; x < img->width - 1; ++x)
10290 {
10291 p = COLOR (new, x, 0);
10292 p->red = p->green = p->blue = 0xffff/2;
10293 p = COLOR (new, x, img->height - 1);
10294 p->red = p->green = p->blue = 0xffff/2;
10295 }
10296
10297 for (y = 1; y < img->height - 1; ++y)
10298 {
10299 p = COLOR (new, 1, y);
10300
10301 for (x = 1; x < img->width - 1; ++x, ++p)
10302 {
10303 int r, g, b, y1, x1;
10304
10305 r = g = b = i = 0;
10306 for (y1 = y - 1; y1 < y + 2; ++y1)
10307 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
10308 if (matrix[i])
10309 {
10310 XColor *t = COLOR (colors, x1, y1);
10311 r += matrix[i] * t->red;
10312 g += matrix[i] * t->green;
10313 b += matrix[i] * t->blue;
10314 }
10315
10316 r = (r / sum + color_adjust) & 0xffff;
10317 g = (g / sum + color_adjust) & 0xffff;
10318 b = (b / sum + color_adjust) & 0xffff;
10319 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
10320 }
10321 }
10322
10323 xfree (colors);
10324 x_from_xcolors (f, img, new);
10325
10326 #undef COLOR
10327 }
10328
10329
10330 /* Perform the pre-defined `emboss' edge-detection on image IMG
10331 on frame F. */
10332
10333 static void
10334 x_emboss (f, img)
10335 struct frame *f;
10336 struct image *img;
10337 {
10338 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
10339 }
10340
10341
10342 /* Transform image IMG which is used on frame F with a Laplace
10343 edge-detection algorithm. The result is an image that can be used
10344 to draw disabled buttons, for example. */
10345
10346 static void
10347 x_laplace (f, img)
10348 struct frame *f;
10349 struct image *img;
10350 {
10351 x_detect_edges (f, img, laplace_matrix, 45000);
10352 }
10353
10354
10355 /* Perform edge-detection on image IMG on frame F, with specified
10356 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
10357
10358 MATRIX must be either
10359
10360 - a list of at least 9 numbers in row-major form
10361 - a vector of at least 9 numbers
10362
10363 COLOR_ADJUST nil means use a default; otherwise it must be a
10364 number. */
10365
10366 static void
10367 x_edge_detection (f, img, matrix, color_adjust)
10368 struct frame *f;
10369 struct image *img;
10370 Lisp_Object matrix, color_adjust;
10371 {
10372 int i = 0;
10373 int trans[9];
10374
10375 if (CONSP (matrix))
10376 {
10377 for (i = 0;
10378 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
10379 ++i, matrix = XCDR (matrix))
10380 trans[i] = XFLOATINT (XCAR (matrix));
10381 }
10382 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
10383 {
10384 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
10385 trans[i] = XFLOATINT (AREF (matrix, i));
10386 }
10387
10388 if (NILP (color_adjust))
10389 color_adjust = make_number (0xffff / 2);
10390
10391 if (i == 9 && NUMBERP (color_adjust))
10392 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
10393 }
10394
10395
10396 /* Transform image IMG on frame F so that it looks disabled. */
10397
10398 static void
10399 x_disable_image (f, img)
10400 struct frame *f;
10401 struct image *img;
10402 {
10403 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10404
10405 if (dpyinfo->n_planes >= 2)
10406 {
10407 /* Color (or grayscale). Convert to gray, and equalize. Just
10408 drawing such images with a stipple can look very odd, so
10409 we're using this method instead. */
10410 XColor *colors = x_to_xcolors (f, img, 1);
10411 XColor *p, *end;
10412 const int h = 15000;
10413 const int l = 30000;
10414
10415 for (p = colors, end = colors + img->width * img->height;
10416 p < end;
10417 ++p)
10418 {
10419 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
10420 int i2 = (0xffff - h - l) * i / 0xffff + l;
10421 p->red = p->green = p->blue = i2;
10422 }
10423
10424 x_from_xcolors (f, img, colors);
10425 }
10426
10427 /* Draw a cross over the disabled image, if we must or if we
10428 should. */
10429 if (dpyinfo->n_planes < 2 || cross_disabled_images)
10430 {
10431 Display *dpy = FRAME_X_DISPLAY (f);
10432 GC gc;
10433
10434 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
10435 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
10436 XDrawLine (dpy, img->pixmap, gc, 0, 0,
10437 img->width - 1, img->height - 1);
10438 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
10439 img->width - 1, 0);
10440 XFreeGC (dpy, gc);
10441
10442 if (img->mask)
10443 {
10444 gc = XCreateGC (dpy, img->mask, 0, NULL);
10445 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
10446 XDrawLine (dpy, img->mask, gc, 0, 0,
10447 img->width - 1, img->height - 1);
10448 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
10449 img->width - 1, 0);
10450 XFreeGC (dpy, gc);
10451 }
10452 }
10453 }
10454
10455
10456 /* Build a mask for image IMG which is used on frame F. FILE is the
10457 name of an image file, for error messages. HOW determines how to
10458 determine the background color of IMG. If it is a list '(R G B)',
10459 with R, G, and B being integers >= 0, take that as the color of the
10460 background. Otherwise, determine the background color of IMG
10461 heuristically. Value is non-zero if successful. */
10462
10463 static int
10464 x_build_heuristic_mask (f, img, how)
10465 struct frame *f;
10466 struct image *img;
10467 Lisp_Object how;
10468 {
10469 Display *dpy = FRAME_W32_DISPLAY (f);
10470 XImage *ximg, *mask_img;
10471 int x, y, rc, use_img_background;
10472 unsigned long bg = 0;
10473
10474 if (img->mask)
10475 {
10476 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
10477 img->mask = None;
10478 img->background_transparent_valid = 0;
10479 }
10480
10481 /* Create an image and pixmap serving as mask. */
10482 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
10483 &mask_img, &img->mask);
10484 if (!rc)
10485 return 0;
10486
10487 /* Get the X image of IMG->pixmap. */
10488 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
10489 ~0, ZPixmap);
10490
10491 /* Determine the background color of ximg. If HOW is `(R G B)'
10492 take that as color. Otherwise, use the image's background color. */
10493 use_img_background = 1;
10494
10495 if (CONSP (how))
10496 {
10497 int rgb[3], i;
10498
10499 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
10500 {
10501 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
10502 how = XCDR (how);
10503 }
10504
10505 if (i == 3 && NILP (how))
10506 {
10507 char color_name[30];
10508 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
10509 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
10510 use_img_background = 0;
10511 }
10512 }
10513
10514 if (use_img_background)
10515 bg = four_corners_best (ximg, img->width, img->height);
10516
10517 /* Set all bits in mask_img to 1 whose color in ximg is different
10518 from the background color bg. */
10519 for (y = 0; y < img->height; ++y)
10520 for (x = 0; x < img->width; ++x)
10521 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
10522
10523 /* Fill in the background_transparent field while we have the mask handy. */
10524 image_background_transparent (img, f, mask_img);
10525
10526 /* Put mask_img into img->mask. */
10527 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
10528 x_destroy_x_image (mask_img);
10529 XDestroyImage (ximg);
10530
10531 return 1;
10532 }
10533 #endif /* TODO */
10534
10535 \f
10536 /***********************************************************************
10537 PBM (mono, gray, color)
10538 ***********************************************************************/
10539 #ifdef HAVE_PBM
10540
10541 static int pbm_image_p P_ ((Lisp_Object object));
10542 static int pbm_load P_ ((struct frame *f, struct image *img));
10543 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
10544
10545 /* The symbol `pbm' identifying images of this type. */
10546
10547 Lisp_Object Qpbm;
10548
10549 /* Indices of image specification fields in gs_format, below. */
10550
10551 enum pbm_keyword_index
10552 {
10553 PBM_TYPE,
10554 PBM_FILE,
10555 PBM_DATA,
10556 PBM_ASCENT,
10557 PBM_MARGIN,
10558 PBM_RELIEF,
10559 PBM_ALGORITHM,
10560 PBM_HEURISTIC_MASK,
10561 PBM_MASK,
10562 PBM_FOREGROUND,
10563 PBM_BACKGROUND,
10564 PBM_LAST
10565 };
10566
10567 /* Vector of image_keyword structures describing the format
10568 of valid user-defined image specifications. */
10569
10570 static struct image_keyword pbm_format[PBM_LAST] =
10571 {
10572 {":type", IMAGE_SYMBOL_VALUE, 1},
10573 {":file", IMAGE_STRING_VALUE, 0},
10574 {":data", IMAGE_STRING_VALUE, 0},
10575 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
10576 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10577 {":relief", IMAGE_INTEGER_VALUE, 0},
10578 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10579 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10580 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10581 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
10582 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10583 };
10584
10585 /* Structure describing the image type `pbm'. */
10586
10587 static struct image_type pbm_type =
10588 {
10589 &Qpbm,
10590 pbm_image_p,
10591 pbm_load,
10592 x_clear_image,
10593 NULL
10594 };
10595
10596
10597 /* Return non-zero if OBJECT is a valid PBM image specification. */
10598
10599 static int
10600 pbm_image_p (object)
10601 Lisp_Object object;
10602 {
10603 struct image_keyword fmt[PBM_LAST];
10604
10605 bcopy (pbm_format, fmt, sizeof fmt);
10606
10607 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
10608 || (fmt[PBM_ASCENT].count
10609 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
10610 return 0;
10611
10612 /* Must specify either :data or :file. */
10613 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
10614 }
10615
10616
10617 /* Scan a decimal number from *S and return it. Advance *S while
10618 reading the number. END is the end of the string. Value is -1 at
10619 end of input. */
10620
10621 static int
10622 pbm_scan_number (s, end)
10623 unsigned char **s, *end;
10624 {
10625 int c, val = -1;
10626
10627 while (*s < end)
10628 {
10629 /* Skip white-space. */
10630 while (*s < end && (c = *(*s)++, isspace (c)))
10631 ;
10632
10633 if (c == '#')
10634 {
10635 /* Skip comment to end of line. */
10636 while (*s < end && (c = *(*s)++, c != '\n'))
10637 ;
10638 }
10639 else if (isdigit (c))
10640 {
10641 /* Read decimal number. */
10642 val = c - '0';
10643 while (*s < end && (c = *(*s)++, isdigit (c)))
10644 val = 10 * val + c - '0';
10645 break;
10646 }
10647 else
10648 break;
10649 }
10650
10651 return val;
10652 }
10653
10654
10655 /* Read FILE into memory. Value is a pointer to a buffer allocated
10656 with xmalloc holding FILE's contents. Value is null if an error
10657 occured. *SIZE is set to the size of the file. */
10658
10659 static char *
10660 pbm_read_file (file, size)
10661 Lisp_Object file;
10662 int *size;
10663 {
10664 FILE *fp = NULL;
10665 char *buf = NULL;
10666 struct stat st;
10667
10668 if (stat (XSTRING (file)->data, &st) == 0
10669 && (fp = fopen (XSTRING (file)->data, "r")) != NULL
10670 && (buf = (char *) xmalloc (st.st_size),
10671 fread (buf, 1, st.st_size, fp) == st.st_size))
10672 {
10673 *size = st.st_size;
10674 fclose (fp);
10675 }
10676 else
10677 {
10678 if (fp)
10679 fclose (fp);
10680 if (buf)
10681 {
10682 xfree (buf);
10683 buf = NULL;
10684 }
10685 }
10686
10687 return buf;
10688 }
10689
10690
10691 /* Load PBM image IMG for use on frame F. */
10692
10693 static int
10694 pbm_load (f, img)
10695 struct frame *f;
10696 struct image *img;
10697 {
10698 int raw_p, x, y;
10699 int width, height, max_color_idx = 0;
10700 XImage *ximg;
10701 Lisp_Object file, specified_file;
10702 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
10703 struct gcpro gcpro1;
10704 unsigned char *contents = NULL;
10705 unsigned char *end, *p;
10706 int size;
10707
10708 specified_file = image_spec_value (img->spec, QCfile, NULL);
10709 file = Qnil;
10710 GCPRO1 (file);
10711
10712 if (STRINGP (specified_file))
10713 {
10714 file = x_find_image_file (specified_file);
10715 if (!STRINGP (file))
10716 {
10717 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10718 UNGCPRO;
10719 return 0;
10720 }
10721
10722 contents = slurp_file (XSTRING (file)->data, &size);
10723 if (contents == NULL)
10724 {
10725 image_error ("Error reading `%s'", file, Qnil);
10726 UNGCPRO;
10727 return 0;
10728 }
10729
10730 p = contents;
10731 end = contents + size;
10732 }
10733 else
10734 {
10735 Lisp_Object data;
10736 data = image_spec_value (img->spec, QCdata, NULL);
10737 p = XSTRING (data)->data;
10738 end = p + STRING_BYTES (XSTRING (data));
10739 }
10740
10741 /* Check magic number. */
10742 if (end - p < 2 || *p++ != 'P')
10743 {
10744 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
10745 error:
10746 xfree (contents);
10747 UNGCPRO;
10748 return 0;
10749 }
10750
10751 switch (*p++)
10752 {
10753 case '1':
10754 raw_p = 0, type = PBM_MONO;
10755 break;
10756
10757 case '2':
10758 raw_p = 0, type = PBM_GRAY;
10759 break;
10760
10761 case '3':
10762 raw_p = 0, type = PBM_COLOR;
10763 break;
10764
10765 case '4':
10766 raw_p = 1, type = PBM_MONO;
10767 break;
10768
10769 case '5':
10770 raw_p = 1, type = PBM_GRAY;
10771 break;
10772
10773 case '6':
10774 raw_p = 1, type = PBM_COLOR;
10775 break;
10776
10777 default:
10778 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
10779 goto error;
10780 }
10781
10782 /* Read width, height, maximum color-component. Characters
10783 starting with `#' up to the end of a line are ignored. */
10784 width = pbm_scan_number (&p, end);
10785 height = pbm_scan_number (&p, end);
10786
10787 if (type != PBM_MONO)
10788 {
10789 max_color_idx = pbm_scan_number (&p, end);
10790 if (raw_p && max_color_idx > 255)
10791 max_color_idx = 255;
10792 }
10793
10794 if (width < 0
10795 || height < 0
10796 || (type != PBM_MONO && max_color_idx < 0))
10797 goto error;
10798
10799 if (!x_create_x_image_and_pixmap (f, width, height, 0,
10800 &ximg, &img->pixmap))
10801 goto error;
10802
10803 /* Initialize the color hash table. */
10804 init_color_table ();
10805
10806 if (type == PBM_MONO)
10807 {
10808 int c = 0, g;
10809 struct image_keyword fmt[PBM_LAST];
10810 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
10811 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
10812
10813 /* Parse the image specification. */
10814 bcopy (pbm_format, fmt, sizeof fmt);
10815 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
10816
10817 /* Get foreground and background colors, maybe allocate colors. */
10818 if (fmt[PBM_FOREGROUND].count
10819 && STRINGP (fmt[PBM_FOREGROUND].value))
10820 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
10821 if (fmt[PBM_BACKGROUND].count
10822 && STRINGP (fmt[PBM_BACKGROUND].value))
10823 {
10824 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
10825 img->background = bg;
10826 img->background_valid = 1;
10827 }
10828
10829 for (y = 0; y < height; ++y)
10830 for (x = 0; x < width; ++x)
10831 {
10832 if (raw_p)
10833 {
10834 if ((x & 7) == 0)
10835 c = *p++;
10836 g = c & 0x80;
10837 c <<= 1;
10838 }
10839 else
10840 g = pbm_scan_number (&p, end);
10841
10842 XPutPixel (ximg, x, y, g ? fg : bg);
10843 }
10844 }
10845 else
10846 {
10847 for (y = 0; y < height; ++y)
10848 for (x = 0; x < width; ++x)
10849 {
10850 int r, g, b;
10851
10852 if (type == PBM_GRAY)
10853 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
10854 else if (raw_p)
10855 {
10856 r = *p++;
10857 g = *p++;
10858 b = *p++;
10859 }
10860 else
10861 {
10862 r = pbm_scan_number (&p, end);
10863 g = pbm_scan_number (&p, end);
10864 b = pbm_scan_number (&p, end);
10865 }
10866
10867 if (r < 0 || g < 0 || b < 0)
10868 {
10869 xfree (ximg->data);
10870 ximg->data = NULL;
10871 XDestroyImage (ximg);
10872 image_error ("Invalid pixel value in image `%s'",
10873 img->spec, Qnil);
10874 goto error;
10875 }
10876
10877 /* RGB values are now in the range 0..max_color_idx.
10878 Scale this to the range 0..0xffff supported by X. */
10879 r = (double) r * 65535 / max_color_idx;
10880 g = (double) g * 65535 / max_color_idx;
10881 b = (double) b * 65535 / max_color_idx;
10882 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
10883 }
10884 }
10885
10886 /* Store in IMG->colors the colors allocated for the image, and
10887 free the color table. */
10888 img->colors = colors_in_color_table (&img->ncolors);
10889 free_color_table ();
10890
10891 /* Maybe fill in the background field while we have ximg handy. */
10892 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10893 IMAGE_BACKGROUND (img, f, ximg);
10894
10895 /* Put the image into a pixmap. */
10896 x_put_x_image (f, ximg, img->pixmap, width, height);
10897 x_destroy_x_image (ximg);
10898
10899 img->width = width;
10900 img->height = height;
10901
10902 UNGCPRO;
10903 xfree (contents);
10904 return 1;
10905 }
10906 #endif /* HAVE_PBM */
10907
10908 \f
10909 /***********************************************************************
10910 PNG
10911 ***********************************************************************/
10912
10913 #if HAVE_PNG
10914
10915 #include <png.h>
10916
10917 /* Function prototypes. */
10918
10919 static int png_image_p P_ ((Lisp_Object object));
10920 static int png_load P_ ((struct frame *f, struct image *img));
10921
10922 /* The symbol `png' identifying images of this type. */
10923
10924 Lisp_Object Qpng;
10925
10926 /* Indices of image specification fields in png_format, below. */
10927
10928 enum png_keyword_index
10929 {
10930 PNG_TYPE,
10931 PNG_DATA,
10932 PNG_FILE,
10933 PNG_ASCENT,
10934 PNG_MARGIN,
10935 PNG_RELIEF,
10936 PNG_ALGORITHM,
10937 PNG_HEURISTIC_MASK,
10938 PNG_MASK,
10939 PNG_BACKGROUND,
10940 PNG_LAST
10941 };
10942
10943 /* Vector of image_keyword structures describing the format
10944 of valid user-defined image specifications. */
10945
10946 static struct image_keyword png_format[PNG_LAST] =
10947 {
10948 {":type", IMAGE_SYMBOL_VALUE, 1},
10949 {":data", IMAGE_STRING_VALUE, 0},
10950 {":file", IMAGE_STRING_VALUE, 0},
10951 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
10952 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10953 {":relief", IMAGE_INTEGER_VALUE, 0},
10954 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10955 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10956 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10957 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10958 };
10959
10960 /* Structure describing the image type `png'. */
10961
10962 static struct image_type png_type =
10963 {
10964 &Qpng,
10965 png_image_p,
10966 png_load,
10967 x_clear_image,
10968 NULL
10969 };
10970
10971
10972 /* Return non-zero if OBJECT is a valid PNG image specification. */
10973
10974 static int
10975 png_image_p (object)
10976 Lisp_Object object;
10977 {
10978 struct image_keyword fmt[PNG_LAST];
10979 bcopy (png_format, fmt, sizeof fmt);
10980
10981 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
10982 || (fmt[PNG_ASCENT].count
10983 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
10984 return 0;
10985
10986 /* Must specify either the :data or :file keyword. */
10987 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
10988 }
10989
10990
10991 /* Error and warning handlers installed when the PNG library
10992 is initialized. */
10993
10994 static void
10995 my_png_error (png_ptr, msg)
10996 png_struct *png_ptr;
10997 char *msg;
10998 {
10999 xassert (png_ptr != NULL);
11000 image_error ("PNG error: %s", build_string (msg), Qnil);
11001 longjmp (png_ptr->jmpbuf, 1);
11002 }
11003
11004
11005 static void
11006 my_png_warning (png_ptr, msg)
11007 png_struct *png_ptr;
11008 char *msg;
11009 {
11010 xassert (png_ptr != NULL);
11011 image_error ("PNG warning: %s", build_string (msg), Qnil);
11012 }
11013
11014 /* Memory source for PNG decoding. */
11015
11016 struct png_memory_storage
11017 {
11018 unsigned char *bytes; /* The data */
11019 size_t len; /* How big is it? */
11020 int index; /* Where are we? */
11021 };
11022
11023
11024 /* Function set as reader function when reading PNG image from memory.
11025 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
11026 bytes from the input to DATA. */
11027
11028 static void
11029 png_read_from_memory (png_ptr, data, length)
11030 png_structp png_ptr;
11031 png_bytep data;
11032 png_size_t length;
11033 {
11034 struct png_memory_storage *tbr
11035 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
11036
11037 if (length > tbr->len - tbr->index)
11038 png_error (png_ptr, "Read error");
11039
11040 bcopy (tbr->bytes + tbr->index, data, length);
11041 tbr->index = tbr->index + length;
11042 }
11043
11044 /* Load PNG image IMG for use on frame F. Value is non-zero if
11045 successful. */
11046
11047 static int
11048 png_load (f, img)
11049 struct frame *f;
11050 struct image *img;
11051 {
11052 Lisp_Object file, specified_file;
11053 Lisp_Object specified_data;
11054 int x, y, i;
11055 XImage *ximg, *mask_img = NULL;
11056 struct gcpro gcpro1;
11057 png_struct *png_ptr = NULL;
11058 png_info *info_ptr = NULL, *end_info = NULL;
11059 FILE *volatile fp = NULL;
11060 png_byte sig[8];
11061 png_byte *volatile pixels = NULL;
11062 png_byte **volatile rows = NULL;
11063 png_uint_32 width, height;
11064 int bit_depth, color_type, interlace_type;
11065 png_byte channels;
11066 png_uint_32 row_bytes;
11067 int transparent_p;
11068 char *gamma_str;
11069 double screen_gamma, image_gamma;
11070 int intent;
11071 struct png_memory_storage tbr; /* Data to be read */
11072
11073 /* Find out what file to load. */
11074 specified_file = image_spec_value (img->spec, QCfile, NULL);
11075 specified_data = image_spec_value (img->spec, QCdata, NULL);
11076 file = Qnil;
11077 GCPRO1 (file);
11078
11079 if (NILP (specified_data))
11080 {
11081 file = x_find_image_file (specified_file);
11082 if (!STRINGP (file))
11083 {
11084 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11085 UNGCPRO;
11086 return 0;
11087 }
11088
11089 /* Open the image file. */
11090 fp = fopen (XSTRING (file)->data, "rb");
11091 if (!fp)
11092 {
11093 image_error ("Cannot open image file `%s'", file, Qnil);
11094 UNGCPRO;
11095 fclose (fp);
11096 return 0;
11097 }
11098
11099 /* Check PNG signature. */
11100 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
11101 || !png_check_sig (sig, sizeof sig))
11102 {
11103 image_error ("Not a PNG file:` %s'", file, Qnil);
11104 UNGCPRO;
11105 fclose (fp);
11106 return 0;
11107 }
11108 }
11109 else
11110 {
11111 /* Read from memory. */
11112 tbr.bytes = XSTRING (specified_data)->data;
11113 tbr.len = STRING_BYTES (XSTRING (specified_data));
11114 tbr.index = 0;
11115
11116 /* Check PNG signature. */
11117 if (tbr.len < sizeof sig
11118 || !png_check_sig (tbr.bytes, sizeof sig))
11119 {
11120 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
11121 UNGCPRO;
11122 return 0;
11123 }
11124
11125 /* Need to skip past the signature. */
11126 tbr.bytes += sizeof (sig);
11127 }
11128
11129 /* Initialize read and info structs for PNG lib. */
11130 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
11131 my_png_error, my_png_warning);
11132 if (!png_ptr)
11133 {
11134 if (fp) fclose (fp);
11135 UNGCPRO;
11136 return 0;
11137 }
11138
11139 info_ptr = png_create_info_struct (png_ptr);
11140 if (!info_ptr)
11141 {
11142 png_destroy_read_struct (&png_ptr, NULL, NULL);
11143 if (fp) fclose (fp);
11144 UNGCPRO;
11145 return 0;
11146 }
11147
11148 end_info = png_create_info_struct (png_ptr);
11149 if (!end_info)
11150 {
11151 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
11152 if (fp) fclose (fp);
11153 UNGCPRO;
11154 return 0;
11155 }
11156
11157 /* Set error jump-back. We come back here when the PNG library
11158 detects an error. */
11159 if (setjmp (png_ptr->jmpbuf))
11160 {
11161 error:
11162 if (png_ptr)
11163 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
11164 xfree (pixels);
11165 xfree (rows);
11166 if (fp) fclose (fp);
11167 UNGCPRO;
11168 return 0;
11169 }
11170
11171 /* Read image info. */
11172 if (!NILP (specified_data))
11173 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
11174 else
11175 png_init_io (png_ptr, fp);
11176
11177 png_set_sig_bytes (png_ptr, sizeof sig);
11178 png_read_info (png_ptr, info_ptr);
11179 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
11180 &interlace_type, NULL, NULL);
11181
11182 /* If image contains simply transparency data, we prefer to
11183 construct a clipping mask. */
11184 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
11185 transparent_p = 1;
11186 else
11187 transparent_p = 0;
11188
11189 /* This function is easier to write if we only have to handle
11190 one data format: RGB or RGBA with 8 bits per channel. Let's
11191 transform other formats into that format. */
11192
11193 /* Strip more than 8 bits per channel. */
11194 if (bit_depth == 16)
11195 png_set_strip_16 (png_ptr);
11196
11197 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
11198 if available. */
11199 png_set_expand (png_ptr);
11200
11201 /* Convert grayscale images to RGB. */
11202 if (color_type == PNG_COLOR_TYPE_GRAY
11203 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
11204 png_set_gray_to_rgb (png_ptr);
11205
11206 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
11207 gamma_str = getenv ("SCREEN_GAMMA");
11208 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
11209
11210 /* Tell the PNG lib to handle gamma correction for us. */
11211
11212 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
11213 if (png_get_sRGB (png_ptr, info_ptr, &intent))
11214 /* There is a special chunk in the image specifying the gamma. */
11215 png_set_sRGB (png_ptr, info_ptr, intent);
11216 else
11217 #endif
11218 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
11219 /* Image contains gamma information. */
11220 png_set_gamma (png_ptr, screen_gamma, image_gamma);
11221 else
11222 /* Use a default of 0.5 for the image gamma. */
11223 png_set_gamma (png_ptr, screen_gamma, 0.5);
11224
11225 /* Handle alpha channel by combining the image with a background
11226 color. Do this only if a real alpha channel is supplied. For
11227 simple transparency, we prefer a clipping mask. */
11228 if (!transparent_p)
11229 {
11230 png_color_16 *image_background;
11231 Lisp_Object specified_bg
11232 = image_spec_value (img->spec, QCbackground, NULL);
11233
11234
11235 if (STRINGP (specified_bg))
11236 /* The user specified `:background', use that. */
11237 {
11238 COLORREF color;
11239 if (w32_defined_color (f, XSTRING (specified_bg)->data, &color, 0))
11240 {
11241 png_color_16 user_bg;
11242
11243 bzero (&user_bg, sizeof user_bg);
11244 user_bg.red = color.red;
11245 user_bg.green = color.green;
11246 user_bg.blue = color.blue;
11247
11248 png_set_background (png_ptr, &user_bg,
11249 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
11250 }
11251 }
11252 else if (png_get_bKGD (png_ptr, info_ptr, &image_background))
11253 /* Image contains a background color with which to
11254 combine the image. */
11255 png_set_background (png_ptr, image_background,
11256 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
11257 else
11258 {
11259 /* Image does not contain a background color with which
11260 to combine the image data via an alpha channel. Use
11261 the frame's background instead. */
11262 XColor color;
11263 Colormap cmap;
11264 png_color_16 frame_background;
11265
11266 cmap = FRAME_X_COLORMAP (f);
11267 color.pixel = FRAME_BACKGROUND_PIXEL (f);
11268 x_query_color (f, &color);
11269
11270 bzero (&frame_background, sizeof frame_background);
11271 frame_background.red = color.red;
11272 frame_background.green = color.green;
11273 frame_background.blue = color.blue;
11274
11275 png_set_background (png_ptr, &frame_background,
11276 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
11277 }
11278 }
11279
11280 /* Update info structure. */
11281 png_read_update_info (png_ptr, info_ptr);
11282
11283 /* Get number of channels. Valid values are 1 for grayscale images
11284 and images with a palette, 2 for grayscale images with transparency
11285 information (alpha channel), 3 for RGB images, and 4 for RGB
11286 images with alpha channel, i.e. RGBA. If conversions above were
11287 sufficient we should only have 3 or 4 channels here. */
11288 channels = png_get_channels (png_ptr, info_ptr);
11289 xassert (channels == 3 || channels == 4);
11290
11291 /* Number of bytes needed for one row of the image. */
11292 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
11293
11294 /* Allocate memory for the image. */
11295 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
11296 rows = (png_byte **) xmalloc (height * sizeof *rows);
11297 for (i = 0; i < height; ++i)
11298 rows[i] = pixels + i * row_bytes;
11299
11300 /* Read the entire image. */
11301 png_read_image (png_ptr, rows);
11302 png_read_end (png_ptr, info_ptr);
11303 if (fp)
11304 {
11305 fclose (fp);
11306 fp = NULL;
11307 }
11308
11309 /* Create the X image and pixmap. */
11310 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
11311 &img->pixmap))
11312 goto error;
11313
11314 /* Create an image and pixmap serving as mask if the PNG image
11315 contains an alpha channel. */
11316 if (channels == 4
11317 && !transparent_p
11318 && !x_create_x_image_and_pixmap (f, width, height, 1,
11319 &mask_img, &img->mask))
11320 {
11321 x_destroy_x_image (ximg);
11322 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
11323 img->pixmap = 0;
11324 goto error;
11325 }
11326
11327 /* Fill the X image and mask from PNG data. */
11328 init_color_table ();
11329
11330 for (y = 0; y < height; ++y)
11331 {
11332 png_byte *p = rows[y];
11333
11334 for (x = 0; x < width; ++x)
11335 {
11336 unsigned r, g, b;
11337
11338 r = *p++ << 8;
11339 g = *p++ << 8;
11340 b = *p++ << 8;
11341 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
11342
11343 /* An alpha channel, aka mask channel, associates variable
11344 transparency with an image. Where other image formats
11345 support binary transparency---fully transparent or fully
11346 opaque---PNG allows up to 254 levels of partial transparency.
11347 The PNG library implements partial transparency by combining
11348 the image with a specified background color.
11349
11350 I'm not sure how to handle this here nicely: because the
11351 background on which the image is displayed may change, for
11352 real alpha channel support, it would be necessary to create
11353 a new image for each possible background.
11354
11355 What I'm doing now is that a mask is created if we have
11356 boolean transparency information. Otherwise I'm using
11357 the frame's background color to combine the image with. */
11358
11359 if (channels == 4)
11360 {
11361 if (mask_img)
11362 XPutPixel (mask_img, x, y, *p > 0);
11363 ++p;
11364 }
11365 }
11366 }
11367
11368 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11369 /* Set IMG's background color from the PNG image, unless the user
11370 overrode it. */
11371 {
11372 png_color_16 *bg;
11373 if (png_get_bKGD (png_ptr, info_ptr, &bg))
11374 {
11375 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
11376 img->background_valid = 1;
11377 }
11378 }
11379
11380 /* Remember colors allocated for this image. */
11381 img->colors = colors_in_color_table (&img->ncolors);
11382 free_color_table ();
11383
11384 /* Clean up. */
11385 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
11386 xfree (rows);
11387 xfree (pixels);
11388
11389 img->width = width;
11390 img->height = height;
11391
11392 /* Maybe fill in the background field while we have ximg handy. */
11393 IMAGE_BACKGROUND (img, f, ximg);
11394
11395 /* Put the image into the pixmap, then free the X image and its buffer. */
11396 x_put_x_image (f, ximg, img->pixmap, width, height);
11397 x_destroy_x_image (ximg);
11398
11399 /* Same for the mask. */
11400 if (mask_img)
11401 {
11402 /* Fill in the background_transparent field while we have the mask
11403 handy. */
11404 image_background_transparent (img, f, mask_img);
11405
11406 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
11407 x_destroy_x_image (mask_img);
11408 }
11409
11410 UNGCPRO;
11411 return 1;
11412 }
11413
11414 #endif /* HAVE_PNG != 0 */
11415
11416
11417 \f
11418 /***********************************************************************
11419 JPEG
11420 ***********************************************************************/
11421
11422 #if HAVE_JPEG
11423
11424 /* Work around a warning about HAVE_STDLIB_H being redefined in
11425 jconfig.h. */
11426 #ifdef HAVE_STDLIB_H
11427 #define HAVE_STDLIB_H_1
11428 #undef HAVE_STDLIB_H
11429 #endif /* HAVE_STLIB_H */
11430
11431 #include <jpeglib.h>
11432 #include <jerror.h>
11433 #include <setjmp.h>
11434
11435 #ifdef HAVE_STLIB_H_1
11436 #define HAVE_STDLIB_H 1
11437 #endif
11438
11439 static int jpeg_image_p P_ ((Lisp_Object object));
11440 static int jpeg_load P_ ((struct frame *f, struct image *img));
11441
11442 /* The symbol `jpeg' identifying images of this type. */
11443
11444 Lisp_Object Qjpeg;
11445
11446 /* Indices of image specification fields in gs_format, below. */
11447
11448 enum jpeg_keyword_index
11449 {
11450 JPEG_TYPE,
11451 JPEG_DATA,
11452 JPEG_FILE,
11453 JPEG_ASCENT,
11454 JPEG_MARGIN,
11455 JPEG_RELIEF,
11456 JPEG_ALGORITHM,
11457 JPEG_HEURISTIC_MASK,
11458 JPEG_MASK,
11459 JPEG_BACKGROUND,
11460 JPEG_LAST
11461 };
11462
11463 /* Vector of image_keyword structures describing the format
11464 of valid user-defined image specifications. */
11465
11466 static struct image_keyword jpeg_format[JPEG_LAST] =
11467 {
11468 {":type", IMAGE_SYMBOL_VALUE, 1},
11469 {":data", IMAGE_STRING_VALUE, 0},
11470 {":file", IMAGE_STRING_VALUE, 0},
11471 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
11472 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11473 {":relief", IMAGE_INTEGER_VALUE, 0},
11474 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11475 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11476 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11477 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11478 };
11479
11480 /* Structure describing the image type `jpeg'. */
11481
11482 static struct image_type jpeg_type =
11483 {
11484 &Qjpeg,
11485 jpeg_image_p,
11486 jpeg_load,
11487 x_clear_image,
11488 NULL
11489 };
11490
11491
11492 /* Return non-zero if OBJECT is a valid JPEG image specification. */
11493
11494 static int
11495 jpeg_image_p (object)
11496 Lisp_Object object;
11497 {
11498 struct image_keyword fmt[JPEG_LAST];
11499
11500 bcopy (jpeg_format, fmt, sizeof fmt);
11501
11502 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
11503 || (fmt[JPEG_ASCENT].count
11504 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
11505 return 0;
11506
11507 /* Must specify either the :data or :file keyword. */
11508 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
11509 }
11510
11511
11512 struct my_jpeg_error_mgr
11513 {
11514 struct jpeg_error_mgr pub;
11515 jmp_buf setjmp_buffer;
11516 };
11517
11518 static void
11519 my_error_exit (cinfo)
11520 j_common_ptr cinfo;
11521 {
11522 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
11523 longjmp (mgr->setjmp_buffer, 1);
11524 }
11525
11526 /* Init source method for JPEG data source manager. Called by
11527 jpeg_read_header() before any data is actually read. See
11528 libjpeg.doc from the JPEG lib distribution. */
11529
11530 static void
11531 our_init_source (cinfo)
11532 j_decompress_ptr cinfo;
11533 {
11534 }
11535
11536
11537 /* Fill input buffer method for JPEG data source manager. Called
11538 whenever more data is needed. We read the whole image in one step,
11539 so this only adds a fake end of input marker at the end. */
11540
11541 static boolean
11542 our_fill_input_buffer (cinfo)
11543 j_decompress_ptr cinfo;
11544 {
11545 /* Insert a fake EOI marker. */
11546 struct jpeg_source_mgr *src = cinfo->src;
11547 static JOCTET buffer[2];
11548
11549 buffer[0] = (JOCTET) 0xFF;
11550 buffer[1] = (JOCTET) JPEG_EOI;
11551
11552 src->next_input_byte = buffer;
11553 src->bytes_in_buffer = 2;
11554 return TRUE;
11555 }
11556
11557
11558 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
11559 is the JPEG data source manager. */
11560
11561 static void
11562 our_skip_input_data (cinfo, num_bytes)
11563 j_decompress_ptr cinfo;
11564 long num_bytes;
11565 {
11566 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
11567
11568 if (src)
11569 {
11570 if (num_bytes > src->bytes_in_buffer)
11571 ERREXIT (cinfo, JERR_INPUT_EOF);
11572
11573 src->bytes_in_buffer -= num_bytes;
11574 src->next_input_byte += num_bytes;
11575 }
11576 }
11577
11578
11579 /* Method to terminate data source. Called by
11580 jpeg_finish_decompress() after all data has been processed. */
11581
11582 static void
11583 our_term_source (cinfo)
11584 j_decompress_ptr cinfo;
11585 {
11586 }
11587
11588
11589 /* Set up the JPEG lib for reading an image from DATA which contains
11590 LEN bytes. CINFO is the decompression info structure created for
11591 reading the image. */
11592
11593 static void
11594 jpeg_memory_src (cinfo, data, len)
11595 j_decompress_ptr cinfo;
11596 JOCTET *data;
11597 unsigned int len;
11598 {
11599 struct jpeg_source_mgr *src;
11600
11601 if (cinfo->src == NULL)
11602 {
11603 /* First time for this JPEG object? */
11604 cinfo->src = (struct jpeg_source_mgr *)
11605 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
11606 sizeof (struct jpeg_source_mgr));
11607 src = (struct jpeg_source_mgr *) cinfo->src;
11608 src->next_input_byte = data;
11609 }
11610
11611 src = (struct jpeg_source_mgr *) cinfo->src;
11612 src->init_source = our_init_source;
11613 src->fill_input_buffer = our_fill_input_buffer;
11614 src->skip_input_data = our_skip_input_data;
11615 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
11616 src->term_source = our_term_source;
11617 src->bytes_in_buffer = len;
11618 src->next_input_byte = data;
11619 }
11620
11621
11622 /* Load image IMG for use on frame F. Patterned after example.c
11623 from the JPEG lib. */
11624
11625 static int
11626 jpeg_load (f, img)
11627 struct frame *f;
11628 struct image *img;
11629 {
11630 struct jpeg_decompress_struct cinfo;
11631 struct my_jpeg_error_mgr mgr;
11632 Lisp_Object file, specified_file;
11633 Lisp_Object specified_data;
11634 FILE * volatile fp = NULL;
11635 JSAMPARRAY buffer;
11636 int row_stride, x, y;
11637 XImage *ximg = NULL;
11638 int rc;
11639 unsigned long *colors;
11640 int width, height;
11641 struct gcpro gcpro1;
11642
11643 /* Open the JPEG file. */
11644 specified_file = image_spec_value (img->spec, QCfile, NULL);
11645 specified_data = image_spec_value (img->spec, QCdata, NULL);
11646 file = Qnil;
11647 GCPRO1 (file);
11648
11649 if (NILP (specified_data))
11650 {
11651 file = x_find_image_file (specified_file);
11652 if (!STRINGP (file))
11653 {
11654 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11655 UNGCPRO;
11656 return 0;
11657 }
11658
11659 fp = fopen (XSTRING (file)->data, "r");
11660 if (fp == NULL)
11661 {
11662 image_error ("Cannot open `%s'", file, Qnil);
11663 UNGCPRO;
11664 return 0;
11665 }
11666 }
11667
11668 /* Customize libjpeg's error handling to call my_error_exit when an
11669 error is detected. This function will perform a longjmp. */
11670 cinfo.err = jpeg_std_error (&mgr.pub);
11671 mgr.pub.error_exit = my_error_exit;
11672
11673 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
11674 {
11675 if (rc == 1)
11676 {
11677 /* Called from my_error_exit. Display a JPEG error. */
11678 char buffer[JMSG_LENGTH_MAX];
11679 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
11680 image_error ("Error reading JPEG image `%s': %s", img->spec,
11681 build_string (buffer));
11682 }
11683
11684 /* Close the input file and destroy the JPEG object. */
11685 if (fp)
11686 fclose (fp);
11687 jpeg_destroy_decompress (&cinfo);
11688
11689 /* If we already have an XImage, free that. */
11690 x_destroy_x_image (ximg);
11691
11692 /* Free pixmap and colors. */
11693 x_clear_image (f, img);
11694
11695 UNGCPRO;
11696 return 0;
11697 }
11698
11699 /* Create the JPEG decompression object. Let it read from fp.
11700 Read the JPEG image header. */
11701 jpeg_create_decompress (&cinfo);
11702
11703 if (NILP (specified_data))
11704 jpeg_stdio_src (&cinfo, fp);
11705 else
11706 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
11707 STRING_BYTES (XSTRING (specified_data)));
11708
11709 jpeg_read_header (&cinfo, TRUE);
11710
11711 /* Customize decompression so that color quantization will be used.
11712 Start decompression. */
11713 cinfo.quantize_colors = TRUE;
11714 jpeg_start_decompress (&cinfo);
11715 width = img->width = cinfo.output_width;
11716 height = img->height = cinfo.output_height;
11717
11718 /* Create X image and pixmap. */
11719 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
11720 &img->pixmap))
11721 longjmp (mgr.setjmp_buffer, 2);
11722
11723 /* Allocate colors. When color quantization is used,
11724 cinfo.actual_number_of_colors has been set with the number of
11725 colors generated, and cinfo.colormap is a two-dimensional array
11726 of color indices in the range 0..cinfo.actual_number_of_colors.
11727 No more than 255 colors will be generated. */
11728 {
11729 int i, ir, ig, ib;
11730
11731 if (cinfo.out_color_components > 2)
11732 ir = 0, ig = 1, ib = 2;
11733 else if (cinfo.out_color_components > 1)
11734 ir = 0, ig = 1, ib = 0;
11735 else
11736 ir = 0, ig = 0, ib = 0;
11737
11738 /* Use the color table mechanism because it handles colors that
11739 cannot be allocated nicely. Such colors will be replaced with
11740 a default color, and we don't have to care about which colors
11741 can be freed safely, and which can't. */
11742 init_color_table ();
11743 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
11744 * sizeof *colors);
11745
11746 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
11747 {
11748 /* Multiply RGB values with 255 because X expects RGB values
11749 in the range 0..0xffff. */
11750 int r = cinfo.colormap[ir][i] << 8;
11751 int g = cinfo.colormap[ig][i] << 8;
11752 int b = cinfo.colormap[ib][i] << 8;
11753 colors[i] = lookup_rgb_color (f, r, g, b);
11754 }
11755
11756 /* Remember those colors actually allocated. */
11757 img->colors = colors_in_color_table (&img->ncolors);
11758 free_color_table ();
11759 }
11760
11761 /* Read pixels. */
11762 row_stride = width * cinfo.output_components;
11763 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
11764 row_stride, 1);
11765 for (y = 0; y < height; ++y)
11766 {
11767 jpeg_read_scanlines (&cinfo, buffer, 1);
11768 for (x = 0; x < cinfo.output_width; ++x)
11769 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
11770 }
11771
11772 /* Clean up. */
11773 jpeg_finish_decompress (&cinfo);
11774 jpeg_destroy_decompress (&cinfo);
11775 if (fp)
11776 fclose (fp);
11777
11778 /* Maybe fill in the background field while we have ximg handy. */
11779 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11780 IMAGE_BACKGROUND (img, f, ximg);
11781
11782 /* Put the image into the pixmap. */
11783 x_put_x_image (f, ximg, img->pixmap, width, height);
11784 x_destroy_x_image (ximg);
11785 UNBLOCK_INPUT;
11786 UNGCPRO;
11787 return 1;
11788 }
11789
11790 #endif /* HAVE_JPEG */
11791
11792
11793 \f
11794 /***********************************************************************
11795 TIFF
11796 ***********************************************************************/
11797
11798 #if HAVE_TIFF
11799
11800 #include <tiffio.h>
11801
11802 static int tiff_image_p P_ ((Lisp_Object object));
11803 static int tiff_load P_ ((struct frame *f, struct image *img));
11804
11805 /* The symbol `tiff' identifying images of this type. */
11806
11807 Lisp_Object Qtiff;
11808
11809 /* Indices of image specification fields in tiff_format, below. */
11810
11811 enum tiff_keyword_index
11812 {
11813 TIFF_TYPE,
11814 TIFF_DATA,
11815 TIFF_FILE,
11816 TIFF_ASCENT,
11817 TIFF_MARGIN,
11818 TIFF_RELIEF,
11819 TIFF_ALGORITHM,
11820 TIFF_HEURISTIC_MASK,
11821 TIFF_MASK,
11822 TIFF_BACKGROUND,
11823 TIFF_LAST
11824 };
11825
11826 /* Vector of image_keyword structures describing the format
11827 of valid user-defined image specifications. */
11828
11829 static struct image_keyword tiff_format[TIFF_LAST] =
11830 {
11831 {":type", IMAGE_SYMBOL_VALUE, 1},
11832 {":data", IMAGE_STRING_VALUE, 0},
11833 {":file", IMAGE_STRING_VALUE, 0},
11834 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
11835 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11836 {":relief", IMAGE_INTEGER_VALUE, 0},
11837 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11838 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11839 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11840 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11841 };
11842
11843 /* Structure describing the image type `tiff'. */
11844
11845 static struct image_type tiff_type =
11846 {
11847 &Qtiff,
11848 tiff_image_p,
11849 tiff_load,
11850 x_clear_image,
11851 NULL
11852 };
11853
11854
11855 /* Return non-zero if OBJECT is a valid TIFF image specification. */
11856
11857 static int
11858 tiff_image_p (object)
11859 Lisp_Object object;
11860 {
11861 struct image_keyword fmt[TIFF_LAST];
11862 bcopy (tiff_format, fmt, sizeof fmt);
11863
11864 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
11865 || (fmt[TIFF_ASCENT].count
11866 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
11867 return 0;
11868
11869 /* Must specify either the :data or :file keyword. */
11870 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
11871 }
11872
11873
11874 /* Reading from a memory buffer for TIFF images Based on the PNG
11875 memory source, but we have to provide a lot of extra functions.
11876 Blah.
11877
11878 We really only need to implement read and seek, but I am not
11879 convinced that the TIFF library is smart enough not to destroy
11880 itself if we only hand it the function pointers we need to
11881 override. */
11882
11883 typedef struct
11884 {
11885 unsigned char *bytes;
11886 size_t len;
11887 int index;
11888 }
11889 tiff_memory_source;
11890
11891 static size_t
11892 tiff_read_from_memory (data, buf, size)
11893 thandle_t data;
11894 tdata_t buf;
11895 tsize_t size;
11896 {
11897 tiff_memory_source *src = (tiff_memory_source *) data;
11898
11899 if (size > src->len - src->index)
11900 return (size_t) -1;
11901 bcopy (src->bytes + src->index, buf, size);
11902 src->index += size;
11903 return size;
11904 }
11905
11906 static size_t
11907 tiff_write_from_memory (data, buf, size)
11908 thandle_t data;
11909 tdata_t buf;
11910 tsize_t size;
11911 {
11912 return (size_t) -1;
11913 }
11914
11915 static toff_t
11916 tiff_seek_in_memory (data, off, whence)
11917 thandle_t data;
11918 toff_t off;
11919 int whence;
11920 {
11921 tiff_memory_source *src = (tiff_memory_source *) data;
11922 int idx;
11923
11924 switch (whence)
11925 {
11926 case SEEK_SET: /* Go from beginning of source. */
11927 idx = off;
11928 break;
11929
11930 case SEEK_END: /* Go from end of source. */
11931 idx = src->len + off;
11932 break;
11933
11934 case SEEK_CUR: /* Go from current position. */
11935 idx = src->index + off;
11936 break;
11937
11938 default: /* Invalid `whence'. */
11939 return -1;
11940 }
11941
11942 if (idx > src->len || idx < 0)
11943 return -1;
11944
11945 src->index = idx;
11946 return src->index;
11947 }
11948
11949 static int
11950 tiff_close_memory (data)
11951 thandle_t data;
11952 {
11953 /* NOOP */
11954 return 0;
11955 }
11956
11957 static int
11958 tiff_mmap_memory (data, pbase, psize)
11959 thandle_t data;
11960 tdata_t *pbase;
11961 toff_t *psize;
11962 {
11963 /* It is already _IN_ memory. */
11964 return 0;
11965 }
11966
11967 static void
11968 tiff_unmap_memory (data, base, size)
11969 thandle_t data;
11970 tdata_t base;
11971 toff_t size;
11972 {
11973 /* We don't need to do this. */
11974 }
11975
11976 static toff_t
11977 tiff_size_of_memory (data)
11978 thandle_t data;
11979 {
11980 return ((tiff_memory_source *) data)->len;
11981 }
11982
11983
11984 static void
11985 tiff_error_handler (title, format, ap)
11986 const char *title, *format;
11987 va_list ap;
11988 {
11989 char buf[512];
11990 int len;
11991
11992 len = sprintf (buf, "TIFF error: %s ", title);
11993 vsprintf (buf + len, format, ap);
11994 add_to_log (buf, Qnil, Qnil);
11995 }
11996
11997
11998 static void
11999 tiff_warning_handler (title, format, ap)
12000 const char *title, *format;
12001 va_list ap;
12002 {
12003 char buf[512];
12004 int len;
12005
12006 len = sprintf (buf, "TIFF warning: %s ", title);
12007 vsprintf (buf + len, format, ap);
12008 add_to_log (buf, Qnil, Qnil);
12009 }
12010
12011
12012 /* Load TIFF image IMG for use on frame F. Value is non-zero if
12013 successful. */
12014
12015 static int
12016 tiff_load (f, img)
12017 struct frame *f;
12018 struct image *img;
12019 {
12020 Lisp_Object file, specified_file;
12021 Lisp_Object specified_data;
12022 TIFF *tiff;
12023 int width, height, x, y;
12024 uint32 *buf;
12025 int rc;
12026 XImage *ximg;
12027 struct gcpro gcpro1;
12028 tiff_memory_source memsrc;
12029
12030 specified_file = image_spec_value (img->spec, QCfile, NULL);
12031 specified_data = image_spec_value (img->spec, QCdata, NULL);
12032 file = Qnil;
12033 GCPRO1 (file);
12034
12035 TIFFSetErrorHandler (tiff_error_handler);
12036 TIFFSetWarningHandler (tiff_warning_handler);
12037
12038 if (NILP (specified_data))
12039 {
12040 /* Read from a file */
12041 file = x_find_image_file (specified_file);
12042 if (!STRINGP (file))
12043 {
12044 image_error ("Cannot find image file `%s'", file, Qnil);
12045 UNGCPRO;
12046 return 0;
12047 }
12048
12049 /* Try to open the image file. */
12050 tiff = TIFFOpen (XSTRING (file)->data, "r");
12051 if (tiff == NULL)
12052 {
12053 image_error ("Cannot open `%s'", file, Qnil);
12054 UNGCPRO;
12055 return 0;
12056 }
12057 }
12058 else
12059 {
12060 /* Memory source! */
12061 memsrc.bytes = XSTRING (specified_data)->data;
12062 memsrc.len = STRING_BYTES (XSTRING (specified_data));
12063 memsrc.index = 0;
12064
12065 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
12066 (TIFFReadWriteProc) tiff_read_from_memory,
12067 (TIFFReadWriteProc) tiff_write_from_memory,
12068 tiff_seek_in_memory,
12069 tiff_close_memory,
12070 tiff_size_of_memory,
12071 tiff_mmap_memory,
12072 tiff_unmap_memory);
12073
12074 if (!tiff)
12075 {
12076 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
12077 UNGCPRO;
12078 return 0;
12079 }
12080 }
12081
12082 /* Get width and height of the image, and allocate a raster buffer
12083 of width x height 32-bit values. */
12084 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
12085 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
12086 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
12087
12088 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
12089 TIFFClose (tiff);
12090 if (!rc)
12091 {
12092 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
12093 xfree (buf);
12094 UNGCPRO;
12095 return 0;
12096 }
12097
12098 /* Create the X image and pixmap. */
12099 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
12100 {
12101 xfree (buf);
12102 UNGCPRO;
12103 return 0;
12104 }
12105
12106 /* Initialize the color table. */
12107 init_color_table ();
12108
12109 /* Process the pixel raster. Origin is in the lower-left corner. */
12110 for (y = 0; y < height; ++y)
12111 {
12112 uint32 *row = buf + y * width;
12113
12114 for (x = 0; x < width; ++x)
12115 {
12116 uint32 abgr = row[x];
12117 int r = TIFFGetR (abgr) << 8;
12118 int g = TIFFGetG (abgr) << 8;
12119 int b = TIFFGetB (abgr) << 8;
12120 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
12121 }
12122 }
12123
12124 /* Remember the colors allocated for the image. Free the color table. */
12125 img->colors = colors_in_color_table (&img->ncolors);
12126 free_color_table ();
12127
12128 img->width = width;
12129 img->height = height;
12130
12131 /* Maybe fill in the background field while we have ximg handy. */
12132 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12133 IMAGE_BACKGROUND (img, f, ximg);
12134
12135 /* Put the image into the pixmap, then free the X image and its buffer. */
12136 x_put_x_image (f, ximg, img->pixmap, width, height);
12137 x_destroy_x_image (ximg);
12138 xfree (buf);
12139
12140 UNGCPRO;
12141 return 1;
12142 }
12143
12144 #endif /* HAVE_TIFF != 0 */
12145
12146
12147 \f
12148 /***********************************************************************
12149 GIF
12150 ***********************************************************************/
12151
12152 #if HAVE_GIF
12153
12154 #include <gif_lib.h>
12155
12156 static int gif_image_p P_ ((Lisp_Object object));
12157 static int gif_load P_ ((struct frame *f, struct image *img));
12158
12159 /* The symbol `gif' identifying images of this type. */
12160
12161 Lisp_Object Qgif;
12162
12163 /* Indices of image specification fields in gif_format, below. */
12164
12165 enum gif_keyword_index
12166 {
12167 GIF_TYPE,
12168 GIF_DATA,
12169 GIF_FILE,
12170 GIF_ASCENT,
12171 GIF_MARGIN,
12172 GIF_RELIEF,
12173 GIF_ALGORITHM,
12174 GIF_HEURISTIC_MASK,
12175 GIF_MASK,
12176 GIF_IMAGE,
12177 GIF_BACKGROUND,
12178 GIF_LAST
12179 };
12180
12181 /* Vector of image_keyword structures describing the format
12182 of valid user-defined image specifications. */
12183
12184 static struct image_keyword gif_format[GIF_LAST] =
12185 {
12186 {":type", IMAGE_SYMBOL_VALUE, 1},
12187 {":data", IMAGE_STRING_VALUE, 0},
12188 {":file", IMAGE_STRING_VALUE, 0},
12189 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12190 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12191 {":relief", IMAGE_INTEGER_VALUE, 0},
12192 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12193 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12194 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12195 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12196 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12197 };
12198
12199 /* Structure describing the image type `gif'. */
12200
12201 static struct image_type gif_type =
12202 {
12203 &Qgif,
12204 gif_image_p,
12205 gif_load,
12206 x_clear_image,
12207 NULL
12208 };
12209
12210 /* Return non-zero if OBJECT is a valid GIF image specification. */
12211
12212 static int
12213 gif_image_p (object)
12214 Lisp_Object object;
12215 {
12216 struct image_keyword fmt[GIF_LAST];
12217 bcopy (gif_format, fmt, sizeof fmt);
12218
12219 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
12220 || (fmt[GIF_ASCENT].count
12221 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
12222 return 0;
12223
12224 /* Must specify either the :data or :file keyword. */
12225 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
12226 }
12227
12228 /* Reading a GIF image from memory
12229 Based on the PNG memory stuff to a certain extent. */
12230
12231 typedef struct
12232 {
12233 unsigned char *bytes;
12234 size_t len;
12235 int index;
12236 }
12237 gif_memory_source;
12238
12239 /* Make the current memory source available to gif_read_from_memory.
12240 It's done this way because not all versions of libungif support
12241 a UserData field in the GifFileType structure. */
12242 static gif_memory_source *current_gif_memory_src;
12243
12244 static int
12245 gif_read_from_memory (file, buf, len)
12246 GifFileType *file;
12247 GifByteType *buf;
12248 int len;
12249 {
12250 gif_memory_source *src = current_gif_memory_src;
12251
12252 if (len > src->len - src->index)
12253 return -1;
12254
12255 bcopy (src->bytes + src->index, buf, len);
12256 src->index += len;
12257 return len;
12258 }
12259
12260
12261 /* Load GIF image IMG for use on frame F. Value is non-zero if
12262 successful. */
12263
12264 static int
12265 gif_load (f, img)
12266 struct frame *f;
12267 struct image *img;
12268 {
12269 Lisp_Object file, specified_file;
12270 Lisp_Object specified_data;
12271 int rc, width, height, x, y, i;
12272 XImage *ximg;
12273 ColorMapObject *gif_color_map;
12274 unsigned long pixel_colors[256];
12275 GifFileType *gif;
12276 struct gcpro gcpro1;
12277 Lisp_Object image;
12278 int ino, image_left, image_top, image_width, image_height;
12279 gif_memory_source memsrc;
12280 unsigned char *raster;
12281
12282 specified_file = image_spec_value (img->spec, QCfile, NULL);
12283 specified_data = image_spec_value (img->spec, QCdata, NULL);
12284 file = Qnil;
12285 GCPRO1 (file);
12286
12287 if (NILP (specified_data))
12288 {
12289 file = x_find_image_file (specified_file);
12290 if (!STRINGP (file))
12291 {
12292 image_error ("Cannot find image file `%s'", specified_file, Qnil);
12293 UNGCPRO;
12294 return 0;
12295 }
12296
12297 /* Open the GIF file. */
12298 gif = DGifOpenFileName (XSTRING (file)->data);
12299 if (gif == NULL)
12300 {
12301 image_error ("Cannot open `%s'", file, Qnil);
12302 UNGCPRO;
12303 return 0;
12304 }
12305 }
12306 else
12307 {
12308 /* Read from memory! */
12309 current_gif_memory_src = &memsrc;
12310 memsrc.bytes = XSTRING (specified_data)->data;
12311 memsrc.len = STRING_BYTES (XSTRING (specified_data));
12312 memsrc.index = 0;
12313
12314 gif = DGifOpen(&memsrc, gif_read_from_memory);
12315 if (!gif)
12316 {
12317 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
12318 UNGCPRO;
12319 return 0;
12320 }
12321 }
12322
12323 /* Read entire contents. */
12324 rc = DGifSlurp (gif);
12325 if (rc == GIF_ERROR)
12326 {
12327 image_error ("Error reading `%s'", img->spec, Qnil);
12328 DGifCloseFile (gif);
12329 UNGCPRO;
12330 return 0;
12331 }
12332
12333 image = image_spec_value (img->spec, QCindex, NULL);
12334 ino = INTEGERP (image) ? XFASTINT (image) : 0;
12335 if (ino >= gif->ImageCount)
12336 {
12337 image_error ("Invalid image number `%s' in image `%s'",
12338 image, img->spec);
12339 DGifCloseFile (gif);
12340 UNGCPRO;
12341 return 0;
12342 }
12343
12344 width = img->width = gif->SWidth;
12345 height = img->height = gif->SHeight;
12346
12347 /* Create the X image and pixmap. */
12348 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
12349 {
12350 DGifCloseFile (gif);
12351 UNGCPRO;
12352 return 0;
12353 }
12354
12355 /* Allocate colors. */
12356 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
12357 if (!gif_color_map)
12358 gif_color_map = gif->SColorMap;
12359 init_color_table ();
12360 bzero (pixel_colors, sizeof pixel_colors);
12361
12362 for (i = 0; i < gif_color_map->ColorCount; ++i)
12363 {
12364 int r = gif_color_map->Colors[i].Red << 8;
12365 int g = gif_color_map->Colors[i].Green << 8;
12366 int b = gif_color_map->Colors[i].Blue << 8;
12367 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
12368 }
12369
12370 img->colors = colors_in_color_table (&img->ncolors);
12371 free_color_table ();
12372
12373 /* Clear the part of the screen image that are not covered by
12374 the image from the GIF file. Full animated GIF support
12375 requires more than can be done here (see the gif89 spec,
12376 disposal methods). Let's simply assume that the part
12377 not covered by a sub-image is in the frame's background color. */
12378 image_top = gif->SavedImages[ino].ImageDesc.Top;
12379 image_left = gif->SavedImages[ino].ImageDesc.Left;
12380 image_width = gif->SavedImages[ino].ImageDesc.Width;
12381 image_height = gif->SavedImages[ino].ImageDesc.Height;
12382
12383 for (y = 0; y < image_top; ++y)
12384 for (x = 0; x < width; ++x)
12385 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12386
12387 for (y = image_top + image_height; y < height; ++y)
12388 for (x = 0; x < width; ++x)
12389 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12390
12391 for (y = image_top; y < image_top + image_height; ++y)
12392 {
12393 for (x = 0; x < image_left; ++x)
12394 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12395 for (x = image_left + image_width; x < width; ++x)
12396 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12397 }
12398
12399 /* Read the GIF image into the X image. We use a local variable
12400 `raster' here because RasterBits below is a char *, and invites
12401 problems with bytes >= 0x80. */
12402 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
12403
12404 if (gif->SavedImages[ino].ImageDesc.Interlace)
12405 {
12406 static int interlace_start[] = {0, 4, 2, 1};
12407 static int interlace_increment[] = {8, 8, 4, 2};
12408 int pass;
12409 int row = interlace_start[0];
12410
12411 pass = 0;
12412
12413 for (y = 0; y < image_height; y++)
12414 {
12415 if (row >= image_height)
12416 {
12417 row = interlace_start[++pass];
12418 while (row >= image_height)
12419 row = interlace_start[++pass];
12420 }
12421
12422 for (x = 0; x < image_width; x++)
12423 {
12424 int i = raster[(y * image_width) + x];
12425 XPutPixel (ximg, x + image_left, row + image_top,
12426 pixel_colors[i]);
12427 }
12428
12429 row += interlace_increment[pass];
12430 }
12431 }
12432 else
12433 {
12434 for (y = 0; y < image_height; ++y)
12435 for (x = 0; x < image_width; ++x)
12436 {
12437 int i = raster[y* image_width + x];
12438 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
12439 }
12440 }
12441
12442 DGifCloseFile (gif);
12443
12444 /* Maybe fill in the background field while we have ximg handy. */
12445 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12446 IMAGE_BACKGROUND (img, f, ximg);
12447
12448 /* Put the image into the pixmap, then free the X image and its buffer. */
12449 x_put_x_image (f, ximg, img->pixmap, width, height);
12450 x_destroy_x_image (ximg);
12451
12452 UNGCPRO;
12453 return 1;
12454 }
12455
12456 #endif /* HAVE_GIF != 0 */
12457
12458
12459 \f
12460 /***********************************************************************
12461 Ghostscript
12462 ***********************************************************************/
12463
12464 Lisp_Object Qpostscript;
12465
12466 #ifdef HAVE_GHOSTSCRIPT
12467 static int gs_image_p P_ ((Lisp_Object object));
12468 static int gs_load P_ ((struct frame *f, struct image *img));
12469 static void gs_clear_image P_ ((struct frame *f, struct image *img));
12470
12471 /* The symbol `postscript' identifying images of this type. */
12472
12473 /* Keyword symbols. */
12474
12475 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
12476
12477 /* Indices of image specification fields in gs_format, below. */
12478
12479 enum gs_keyword_index
12480 {
12481 GS_TYPE,
12482 GS_PT_WIDTH,
12483 GS_PT_HEIGHT,
12484 GS_FILE,
12485 GS_LOADER,
12486 GS_BOUNDING_BOX,
12487 GS_ASCENT,
12488 GS_MARGIN,
12489 GS_RELIEF,
12490 GS_ALGORITHM,
12491 GS_HEURISTIC_MASK,
12492 GS_MASK,
12493 GS_BACKGROUND,
12494 GS_LAST
12495 };
12496
12497 /* Vector of image_keyword structures describing the format
12498 of valid user-defined image specifications. */
12499
12500 static struct image_keyword gs_format[GS_LAST] =
12501 {
12502 {":type", IMAGE_SYMBOL_VALUE, 1},
12503 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12504 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12505 {":file", IMAGE_STRING_VALUE, 1},
12506 {":loader", IMAGE_FUNCTION_VALUE, 0},
12507 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
12508 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12509 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12510 {":relief", IMAGE_INTEGER_VALUE, 0},
12511 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12512 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12513 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12514 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12515 };
12516
12517 /* Structure describing the image type `ghostscript'. */
12518
12519 static struct image_type gs_type =
12520 {
12521 &Qpostscript,
12522 gs_image_p,
12523 gs_load,
12524 gs_clear_image,
12525 NULL
12526 };
12527
12528
12529 /* Free X resources of Ghostscript image IMG which is used on frame F. */
12530
12531 static void
12532 gs_clear_image (f, img)
12533 struct frame *f;
12534 struct image *img;
12535 {
12536 /* IMG->data.ptr_val may contain a recorded colormap. */
12537 xfree (img->data.ptr_val);
12538 x_clear_image (f, img);
12539 }
12540
12541
12542 /* Return non-zero if OBJECT is a valid Ghostscript image
12543 specification. */
12544
12545 static int
12546 gs_image_p (object)
12547 Lisp_Object object;
12548 {
12549 struct image_keyword fmt[GS_LAST];
12550 Lisp_Object tem;
12551 int i;
12552
12553 bcopy (gs_format, fmt, sizeof fmt);
12554
12555 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
12556 || (fmt[GS_ASCENT].count
12557 && XFASTINT (fmt[GS_ASCENT].value) > 100))
12558 return 0;
12559
12560 /* Bounding box must be a list or vector containing 4 integers. */
12561 tem = fmt[GS_BOUNDING_BOX].value;
12562 if (CONSP (tem))
12563 {
12564 for (i = 0; i < 4; ++i, tem = XCDR (tem))
12565 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
12566 return 0;
12567 if (!NILP (tem))
12568 return 0;
12569 }
12570 else if (VECTORP (tem))
12571 {
12572 if (XVECTOR (tem)->size != 4)
12573 return 0;
12574 for (i = 0; i < 4; ++i)
12575 if (!INTEGERP (XVECTOR (tem)->contents[i]))
12576 return 0;
12577 }
12578 else
12579 return 0;
12580
12581 return 1;
12582 }
12583
12584
12585 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
12586 if successful. */
12587
12588 static int
12589 gs_load (f, img)
12590 struct frame *f;
12591 struct image *img;
12592 {
12593 char buffer[100];
12594 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
12595 struct gcpro gcpro1, gcpro2;
12596 Lisp_Object frame;
12597 double in_width, in_height;
12598 Lisp_Object pixel_colors = Qnil;
12599
12600 /* Compute pixel size of pixmap needed from the given size in the
12601 image specification. Sizes in the specification are in pt. 1 pt
12602 = 1/72 in, xdpi and ydpi are stored in the frame's X display
12603 info. */
12604 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
12605 in_width = XFASTINT (pt_width) / 72.0;
12606 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
12607 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
12608 in_height = XFASTINT (pt_height) / 72.0;
12609 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
12610
12611 /* Create the pixmap. */
12612 BLOCK_INPUT;
12613 xassert (img->pixmap == 0);
12614 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12615 img->width, img->height,
12616 one_w32_display_info.n_cbits);
12617 UNBLOCK_INPUT;
12618
12619 if (!img->pixmap)
12620 {
12621 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
12622 return 0;
12623 }
12624
12625 /* Call the loader to fill the pixmap. It returns a process object
12626 if successful. We do not record_unwind_protect here because
12627 other places in redisplay like calling window scroll functions
12628 don't either. Let the Lisp loader use `unwind-protect' instead. */
12629 GCPRO2 (window_and_pixmap_id, pixel_colors);
12630
12631 sprintf (buffer, "%lu %lu",
12632 (unsigned long) FRAME_W32_WINDOW (f),
12633 (unsigned long) img->pixmap);
12634 window_and_pixmap_id = build_string (buffer);
12635
12636 sprintf (buffer, "%lu %lu",
12637 FRAME_FOREGROUND_PIXEL (f),
12638 FRAME_BACKGROUND_PIXEL (f));
12639 pixel_colors = build_string (buffer);
12640
12641 XSETFRAME (frame, f);
12642 loader = image_spec_value (img->spec, QCloader, NULL);
12643 if (NILP (loader))
12644 loader = intern ("gs-load-image");
12645
12646 img->data.lisp_val = call6 (loader, frame, img->spec,
12647 make_number (img->width),
12648 make_number (img->height),
12649 window_and_pixmap_id,
12650 pixel_colors);
12651 UNGCPRO;
12652 return PROCESSP (img->data.lisp_val);
12653 }
12654
12655
12656 /* Kill the Ghostscript process that was started to fill PIXMAP on
12657 frame F. Called from XTread_socket when receiving an event
12658 telling Emacs that Ghostscript has finished drawing. */
12659
12660 void
12661 x_kill_gs_process (pixmap, f)
12662 Pixmap pixmap;
12663 struct frame *f;
12664 {
12665 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
12666 int class, i;
12667 struct image *img;
12668
12669 /* Find the image containing PIXMAP. */
12670 for (i = 0; i < c->used; ++i)
12671 if (c->images[i]->pixmap == pixmap)
12672 break;
12673
12674 /* Should someone in between have cleared the image cache, for
12675 instance, give up. */
12676 if (i == c->used)
12677 return;
12678
12679 /* Kill the GS process. We should have found PIXMAP in the image
12680 cache and its image should contain a process object. */
12681 img = c->images[i];
12682 xassert (PROCESSP (img->data.lisp_val));
12683 Fkill_process (img->data.lisp_val, Qnil);
12684 img->data.lisp_val = Qnil;
12685
12686 /* On displays with a mutable colormap, figure out the colors
12687 allocated for the image by looking at the pixels of an XImage for
12688 img->pixmap. */
12689 class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
12690 if (class != StaticColor && class != StaticGray && class != TrueColor)
12691 {
12692 XImage *ximg;
12693
12694 BLOCK_INPUT;
12695
12696 /* Try to get an XImage for img->pixmep. */
12697 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
12698 0, 0, img->width, img->height, ~0, ZPixmap);
12699 if (ximg)
12700 {
12701 int x, y;
12702
12703 /* Initialize the color table. */
12704 init_color_table ();
12705
12706 /* For each pixel of the image, look its color up in the
12707 color table. After having done so, the color table will
12708 contain an entry for each color used by the image. */
12709 for (y = 0; y < img->height; ++y)
12710 for (x = 0; x < img->width; ++x)
12711 {
12712 unsigned long pixel = XGetPixel (ximg, x, y);
12713 lookup_pixel_color (f, pixel);
12714 }
12715
12716 /* Record colors in the image. Free color table and XImage. */
12717 img->colors = colors_in_color_table (&img->ncolors);
12718 free_color_table ();
12719 XDestroyImage (ximg);
12720
12721 #if 0 /* This doesn't seem to be the case. If we free the colors
12722 here, we get a BadAccess later in x_clear_image when
12723 freeing the colors. */
12724 /* We have allocated colors once, but Ghostscript has also
12725 allocated colors on behalf of us. So, to get the
12726 reference counts right, free them once. */
12727 if (img->ncolors)
12728 x_free_colors (FRAME_W32_DISPLAY (f), cmap,
12729 img->colors, img->ncolors, 0);
12730 #endif
12731 }
12732 else
12733 image_error ("Cannot get X image of `%s'; colors will not be freed",
12734 img->spec, Qnil);
12735
12736 UNBLOCK_INPUT;
12737 }
12738
12739 /* Now that we have the pixmap, compute mask and transform the
12740 image if requested. */
12741 BLOCK_INPUT;
12742 postprocess_image (f, img);
12743 UNBLOCK_INPUT;
12744 }
12745
12746 #endif /* HAVE_GHOSTSCRIPT */
12747
12748 \f
12749 /***********************************************************************
12750 Window properties
12751 ***********************************************************************/
12752
12753 DEFUN ("x-change-window-property", Fx_change_window_property,
12754 Sx_change_window_property, 2, 3, 0,
12755 doc: /* Change window property PROP to VALUE on the X window of FRAME.
12756 PROP and VALUE must be strings. FRAME nil or omitted means use the
12757 selected frame. Value is VALUE. */)
12758 (prop, value, frame)
12759 Lisp_Object frame, prop, value;
12760 {
12761 #if 0 /* TODO : port window properties to W32 */
12762 struct frame *f = check_x_frame (frame);
12763 Atom prop_atom;
12764
12765 CHECK_STRING (prop);
12766 CHECK_STRING (value);
12767
12768 BLOCK_INPUT;
12769 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
12770 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12771 prop_atom, XA_STRING, 8, PropModeReplace,
12772 XSTRING (value)->data, XSTRING (value)->size);
12773
12774 /* Make sure the property is set when we return. */
12775 XFlush (FRAME_W32_DISPLAY (f));
12776 UNBLOCK_INPUT;
12777
12778 #endif /* TODO */
12779
12780 return value;
12781 }
12782
12783
12784 DEFUN ("x-delete-window-property", Fx_delete_window_property,
12785 Sx_delete_window_property, 1, 2, 0,
12786 doc: /* Remove window property PROP from X window of FRAME.
12787 FRAME nil or omitted means use the selected frame. Value is PROP. */)
12788 (prop, frame)
12789 Lisp_Object prop, frame;
12790 {
12791 #if 0 /* TODO : port window properties to W32 */
12792
12793 struct frame *f = check_x_frame (frame);
12794 Atom prop_atom;
12795
12796 CHECK_STRING (prop);
12797 BLOCK_INPUT;
12798 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
12799 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
12800
12801 /* Make sure the property is removed when we return. */
12802 XFlush (FRAME_W32_DISPLAY (f));
12803 UNBLOCK_INPUT;
12804 #endif /* TODO */
12805
12806 return prop;
12807 }
12808
12809
12810 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
12811 1, 2, 0,
12812 doc: /* Value is the value of window property PROP on FRAME.
12813 If FRAME is nil or omitted, use the selected frame. Value is nil
12814 if FRAME hasn't a property with name PROP or if PROP has no string
12815 value. */)
12816 (prop, frame)
12817 Lisp_Object prop, frame;
12818 {
12819 #if 0 /* TODO : port window properties to W32 */
12820
12821 struct frame *f = check_x_frame (frame);
12822 Atom prop_atom;
12823 int rc;
12824 Lisp_Object prop_value = Qnil;
12825 char *tmp_data = NULL;
12826 Atom actual_type;
12827 int actual_format;
12828 unsigned long actual_size, bytes_remaining;
12829
12830 CHECK_STRING (prop);
12831 BLOCK_INPUT;
12832 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
12833 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12834 prop_atom, 0, 0, False, XA_STRING,
12835 &actual_type, &actual_format, &actual_size,
12836 &bytes_remaining, (unsigned char **) &tmp_data);
12837 if (rc == Success)
12838 {
12839 int size = bytes_remaining;
12840
12841 XFree (tmp_data);
12842 tmp_data = NULL;
12843
12844 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12845 prop_atom, 0, bytes_remaining,
12846 False, XA_STRING,
12847 &actual_type, &actual_format,
12848 &actual_size, &bytes_remaining,
12849 (unsigned char **) &tmp_data);
12850 if (rc == Success)
12851 prop_value = make_string (tmp_data, size);
12852
12853 XFree (tmp_data);
12854 }
12855
12856 UNBLOCK_INPUT;
12857
12858 return prop_value;
12859
12860 #endif /* TODO */
12861 return Qnil;
12862 }
12863
12864
12865 \f
12866 /***********************************************************************
12867 Busy cursor
12868 ***********************************************************************/
12869
12870 /* If non-null, an asynchronous timer that, when it expires, displays
12871 an hourglass cursor on all frames. */
12872
12873 static struct atimer *hourglass_atimer;
12874
12875 /* Non-zero means an hourglass cursor is currently shown. */
12876
12877 static int hourglass_shown_p;
12878
12879 /* Number of seconds to wait before displaying an hourglass cursor. */
12880
12881 static Lisp_Object Vhourglass_delay;
12882
12883 /* Default number of seconds to wait before displaying an hourglass
12884 cursor. */
12885
12886 #define DEFAULT_HOURGLASS_DELAY 1
12887
12888 /* Function prototypes. */
12889
12890 static void show_hourglass P_ ((struct atimer *));
12891 static void hide_hourglass P_ ((void));
12892
12893
12894 /* Cancel a currently active hourglass timer, and start a new one. */
12895
12896 void
12897 start_hourglass ()
12898 {
12899 #if 0 /* TODO: cursor shape changes. */
12900 EMACS_TIME delay;
12901 int secs, usecs = 0;
12902
12903 cancel_hourglass ();
12904
12905 if (INTEGERP (Vhourglass_delay)
12906 && XINT (Vhourglass_delay) > 0)
12907 secs = XFASTINT (Vhourglass_delay);
12908 else if (FLOATP (Vhourglass_delay)
12909 && XFLOAT_DATA (Vhourglass_delay) > 0)
12910 {
12911 Lisp_Object tem;
12912 tem = Ftruncate (Vhourglass_delay, Qnil);
12913 secs = XFASTINT (tem);
12914 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
12915 }
12916 else
12917 secs = DEFAULT_HOURGLASS_DELAY;
12918
12919 EMACS_SET_SECS_USECS (delay, secs, usecs);
12920 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
12921 show_hourglass, NULL);
12922 #endif
12923 }
12924
12925
12926 /* Cancel the hourglass cursor timer if active, hide an hourglass
12927 cursor if shown. */
12928
12929 void
12930 cancel_hourglass ()
12931 {
12932 if (hourglass_atimer)
12933 {
12934 cancel_atimer (hourglass_atimer);
12935 hourglass_atimer = NULL;
12936 }
12937
12938 if (hourglass_shown_p)
12939 hide_hourglass ();
12940 }
12941
12942
12943 /* Timer function of hourglass_atimer. TIMER is equal to
12944 hourglass_atimer.
12945
12946 Display an hourglass cursor on all frames by mapping the frames'
12947 hourglass_window. Set the hourglass_p flag in the frames'
12948 output_data.x structure to indicate that an hourglass cursor is
12949 shown on the frames. */
12950
12951 static void
12952 show_hourglass (timer)
12953 struct atimer *timer;
12954 {
12955 #if 0 /* TODO: cursor shape changes. */
12956 /* The timer implementation will cancel this timer automatically
12957 after this function has run. Set hourglass_atimer to null
12958 so that we know the timer doesn't have to be canceled. */
12959 hourglass_atimer = NULL;
12960
12961 if (!hourglass_shown_p)
12962 {
12963 Lisp_Object rest, frame;
12964
12965 BLOCK_INPUT;
12966
12967 FOR_EACH_FRAME (rest, frame)
12968 if (FRAME_W32_P (XFRAME (frame)))
12969 {
12970 struct frame *f = XFRAME (frame);
12971
12972 f->output_data.w32->hourglass_p = 1;
12973
12974 if (!f->output_data.w32->hourglass_window)
12975 {
12976 unsigned long mask = CWCursor;
12977 XSetWindowAttributes attrs;
12978
12979 attrs.cursor = f->output_data.w32->hourglass_cursor;
12980
12981 f->output_data.w32->hourglass_window
12982 = XCreateWindow (FRAME_X_DISPLAY (f),
12983 FRAME_OUTER_WINDOW (f),
12984 0, 0, 32000, 32000, 0, 0,
12985 InputOnly,
12986 CopyFromParent,
12987 mask, &attrs);
12988 }
12989
12990 XMapRaised (FRAME_X_DISPLAY (f),
12991 f->output_data.w32->hourglass_window);
12992 XFlush (FRAME_X_DISPLAY (f));
12993 }
12994
12995 hourglass_shown_p = 1;
12996 UNBLOCK_INPUT;
12997 }
12998 #endif
12999 }
13000
13001
13002 /* Hide the hourglass cursor on all frames, if it is currently shown. */
13003
13004 static void
13005 hide_hourglass ()
13006 {
13007 #if 0 /* TODO: cursor shape changes. */
13008 if (hourglass_shown_p)
13009 {
13010 Lisp_Object rest, frame;
13011
13012 BLOCK_INPUT;
13013 FOR_EACH_FRAME (rest, frame)
13014 {
13015 struct frame *f = XFRAME (frame);
13016
13017 if (FRAME_W32_P (f)
13018 /* Watch out for newly created frames. */
13019 && f->output_data.x->hourglass_window)
13020 {
13021 XUnmapWindow (FRAME_X_DISPLAY (f),
13022 f->output_data.x->hourglass_window);
13023 /* Sync here because XTread_socket looks at the
13024 hourglass_p flag that is reset to zero below. */
13025 XSync (FRAME_X_DISPLAY (f), False);
13026 f->output_data.x->hourglass_p = 0;
13027 }
13028 }
13029
13030 hourglass_shown_p = 0;
13031 UNBLOCK_INPUT;
13032 }
13033 #endif
13034 }
13035
13036
13037 \f
13038 /***********************************************************************
13039 Tool tips
13040 ***********************************************************************/
13041
13042 static Lisp_Object x_create_tip_frame P_ ((struct w32_display_info *,
13043 Lisp_Object, Lisp_Object));
13044 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
13045 Lisp_Object, int, int, int *, int *));
13046
13047 /* The frame of a currently visible tooltip. */
13048
13049 Lisp_Object tip_frame;
13050
13051 /* If non-nil, a timer started that hides the last tooltip when it
13052 fires. */
13053
13054 Lisp_Object tip_timer;
13055 Window tip_window;
13056
13057 /* If non-nil, a vector of 3 elements containing the last args
13058 with which x-show-tip was called. See there. */
13059
13060 Lisp_Object last_show_tip_args;
13061
13062 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
13063
13064 Lisp_Object Vx_max_tooltip_size;
13065
13066
13067 static Lisp_Object
13068 unwind_create_tip_frame (frame)
13069 Lisp_Object frame;
13070 {
13071 Lisp_Object deleted;
13072
13073 deleted = unwind_create_frame (frame);
13074 if (EQ (deleted, Qt))
13075 {
13076 tip_window = NULL;
13077 tip_frame = Qnil;
13078 }
13079
13080 return deleted;
13081 }
13082
13083
13084 /* Create a frame for a tooltip on the display described by DPYINFO.
13085 PARMS is a list of frame parameters. TEXT is the string to
13086 display in the tip frame. Value is the frame.
13087
13088 Note that functions called here, esp. x_default_parameter can
13089 signal errors, for instance when a specified color name is
13090 undefined. We have to make sure that we're in a consistent state
13091 when this happens. */
13092
13093 static Lisp_Object
13094 x_create_tip_frame (dpyinfo, parms, text)
13095 struct w32_display_info *dpyinfo;
13096 Lisp_Object parms, text;
13097 {
13098 struct frame *f;
13099 Lisp_Object frame, tem;
13100 Lisp_Object name;
13101 long window_prompting = 0;
13102 int width, height;
13103 int count = BINDING_STACK_SIZE ();
13104 struct gcpro gcpro1, gcpro2, gcpro3;
13105 struct kboard *kb;
13106 int face_change_count_before = face_change_count;
13107 Lisp_Object buffer;
13108 struct buffer *old_buffer;
13109
13110 check_w32 ();
13111
13112 /* Use this general default value to start with until we know if
13113 this frame has a specified name. */
13114 Vx_resource_name = Vinvocation_name;
13115
13116 #ifdef MULTI_KBOARD
13117 kb = dpyinfo->kboard;
13118 #else
13119 kb = &the_only_kboard;
13120 #endif
13121
13122 /* Get the name of the frame to use for resource lookup. */
13123 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
13124 if (!STRINGP (name)
13125 && !EQ (name, Qunbound)
13126 && !NILP (name))
13127 error ("Invalid frame name--not a string or nil");
13128 Vx_resource_name = name;
13129
13130 frame = Qnil;
13131 GCPRO3 (parms, name, frame);
13132 f = make_frame (1);
13133 XSETFRAME (frame, f);
13134
13135 buffer = Fget_buffer_create (build_string (" *tip*"));
13136 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
13137 old_buffer = current_buffer;
13138 set_buffer_internal_1 (XBUFFER (buffer));
13139 current_buffer->truncate_lines = Qnil;
13140 Ferase_buffer ();
13141 Finsert (1, &text);
13142 set_buffer_internal_1 (old_buffer);
13143
13144 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
13145 record_unwind_protect (unwind_create_tip_frame, frame);
13146
13147 /* By setting the output method, we're essentially saying that
13148 the frame is live, as per FRAME_LIVE_P. If we get a signal
13149 from this point on, x_destroy_window might screw up reference
13150 counts etc. */
13151 f->output_method = output_w32;
13152 f->output_data.w32 =
13153 (struct w32_output *) xmalloc (sizeof (struct w32_output));
13154 bzero (f->output_data.w32, sizeof (struct w32_output));
13155
13156 FRAME_FONTSET (f) = -1;
13157 f->icon_name = Qnil;
13158
13159 #if 0 /* GLYPH_DEBUG TODO: image support. */
13160 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
13161 dpyinfo_refcount = dpyinfo->reference_count;
13162 #endif /* GLYPH_DEBUG */
13163 #ifdef MULTI_KBOARD
13164 FRAME_KBOARD (f) = kb;
13165 #endif
13166 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
13167 f->output_data.w32->explicit_parent = 0;
13168
13169 /* Set the name; the functions to which we pass f expect the name to
13170 be set. */
13171 if (EQ (name, Qunbound) || NILP (name))
13172 {
13173 f->name = build_string (dpyinfo->w32_id_name);
13174 f->explicit_name = 0;
13175 }
13176 else
13177 {
13178 f->name = name;
13179 f->explicit_name = 1;
13180 /* use the frame's title when getting resources for this frame. */
13181 specbind (Qx_resource_name, name);
13182 }
13183
13184 /* Extract the window parameters from the supplied values
13185 that are needed to determine window geometry. */
13186 {
13187 Lisp_Object font;
13188
13189 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
13190
13191 BLOCK_INPUT;
13192 /* First, try whatever font the caller has specified. */
13193 if (STRINGP (font))
13194 {
13195 tem = Fquery_fontset (font, Qnil);
13196 if (STRINGP (tem))
13197 font = x_new_fontset (f, XSTRING (tem)->data);
13198 else
13199 font = x_new_font (f, XSTRING (font)->data);
13200 }
13201
13202 /* Try out a font which we hope has bold and italic variations. */
13203 if (!STRINGP (font))
13204 font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
13205 if (! STRINGP (font))
13206 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
13207 /* If those didn't work, look for something which will at least work. */
13208 if (! STRINGP (font))
13209 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
13210 UNBLOCK_INPUT;
13211 if (! STRINGP (font))
13212 font = build_string ("Fixedsys");
13213
13214 x_default_parameter (f, parms, Qfont, font,
13215 "font", "Font", RES_TYPE_STRING);
13216 }
13217
13218 x_default_parameter (f, parms, Qborder_width, make_number (2),
13219 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
13220 /* This defaults to 2 in order to match xterm. We recognize either
13221 internalBorderWidth or internalBorder (which is what xterm calls
13222 it). */
13223 if (NILP (Fassq (Qinternal_border_width, parms)))
13224 {
13225 Lisp_Object value;
13226
13227 value = w32_get_arg (parms, Qinternal_border_width,
13228 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
13229 if (! EQ (value, Qunbound))
13230 parms = Fcons (Fcons (Qinternal_border_width, value),
13231 parms);
13232 }
13233 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
13234 "internalBorderWidth", "internalBorderWidth",
13235 RES_TYPE_NUMBER);
13236
13237 /* Also do the stuff which must be set before the window exists. */
13238 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
13239 "foreground", "Foreground", RES_TYPE_STRING);
13240 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
13241 "background", "Background", RES_TYPE_STRING);
13242 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
13243 "pointerColor", "Foreground", RES_TYPE_STRING);
13244 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
13245 "cursorColor", "Foreground", RES_TYPE_STRING);
13246 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
13247 "borderColor", "BorderColor", RES_TYPE_STRING);
13248
13249 /* Init faces before x_default_parameter is called for scroll-bar
13250 parameters because that function calls x_set_scroll_bar_width,
13251 which calls change_frame_size, which calls Fset_window_buffer,
13252 which runs hooks, which call Fvertical_motion. At the end, we
13253 end up in init_iterator with a null face cache, which should not
13254 happen. */
13255 init_frame_faces (f);
13256
13257 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
13258 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
13259 window_prompting = x_figure_window_size (f, parms);
13260
13261 if (window_prompting & XNegative)
13262 {
13263 if (window_prompting & YNegative)
13264 f->output_data.w32->win_gravity = SouthEastGravity;
13265 else
13266 f->output_data.w32->win_gravity = NorthEastGravity;
13267 }
13268 else
13269 {
13270 if (window_prompting & YNegative)
13271 f->output_data.w32->win_gravity = SouthWestGravity;
13272 else
13273 f->output_data.w32->win_gravity = NorthWestGravity;
13274 }
13275
13276 f->output_data.w32->size_hint_flags = window_prompting;
13277
13278 BLOCK_INPUT;
13279 my_create_tip_window (f);
13280 UNBLOCK_INPUT;
13281
13282 x_make_gc (f);
13283
13284 x_default_parameter (f, parms, Qauto_raise, Qnil,
13285 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
13286 x_default_parameter (f, parms, Qauto_lower, Qnil,
13287 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
13288 x_default_parameter (f, parms, Qcursor_type, Qbox,
13289 "cursorType", "CursorType", RES_TYPE_SYMBOL);
13290
13291 /* Dimensions, especially f->height, must be done via change_frame_size.
13292 Change will not be effected unless different from the current
13293 f->height. */
13294 width = f->width;
13295 height = f->height;
13296 f->height = 0;
13297 SET_FRAME_WIDTH (f, 0);
13298 change_frame_size (f, height, width, 1, 0, 0);
13299
13300 /* Set up faces after all frame parameters are known. This call
13301 also merges in face attributes specified for new frames.
13302
13303 Frame parameters may be changed if .Xdefaults contains
13304 specifications for the default font. For example, if there is an
13305 `Emacs.default.attributeBackground: pink', the `background-color'
13306 attribute of the frame get's set, which let's the internal border
13307 of the tooltip frame appear in pink. Prevent this. */
13308 {
13309 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
13310
13311 /* Set tip_frame here, so that */
13312 tip_frame = frame;
13313 call1 (Qface_set_after_frame_default, frame);
13314
13315 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
13316 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
13317 Qnil));
13318 }
13319
13320 f->no_split = 1;
13321
13322 UNGCPRO;
13323
13324 /* It is now ok to make the frame official even if we get an error
13325 below. And the frame needs to be on Vframe_list or making it
13326 visible won't work. */
13327 Vframe_list = Fcons (frame, Vframe_list);
13328
13329 /* Now that the frame is official, it counts as a reference to
13330 its display. */
13331 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
13332
13333 /* Setting attributes of faces of the tooltip frame from resources
13334 and similar will increment face_change_count, which leads to the
13335 clearing of all current matrices. Since this isn't necessary
13336 here, avoid it by resetting face_change_count to the value it
13337 had before we created the tip frame. */
13338 face_change_count = face_change_count_before;
13339
13340 /* Discard the unwind_protect. */
13341 return unbind_to (count, frame);
13342 }
13343
13344
13345 /* Compute where to display tip frame F. PARMS is the list of frame
13346 parameters for F. DX and DY are specified offsets from the current
13347 location of the mouse. WIDTH and HEIGHT are the width and height
13348 of the tooltip. Return coordinates relative to the root window of
13349 the display in *ROOT_X, and *ROOT_Y. */
13350
13351 static void
13352 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
13353 struct frame *f;
13354 Lisp_Object parms, dx, dy;
13355 int width, height;
13356 int *root_x, *root_y;
13357 {
13358 Lisp_Object left, top;
13359
13360 /* User-specified position? */
13361 left = Fcdr (Fassq (Qleft, parms));
13362 top = Fcdr (Fassq (Qtop, parms));
13363
13364 /* Move the tooltip window where the mouse pointer is. Resize and
13365 show it. */
13366 if (!INTEGERP (left) || !INTEGERP (top))
13367 {
13368 POINT pt;
13369
13370 BLOCK_INPUT;
13371 GetCursorPos (&pt);
13372 *root_x = pt.x;
13373 *root_y = pt.y;
13374 UNBLOCK_INPUT;
13375 }
13376
13377 if (INTEGERP (top))
13378 *root_y = XINT (top);
13379 else if (*root_y + XINT (dy) - height < 0)
13380 *root_y -= XINT (dy);
13381 else
13382 {
13383 *root_y -= height;
13384 *root_y += XINT (dy);
13385 }
13386
13387 if (INTEGERP (left))
13388 *root_x = XINT (left);
13389 else if (*root_x + XINT (dx) + width > FRAME_W32_DISPLAY_INFO (f)->width)
13390 *root_x -= width + XINT (dx);
13391 else
13392 *root_x += XINT (dx);
13393 }
13394
13395
13396 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
13397 doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
13398 A tooltip window is a small window displaying a string.
13399
13400 FRAME nil or omitted means use the selected frame.
13401
13402 PARMS is an optional list of frame parameters which can be
13403 used to change the tooltip's appearance.
13404
13405 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
13406 means use the default timeout of 5 seconds.
13407
13408 If the list of frame parameters PARAMS contains a `left' parameter,
13409 the tooltip is displayed at that x-position. Otherwise it is
13410 displayed at the mouse position, with offset DX added (default is 5 if
13411 DX isn't specified). Likewise for the y-position; if a `top' frame
13412 parameter is specified, it determines the y-position of the tooltip
13413 window, otherwise it is displayed at the mouse position, with offset
13414 DY added (default is -10).
13415
13416 A tooltip's maximum size is specified by `x-max-tooltip-size'.
13417 Text larger than the specified size is clipped. */)
13418 (string, frame, parms, timeout, dx, dy)
13419 Lisp_Object string, frame, parms, timeout, dx, dy;
13420 {
13421 struct frame *f;
13422 struct window *w;
13423 int root_x, root_y;
13424 struct buffer *old_buffer;
13425 struct text_pos pos;
13426 int i, width, height;
13427 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
13428 int old_windows_or_buffers_changed = windows_or_buffers_changed;
13429 int count = BINDING_STACK_SIZE ();
13430
13431 specbind (Qinhibit_redisplay, Qt);
13432
13433 GCPRO4 (string, parms, frame, timeout);
13434
13435 CHECK_STRING (string);
13436 f = check_x_frame (frame);
13437 if (NILP (timeout))
13438 timeout = make_number (5);
13439 else
13440 CHECK_NATNUM (timeout);
13441
13442 if (NILP (dx))
13443 dx = make_number (5);
13444 else
13445 CHECK_NUMBER (dx);
13446
13447 if (NILP (dy))
13448 dy = make_number (-10);
13449 else
13450 CHECK_NUMBER (dy);
13451
13452 if (NILP (last_show_tip_args))
13453 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
13454
13455 if (!NILP (tip_frame))
13456 {
13457 Lisp_Object last_string = AREF (last_show_tip_args, 0);
13458 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
13459 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
13460
13461 if (EQ (frame, last_frame)
13462 && !NILP (Fequal (last_string, string))
13463 && !NILP (Fequal (last_parms, parms)))
13464 {
13465 struct frame *f = XFRAME (tip_frame);
13466
13467 /* Only DX and DY have changed. */
13468 if (!NILP (tip_timer))
13469 {
13470 Lisp_Object timer = tip_timer;
13471 tip_timer = Qnil;
13472 call1 (Qcancel_timer, timer);
13473 }
13474
13475 BLOCK_INPUT;
13476 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
13477 PIXEL_HEIGHT (f), &root_x, &root_y);
13478 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
13479 root_x, root_y, 0, 0,
13480 SWP_NOSIZE | SWP_NOACTIVATE);
13481 UNBLOCK_INPUT;
13482 goto start_timer;
13483 }
13484 }
13485
13486 /* Hide a previous tip, if any. */
13487 Fx_hide_tip ();
13488
13489 ASET (last_show_tip_args, 0, string);
13490 ASET (last_show_tip_args, 1, frame);
13491 ASET (last_show_tip_args, 2, parms);
13492
13493 /* Add default values to frame parameters. */
13494 if (NILP (Fassq (Qname, parms)))
13495 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
13496 if (NILP (Fassq (Qinternal_border_width, parms)))
13497 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
13498 if (NILP (Fassq (Qborder_width, parms)))
13499 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
13500 if (NILP (Fassq (Qborder_color, parms)))
13501 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
13502 if (NILP (Fassq (Qbackground_color, parms)))
13503 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
13504 parms);
13505
13506 /* Block input until the tip has been fully drawn, to avoid crashes
13507 when drawing tips in menus. */
13508 BLOCK_INPUT;
13509
13510 /* Create a frame for the tooltip, and record it in the global
13511 variable tip_frame. */
13512 frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
13513 f = XFRAME (frame);
13514
13515 /* Set up the frame's root window. */
13516 w = XWINDOW (FRAME_ROOT_WINDOW (f));
13517 w->left = w->top = make_number (0);
13518
13519 if (CONSP (Vx_max_tooltip_size)
13520 && INTEGERP (XCAR (Vx_max_tooltip_size))
13521 && XINT (XCAR (Vx_max_tooltip_size)) > 0
13522 && INTEGERP (XCDR (Vx_max_tooltip_size))
13523 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
13524 {
13525 w->width = XCAR (Vx_max_tooltip_size);
13526 w->height = XCDR (Vx_max_tooltip_size);
13527 }
13528 else
13529 {
13530 w->width = make_number (80);
13531 w->height = make_number (40);
13532 }
13533
13534 f->window_width = XINT (w->width);
13535 adjust_glyphs (f);
13536 w->pseudo_window_p = 1;
13537
13538 /* Display the tooltip text in a temporary buffer. */
13539 old_buffer = current_buffer;
13540 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
13541 current_buffer->truncate_lines = Qnil;
13542 clear_glyph_matrix (w->desired_matrix);
13543 clear_glyph_matrix (w->current_matrix);
13544 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
13545 try_window (FRAME_ROOT_WINDOW (f), pos);
13546
13547 /* Compute width and height of the tooltip. */
13548 width = height = 0;
13549 for (i = 0; i < w->desired_matrix->nrows; ++i)
13550 {
13551 struct glyph_row *row = &w->desired_matrix->rows[i];
13552 struct glyph *last;
13553 int row_width;
13554
13555 /* Stop at the first empty row at the end. */
13556 if (!row->enabled_p || !row->displays_text_p)
13557 break;
13558
13559 /* Let the row go over the full width of the frame. */
13560 row->full_width_p = 1;
13561
13562 #ifdef TODO /* Investigate why some fonts need more width than is
13563 calculated for some tooltips. */
13564 /* There's a glyph at the end of rows that is use to place
13565 the cursor there. Don't include the width of this glyph. */
13566 if (row->used[TEXT_AREA])
13567 {
13568 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
13569 row_width = row->pixel_width - last->pixel_width;
13570 }
13571 else
13572 #endif
13573 row_width = row->pixel_width;
13574
13575 /* TODO: find why tips do not draw along baseline as instructed. */
13576 height += row->height;
13577 width = max (width, row_width);
13578 }
13579
13580 /* Add the frame's internal border to the width and height the X
13581 window should have. */
13582 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
13583 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
13584
13585 /* Move the tooltip window where the mouse pointer is. Resize and
13586 show it. */
13587 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
13588
13589 {
13590 /* Adjust Window size to take border into account. */
13591 RECT rect;
13592 rect.left = rect.top = 0;
13593 rect.right = width;
13594 rect.bottom = height;
13595 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
13596 FRAME_EXTERNAL_MENU_BAR (f));
13597
13598 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
13599 root_x, root_y, rect.right - rect.left,
13600 rect.bottom - rect.top, SWP_NOACTIVATE);
13601
13602 /* Let redisplay know that we have made the frame visible already. */
13603 f->async_visible = 1;
13604
13605 ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
13606 }
13607
13608 /* Draw into the window. */
13609 w->must_be_updated_p = 1;
13610 update_single_window (w, 1);
13611
13612 UNBLOCK_INPUT;
13613
13614 /* Restore original current buffer. */
13615 set_buffer_internal_1 (old_buffer);
13616 windows_or_buffers_changed = old_windows_or_buffers_changed;
13617
13618 start_timer:
13619 /* Let the tip disappear after timeout seconds. */
13620 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
13621 intern ("x-hide-tip"));
13622
13623 UNGCPRO;
13624 return unbind_to (count, Qnil);
13625 }
13626
13627
13628 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
13629 doc: /* Hide the current tooltip window, if there is any.
13630 Value is t if tooltip was open, nil otherwise. */)
13631 ()
13632 {
13633 int count;
13634 Lisp_Object deleted, frame, timer;
13635 struct gcpro gcpro1, gcpro2;
13636
13637 /* Return quickly if nothing to do. */
13638 if (NILP (tip_timer) && NILP (tip_frame))
13639 return Qnil;
13640
13641 frame = tip_frame;
13642 timer = tip_timer;
13643 GCPRO2 (frame, timer);
13644 tip_frame = tip_timer = deleted = Qnil;
13645
13646 count = BINDING_STACK_SIZE ();
13647 specbind (Qinhibit_redisplay, Qt);
13648 specbind (Qinhibit_quit, Qt);
13649
13650 if (!NILP (timer))
13651 call1 (Qcancel_timer, timer);
13652
13653 if (FRAMEP (frame))
13654 {
13655 Fdelete_frame (frame, Qnil);
13656 deleted = Qt;
13657 }
13658
13659 UNGCPRO;
13660 return unbind_to (count, deleted);
13661 }
13662
13663
13664 \f
13665 /***********************************************************************
13666 File selection dialog
13667 ***********************************************************************/
13668
13669 extern Lisp_Object Qfile_name_history;
13670
13671 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
13672 doc: /* Read file name, prompting with PROMPT in directory DIR.
13673 Use a file selection dialog.
13674 Select DEFAULT-FILENAME in the dialog's file selection box, if
13675 specified. Ensure that file exists if MUSTMATCH is non-nil. */)
13676 (prompt, dir, default_filename, mustmatch)
13677 Lisp_Object prompt, dir, default_filename, mustmatch;
13678 {
13679 struct frame *f = SELECTED_FRAME ();
13680 Lisp_Object file = Qnil;
13681 int count = specpdl_ptr - specpdl;
13682 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
13683 char filename[MAX_PATH + 1];
13684 char init_dir[MAX_PATH + 1];
13685 int use_dialog_p = 1;
13686
13687 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
13688 CHECK_STRING (prompt);
13689 CHECK_STRING (dir);
13690
13691 /* Create the dialog with PROMPT as title, using DIR as initial
13692 directory and using "*" as pattern. */
13693 dir = Fexpand_file_name (dir, Qnil);
13694 strncpy (init_dir, XSTRING (dir)->data, MAX_PATH);
13695 init_dir[MAX_PATH] = '\0';
13696 unixtodos_filename (init_dir);
13697
13698 if (STRINGP (default_filename))
13699 {
13700 char *file_name_only;
13701 char *full_path_name = XSTRING (default_filename)->data;
13702
13703 unixtodos_filename (full_path_name);
13704
13705 file_name_only = strrchr (full_path_name, '\\');
13706 if (!file_name_only)
13707 file_name_only = full_path_name;
13708 else
13709 {
13710 file_name_only++;
13711
13712 /* If default_file_name is a directory, don't use the open
13713 file dialog, as it does not support selecting
13714 directories. */
13715 if (!(*file_name_only))
13716 use_dialog_p = 0;
13717 }
13718
13719 strncpy (filename, file_name_only, MAX_PATH);
13720 filename[MAX_PATH] = '\0';
13721 }
13722 else
13723 filename[0] = '\0';
13724
13725 if (use_dialog_p)
13726 {
13727 OPENFILENAME file_details;
13728
13729 /* Prevent redisplay. */
13730 specbind (Qinhibit_redisplay, Qt);
13731 BLOCK_INPUT;
13732
13733 bzero (&file_details, sizeof (file_details));
13734 file_details.lStructSize = sizeof (file_details);
13735 file_details.hwndOwner = FRAME_W32_WINDOW (f);
13736 /* Undocumented Bug in Common File Dialog:
13737 If a filter is not specified, shell links are not resolved. */
13738 file_details.lpstrFilter = "ALL Files (*.*)\0*.*\0\0";
13739 file_details.lpstrFile = filename;
13740 file_details.nMaxFile = sizeof (filename);
13741 file_details.lpstrInitialDir = init_dir;
13742 file_details.lpstrTitle = XSTRING (prompt)->data;
13743 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
13744
13745 if (!NILP (mustmatch))
13746 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
13747
13748 if (GetOpenFileName (&file_details))
13749 {
13750 dostounix_filename (filename);
13751 file = build_string (filename);
13752 }
13753 else
13754 file = Qnil;
13755
13756 UNBLOCK_INPUT;
13757 file = unbind_to (count, file);
13758 }
13759 /* Open File dialog will not allow folders to be selected, so resort
13760 to minibuffer completing reads for directories. */
13761 else
13762 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
13763 dir, mustmatch, dir, Qfile_name_history,
13764 default_filename, Qnil);
13765
13766 UNGCPRO;
13767
13768 /* Make "Cancel" equivalent to C-g. */
13769 if (NILP (file))
13770 Fsignal (Qquit, Qnil);
13771
13772 return unbind_to (count, file);
13773 }
13774
13775
13776 \f
13777 /***********************************************************************
13778 w32 specialized functions
13779 ***********************************************************************/
13780
13781 DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 1, 0,
13782 doc: /* Select a font using the W32 font dialog.
13783 Returns an X font string corresponding to the selection. */)
13784 (frame)
13785 Lisp_Object frame;
13786 {
13787 FRAME_PTR f = check_x_frame (frame);
13788 CHOOSEFONT cf;
13789 LOGFONT lf;
13790 TEXTMETRIC tm;
13791 HDC hdc;
13792 HANDLE oldobj;
13793 char buf[100];
13794
13795 bzero (&cf, sizeof (cf));
13796 bzero (&lf, sizeof (lf));
13797
13798 cf.lStructSize = sizeof (cf);
13799 cf.hwndOwner = FRAME_W32_WINDOW (f);
13800 cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS;
13801 cf.lpLogFont = &lf;
13802
13803 /* Initialize as much of the font details as we can from the current
13804 default font. */
13805 hdc = GetDC (FRAME_W32_WINDOW (f));
13806 oldobj = SelectObject (hdc, FRAME_FONT (f)->hfont);
13807 GetTextFace (hdc, LF_FACESIZE, lf.lfFaceName);
13808 if (GetTextMetrics (hdc, &tm))
13809 {
13810 lf.lfHeight = tm.tmInternalLeading - tm.tmHeight;
13811 lf.lfWeight = tm.tmWeight;
13812 lf.lfItalic = tm.tmItalic;
13813 lf.lfUnderline = tm.tmUnderlined;
13814 lf.lfStrikeOut = tm.tmStruckOut;
13815 lf.lfCharSet = tm.tmCharSet;
13816 cf.Flags |= CF_INITTOLOGFONTSTRUCT;
13817 }
13818 SelectObject (hdc, oldobj);
13819 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
13820
13821 if (!ChooseFont (&cf) || !w32_to_x_font (&lf, buf, 100, NULL))
13822 return Qnil;
13823
13824 return build_string (buf);
13825 }
13826
13827 DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
13828 Sw32_send_sys_command, 1, 2, 0,
13829 doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
13830 Some useful values for command are 0xf030 to maximise frame (0xf020
13831 to minimize), 0xf120 to restore frame to original size, and 0xf100
13832 to activate the menubar for keyboard access. 0xf140 activates the
13833 screen saver if defined.
13834
13835 If optional parameter FRAME is not specified, use selected frame. */)
13836 (command, frame)
13837 Lisp_Object command, frame;
13838 {
13839 FRAME_PTR f = check_x_frame (frame);
13840
13841 CHECK_NUMBER (command);
13842
13843 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
13844
13845 return Qnil;
13846 }
13847
13848 DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
13849 doc: /* Get Windows to perform OPERATION on DOCUMENT.
13850 This is a wrapper around the ShellExecute system function, which
13851 invokes the application registered to handle OPERATION for DOCUMENT.
13852 OPERATION is typically \"open\", \"print\" or \"explore\" (but can be
13853 nil for the default action), and DOCUMENT is typically the name of a
13854 document file or URL, but can also be a program executable to run or
13855 a directory to open in the Windows Explorer.
13856
13857 If DOCUMENT is a program executable, PARAMETERS can be a string
13858 containing command line parameters, but otherwise should be nil.
13859
13860 SHOW-FLAG can be used to control whether the invoked application is hidden
13861 or minimized. If SHOW-FLAG is nil, the application is displayed normally,
13862 otherwise it is an integer representing a ShowWindow flag:
13863
13864 0 - start hidden
13865 1 - start normally
13866 3 - start maximized
13867 6 - start minimized */)
13868 (operation, document, parameters, show_flag)
13869 Lisp_Object operation, document, parameters, show_flag;
13870 {
13871 Lisp_Object current_dir;
13872
13873 CHECK_STRING (document);
13874
13875 /* Encode filename and current directory. */
13876 current_dir = ENCODE_FILE (current_buffer->directory);
13877 document = ENCODE_FILE (document);
13878 if ((int) ShellExecute (NULL,
13879 (STRINGP (operation) ?
13880 XSTRING (operation)->data : NULL),
13881 XSTRING (document)->data,
13882 (STRINGP (parameters) ?
13883 XSTRING (parameters)->data : NULL),
13884 XSTRING (current_dir)->data,
13885 (INTEGERP (show_flag) ?
13886 XINT (show_flag) : SW_SHOWDEFAULT))
13887 > 32)
13888 return Qt;
13889 error ("ShellExecute failed: %s", w32_strerror (0));
13890 }
13891
13892 /* Lookup virtual keycode from string representing the name of a
13893 non-ascii keystroke into the corresponding virtual key, using
13894 lispy_function_keys. */
13895 static int
13896 lookup_vk_code (char *key)
13897 {
13898 int i;
13899
13900 for (i = 0; i < 256; i++)
13901 if (lispy_function_keys[i] != 0
13902 && strcmp (lispy_function_keys[i], key) == 0)
13903 return i;
13904
13905 return -1;
13906 }
13907
13908 /* Convert a one-element vector style key sequence to a hot key
13909 definition. */
13910 static int
13911 w32_parse_hot_key (key)
13912 Lisp_Object key;
13913 {
13914 /* Copied from Fdefine_key and store_in_keymap. */
13915 register Lisp_Object c;
13916 int vk_code;
13917 int lisp_modifiers;
13918 int w32_modifiers;
13919 struct gcpro gcpro1;
13920
13921 CHECK_VECTOR (key);
13922
13923 if (XFASTINT (Flength (key)) != 1)
13924 return Qnil;
13925
13926 GCPRO1 (key);
13927
13928 c = Faref (key, make_number (0));
13929
13930 if (CONSP (c) && lucid_event_type_list_p (c))
13931 c = Fevent_convert_list (c);
13932
13933 UNGCPRO;
13934
13935 if (! INTEGERP (c) && ! SYMBOLP (c))
13936 error ("Key definition is invalid");
13937
13938 /* Work out the base key and the modifiers. */
13939 if (SYMBOLP (c))
13940 {
13941 c = parse_modifiers (c);
13942 lisp_modifiers = Fcar (Fcdr (c));
13943 c = Fcar (c);
13944 if (!SYMBOLP (c))
13945 abort ();
13946 vk_code = lookup_vk_code (XSYMBOL (c)->name->data);
13947 }
13948 else if (INTEGERP (c))
13949 {
13950 lisp_modifiers = XINT (c) & ~CHARACTERBITS;
13951 /* Many ascii characters are their own virtual key code. */
13952 vk_code = XINT (c) & CHARACTERBITS;
13953 }
13954
13955 if (vk_code < 0 || vk_code > 255)
13956 return Qnil;
13957
13958 if ((lisp_modifiers & meta_modifier) != 0
13959 && !NILP (Vw32_alt_is_meta))
13960 lisp_modifiers |= alt_modifier;
13961
13962 /* Supply defs missing from mingw32. */
13963 #ifndef MOD_ALT
13964 #define MOD_ALT 0x0001
13965 #define MOD_CONTROL 0x0002
13966 #define MOD_SHIFT 0x0004
13967 #define MOD_WIN 0x0008
13968 #endif
13969
13970 /* Convert lisp modifiers to Windows hot-key form. */
13971 w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0;
13972 w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0;
13973 w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0;
13974 w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0;
13975
13976 return HOTKEY (vk_code, w32_modifiers);
13977 }
13978
13979 DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
13980 Sw32_register_hot_key, 1, 1, 0,
13981 doc: /* Register KEY as a hot-key combination.
13982 Certain key combinations like Alt-Tab are reserved for system use on
13983 Windows, and therefore are normally intercepted by the system. However,
13984 most of these key combinations can be received by registering them as
13985 hot-keys, overriding their special meaning.
13986
13987 KEY must be a one element key definition in vector form that would be
13988 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
13989 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
13990 is always interpreted as the Windows modifier keys.
13991
13992 The return value is the hotkey-id if registered, otherwise nil. */)
13993 (key)
13994 Lisp_Object key;
13995 {
13996 key = w32_parse_hot_key (key);
13997
13998 if (NILP (Fmemq (key, w32_grabbed_keys)))
13999 {
14000 /* Reuse an empty slot if possible. */
14001 Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
14002
14003 /* Safe to add new key to list, even if we have focus. */
14004 if (NILP (item))
14005 w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
14006 else
14007 XSETCAR (item, key);
14008
14009 /* Notify input thread about new hot-key definition, so that it
14010 takes effect without needing to switch focus. */
14011 PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
14012 (WPARAM) key, 0);
14013 }
14014
14015 return key;
14016 }
14017
14018 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
14019 Sw32_unregister_hot_key, 1, 1, 0,
14020 doc: /* Unregister HOTKEY as a hot-key combination. */)
14021 (key)
14022 Lisp_Object key;
14023 {
14024 Lisp_Object item;
14025
14026 if (!INTEGERP (key))
14027 key = w32_parse_hot_key (key);
14028
14029 item = Fmemq (key, w32_grabbed_keys);
14030
14031 if (!NILP (item))
14032 {
14033 /* Notify input thread about hot-key definition being removed, so
14034 that it takes effect without needing focus switch. */
14035 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
14036 (WPARAM) XINT (XCAR (item)), (LPARAM) item))
14037 {
14038 MSG msg;
14039 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
14040 }
14041 return Qt;
14042 }
14043 return Qnil;
14044 }
14045
14046 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
14047 Sw32_registered_hot_keys, 0, 0, 0,
14048 doc: /* Return list of registered hot-key IDs. */)
14049 ()
14050 {
14051 return Fcopy_sequence (w32_grabbed_keys);
14052 }
14053
14054 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
14055 Sw32_reconstruct_hot_key, 1, 1, 0,
14056 doc: /* Convert hot-key ID to a lisp key combination. */)
14057 (hotkeyid)
14058 Lisp_Object hotkeyid;
14059 {
14060 int vk_code, w32_modifiers;
14061 Lisp_Object key;
14062
14063 CHECK_NUMBER (hotkeyid);
14064
14065 vk_code = HOTKEY_VK_CODE (hotkeyid);
14066 w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
14067
14068 if (lispy_function_keys[vk_code])
14069 key = intern (lispy_function_keys[vk_code]);
14070 else
14071 key = make_number (vk_code);
14072
14073 key = Fcons (key, Qnil);
14074 if (w32_modifiers & MOD_SHIFT)
14075 key = Fcons (Qshift, key);
14076 if (w32_modifiers & MOD_CONTROL)
14077 key = Fcons (Qctrl, key);
14078 if (w32_modifiers & MOD_ALT)
14079 key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
14080 if (w32_modifiers & MOD_WIN)
14081 key = Fcons (Qhyper, key);
14082
14083 return key;
14084 }
14085
14086 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
14087 Sw32_toggle_lock_key, 1, 2, 0,
14088 doc: /* Toggle the state of the lock key KEY.
14089 KEY can be `capslock', `kp-numlock', or `scroll'.
14090 If the optional parameter NEW-STATE is a number, then the state of KEY
14091 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
14092 (key, new_state)
14093 Lisp_Object key, new_state;
14094 {
14095 int vk_code;
14096
14097 if (EQ (key, intern ("capslock")))
14098 vk_code = VK_CAPITAL;
14099 else if (EQ (key, intern ("kp-numlock")))
14100 vk_code = VK_NUMLOCK;
14101 else if (EQ (key, intern ("scroll")))
14102 vk_code = VK_SCROLL;
14103 else
14104 return Qnil;
14105
14106 if (!dwWindowsThreadId)
14107 return make_number (w32_console_toggle_lock_key (vk_code, new_state));
14108
14109 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
14110 (WPARAM) vk_code, (LPARAM) new_state))
14111 {
14112 MSG msg;
14113 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
14114 return make_number (msg.wParam);
14115 }
14116 return Qnil;
14117 }
14118 \f
14119 DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
14120 doc: /* Return storage information about the file system FILENAME is on.
14121 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
14122 storage of the file system, FREE is the free storage, and AVAIL is the
14123 storage available to a non-superuser. All 3 numbers are in bytes.
14124 If the underlying system call fails, value is nil. */)
14125 (filename)
14126 Lisp_Object filename;
14127 {
14128 Lisp_Object encoded, value;
14129
14130 CHECK_STRING (filename);
14131 filename = Fexpand_file_name (filename, Qnil);
14132 encoded = ENCODE_FILE (filename);
14133
14134 value = Qnil;
14135
14136 /* Determining the required information on Windows turns out, sadly,
14137 to be more involved than one would hope. The original Win32 api
14138 call for this will return bogus information on some systems, but we
14139 must dynamically probe for the replacement api, since that was
14140 added rather late on. */
14141 {
14142 HMODULE hKernel = GetModuleHandle ("kernel32");
14143 BOOL (*pfn_GetDiskFreeSpaceEx)
14144 (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
14145 = (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceEx");
14146
14147 /* On Windows, we may need to specify the root directory of the
14148 volume holding FILENAME. */
14149 char rootname[MAX_PATH];
14150 char *name = XSTRING (encoded)->data;
14151
14152 /* find the root name of the volume if given */
14153 if (isalpha (name[0]) && name[1] == ':')
14154 {
14155 rootname[0] = name[0];
14156 rootname[1] = name[1];
14157 rootname[2] = '\\';
14158 rootname[3] = 0;
14159 }
14160 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
14161 {
14162 char *str = rootname;
14163 int slashes = 4;
14164 do
14165 {
14166 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
14167 break;
14168 *str++ = *name++;
14169 }
14170 while ( *name );
14171
14172 *str++ = '\\';
14173 *str = 0;
14174 }
14175
14176 if (pfn_GetDiskFreeSpaceEx)
14177 {
14178 LARGE_INTEGER availbytes;
14179 LARGE_INTEGER freebytes;
14180 LARGE_INTEGER totalbytes;
14181
14182 if (pfn_GetDiskFreeSpaceEx(rootname,
14183 &availbytes,
14184 &totalbytes,
14185 &freebytes))
14186 value = list3 (make_float ((double) totalbytes.QuadPart),
14187 make_float ((double) freebytes.QuadPart),
14188 make_float ((double) availbytes.QuadPart));
14189 }
14190 else
14191 {
14192 DWORD sectors_per_cluster;
14193 DWORD bytes_per_sector;
14194 DWORD free_clusters;
14195 DWORD total_clusters;
14196
14197 if (GetDiskFreeSpace(rootname,
14198 &sectors_per_cluster,
14199 &bytes_per_sector,
14200 &free_clusters,
14201 &total_clusters))
14202 value = list3 (make_float ((double) total_clusters
14203 * sectors_per_cluster * bytes_per_sector),
14204 make_float ((double) free_clusters
14205 * sectors_per_cluster * bytes_per_sector),
14206 make_float ((double) free_clusters
14207 * sectors_per_cluster * bytes_per_sector));
14208 }
14209 }
14210
14211 return value;
14212 }
14213 \f
14214 /***********************************************************************
14215 Initialization
14216 ***********************************************************************/
14217
14218 void
14219 syms_of_w32fns ()
14220 {
14221 /* This is zero if not using MS-Windows. */
14222 w32_in_use = 0;
14223
14224 /* The section below is built by the lisp expression at the top of the file,
14225 just above where these variables are declared. */
14226 /*&&& init symbols here &&&*/
14227 Qauto_raise = intern ("auto-raise");
14228 staticpro (&Qauto_raise);
14229 Qauto_lower = intern ("auto-lower");
14230 staticpro (&Qauto_lower);
14231 Qbar = intern ("bar");
14232 staticpro (&Qbar);
14233 Qborder_color = intern ("border-color");
14234 staticpro (&Qborder_color);
14235 Qborder_width = intern ("border-width");
14236 staticpro (&Qborder_width);
14237 Qbox = intern ("box");
14238 staticpro (&Qbox);
14239 Qcursor_color = intern ("cursor-color");
14240 staticpro (&Qcursor_color);
14241 Qcursor_type = intern ("cursor-type");
14242 staticpro (&Qcursor_type);
14243 Qgeometry = intern ("geometry");
14244 staticpro (&Qgeometry);
14245 Qicon_left = intern ("icon-left");
14246 staticpro (&Qicon_left);
14247 Qicon_top = intern ("icon-top");
14248 staticpro (&Qicon_top);
14249 Qicon_type = intern ("icon-type");
14250 staticpro (&Qicon_type);
14251 Qicon_name = intern ("icon-name");
14252 staticpro (&Qicon_name);
14253 Qinternal_border_width = intern ("internal-border-width");
14254 staticpro (&Qinternal_border_width);
14255 Qleft = intern ("left");
14256 staticpro (&Qleft);
14257 Qright = intern ("right");
14258 staticpro (&Qright);
14259 Qmouse_color = intern ("mouse-color");
14260 staticpro (&Qmouse_color);
14261 Qnone = intern ("none");
14262 staticpro (&Qnone);
14263 Qparent_id = intern ("parent-id");
14264 staticpro (&Qparent_id);
14265 Qscroll_bar_width = intern ("scroll-bar-width");
14266 staticpro (&Qscroll_bar_width);
14267 Qsuppress_icon = intern ("suppress-icon");
14268 staticpro (&Qsuppress_icon);
14269 Qundefined_color = intern ("undefined-color");
14270 staticpro (&Qundefined_color);
14271 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
14272 staticpro (&Qvertical_scroll_bars);
14273 Qvisibility = intern ("visibility");
14274 staticpro (&Qvisibility);
14275 Qwindow_id = intern ("window-id");
14276 staticpro (&Qwindow_id);
14277 Qx_frame_parameter = intern ("x-frame-parameter");
14278 staticpro (&Qx_frame_parameter);
14279 Qx_resource_name = intern ("x-resource-name");
14280 staticpro (&Qx_resource_name);
14281 Quser_position = intern ("user-position");
14282 staticpro (&Quser_position);
14283 Quser_size = intern ("user-size");
14284 staticpro (&Quser_size);
14285 Qscreen_gamma = intern ("screen-gamma");
14286 staticpro (&Qscreen_gamma);
14287 Qline_spacing = intern ("line-spacing");
14288 staticpro (&Qline_spacing);
14289 Qcenter = intern ("center");
14290 staticpro (&Qcenter);
14291 Qcancel_timer = intern ("cancel-timer");
14292 staticpro (&Qcancel_timer);
14293 /* This is the end of symbol initialization. */
14294
14295 Qhyper = intern ("hyper");
14296 staticpro (&Qhyper);
14297 Qsuper = intern ("super");
14298 staticpro (&Qsuper);
14299 Qmeta = intern ("meta");
14300 staticpro (&Qmeta);
14301 Qalt = intern ("alt");
14302 staticpro (&Qalt);
14303 Qctrl = intern ("ctrl");
14304 staticpro (&Qctrl);
14305 Qcontrol = intern ("control");
14306 staticpro (&Qcontrol);
14307 Qshift = intern ("shift");
14308 staticpro (&Qshift);
14309
14310 /* Text property `display' should be nonsticky by default. */
14311 Vtext_property_default_nonsticky
14312 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
14313
14314
14315 Qlaplace = intern ("laplace");
14316 staticpro (&Qlaplace);
14317 Qemboss = intern ("emboss");
14318 staticpro (&Qemboss);
14319 Qedge_detection = intern ("edge-detection");
14320 staticpro (&Qedge_detection);
14321 Qheuristic = intern ("heuristic");
14322 staticpro (&Qheuristic);
14323 QCmatrix = intern (":matrix");
14324 staticpro (&QCmatrix);
14325 QCcolor_adjustment = intern (":color-adjustment");
14326 staticpro (&QCcolor_adjustment);
14327 QCmask = intern (":mask");
14328 staticpro (&QCmask);
14329
14330 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
14331 staticpro (&Qface_set_after_frame_default);
14332
14333 Fput (Qundefined_color, Qerror_conditions,
14334 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
14335 Fput (Qundefined_color, Qerror_message,
14336 build_string ("Undefined color"));
14337
14338 staticpro (&w32_grabbed_keys);
14339 w32_grabbed_keys = Qnil;
14340
14341 DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
14342 doc: /* An array of color name mappings for windows. */);
14343 Vw32_color_map = Qnil;
14344
14345 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
14346 doc: /* Non-nil if alt key presses are passed on to Windows.
14347 When non-nil, for example, alt pressed and released and then space will
14348 open the System menu. When nil, Emacs silently swallows alt key events. */);
14349 Vw32_pass_alt_to_system = Qnil;
14350
14351 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
14352 doc: /* Non-nil if the alt key is to be considered the same as the meta key.
14353 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta. */);
14354 Vw32_alt_is_meta = Qt;
14355
14356 DEFVAR_INT ("w32-quit-key", &Vw32_quit_key,
14357 doc: /* If non-zero, the virtual key code for an alternative quit key. */);
14358 XSETINT (Vw32_quit_key, 0);
14359
14360 DEFVAR_LISP ("w32-pass-lwindow-to-system",
14361 &Vw32_pass_lwindow_to_system,
14362 doc: /* Non-nil if the left \"Windows\" key is passed on to Windows.
14363 When non-nil, the Start menu is opened by tapping the key. */);
14364 Vw32_pass_lwindow_to_system = Qt;
14365
14366 DEFVAR_LISP ("w32-pass-rwindow-to-system",
14367 &Vw32_pass_rwindow_to_system,
14368 doc: /* Non-nil if the right \"Windows\" key is passed on to Windows.
14369 When non-nil, the Start menu is opened by tapping the key. */);
14370 Vw32_pass_rwindow_to_system = Qt;
14371
14372 DEFVAR_INT ("w32-phantom-key-code",
14373 &Vw32_phantom_key_code,
14374 doc: /* Virtual key code used to generate \"phantom\" key presses.
14375 Value is a number between 0 and 255.
14376
14377 Phantom key presses are generated in order to stop the system from
14378 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
14379 `w32-pass-rwindow-to-system' is nil. */);
14380 /* Although 255 is technically not a valid key code, it works and
14381 means that this hack won't interfere with any real key code. */
14382 Vw32_phantom_key_code = 255;
14383
14384 DEFVAR_LISP ("w32-enable-num-lock",
14385 &Vw32_enable_num_lock,
14386 doc: /* Non-nil if Num Lock should act normally.
14387 Set to nil to see Num Lock as the key `kp-numlock'. */);
14388 Vw32_enable_num_lock = Qt;
14389
14390 DEFVAR_LISP ("w32-enable-caps-lock",
14391 &Vw32_enable_caps_lock,
14392 doc: /* Non-nil if Caps Lock should act normally.
14393 Set to nil to see Caps Lock as the key `capslock'. */);
14394 Vw32_enable_caps_lock = Qt;
14395
14396 DEFVAR_LISP ("w32-scroll-lock-modifier",
14397 &Vw32_scroll_lock_modifier,
14398 doc: /* Modifier to use for the Scroll Lock on state.
14399 The value can be hyper, super, meta, alt, control or shift for the
14400 respective modifier, or nil to see Scroll Lock as the key `scroll'.
14401 Any other value will cause the key to be ignored. */);
14402 Vw32_scroll_lock_modifier = Qt;
14403
14404 DEFVAR_LISP ("w32-lwindow-modifier",
14405 &Vw32_lwindow_modifier,
14406 doc: /* Modifier to use for the left \"Windows\" key.
14407 The value can be hyper, super, meta, alt, control or shift for the
14408 respective modifier, or nil to appear as the key `lwindow'.
14409 Any other value will cause the key to be ignored. */);
14410 Vw32_lwindow_modifier = Qnil;
14411
14412 DEFVAR_LISP ("w32-rwindow-modifier",
14413 &Vw32_rwindow_modifier,
14414 doc: /* Modifier to use for the right \"Windows\" key.
14415 The value can be hyper, super, meta, alt, control or shift for the
14416 respective modifier, or nil to appear as the key `rwindow'.
14417 Any other value will cause the key to be ignored. */);
14418 Vw32_rwindow_modifier = Qnil;
14419
14420 DEFVAR_LISP ("w32-apps-modifier",
14421 &Vw32_apps_modifier,
14422 doc: /* Modifier to use for the \"Apps\" key.
14423 The value can be hyper, super, meta, alt, control or shift for the
14424 respective modifier, or nil to appear as the key `apps'.
14425 Any other value will cause the key to be ignored. */);
14426 Vw32_apps_modifier = Qnil;
14427
14428 DEFVAR_LISP ("w32-enable-synthesized-fonts", &Vw32_enable_synthesized_fonts,
14429 doc: /* Non-nil enables selection of artificially italicized and bold fonts. */);
14430 Vw32_enable_synthesized_fonts = Qnil;
14431
14432 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette,
14433 doc: /* Non-nil enables Windows palette management to map colors exactly. */);
14434 Vw32_enable_palette = Qt;
14435
14436 DEFVAR_INT ("w32-mouse-button-tolerance",
14437 &Vw32_mouse_button_tolerance,
14438 doc: /* Analogue of double click interval for faking middle mouse events.
14439 The value is the minimum time in milliseconds that must elapse between
14440 left/right button down events before they are considered distinct events.
14441 If both mouse buttons are depressed within this interval, a middle mouse
14442 button down event is generated instead. */);
14443 XSETINT (Vw32_mouse_button_tolerance, GetDoubleClickTime () / 2);
14444
14445 DEFVAR_INT ("w32-mouse-move-interval",
14446 &Vw32_mouse_move_interval,
14447 doc: /* Minimum interval between mouse move events.
14448 The value is the minimum time in milliseconds that must elapse between
14449 successive mouse move (or scroll bar drag) events before they are
14450 reported as lisp events. */);
14451 XSETINT (Vw32_mouse_move_interval, 0);
14452
14453 init_x_parm_symbols ();
14454
14455 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
14456 doc: /* List of directories to search for bitmap files for w32. */);
14457 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
14458
14459 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
14460 doc: /* The shape of the pointer when over text.
14461 Changing the value does not affect existing frames
14462 unless you set the mouse color. */);
14463 Vx_pointer_shape = Qnil;
14464
14465 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
14466 doc: /* The name Emacs uses to look up resources; for internal use only.
14467 `x-get-resource' uses this as the first component of the instance name
14468 when requesting resource values.
14469 Emacs initially sets `x-resource-name' to the name under which Emacs
14470 was invoked, or to the value specified with the `-name' or `-rn'
14471 switches, if present. */);
14472 Vx_resource_name = Qnil;
14473
14474 Vx_nontext_pointer_shape = Qnil;
14475
14476 Vx_mode_pointer_shape = Qnil;
14477
14478 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
14479 doc: /* The shape of the pointer when Emacs is busy.
14480 This variable takes effect when you create a new frame
14481 or when you set the mouse color. */);
14482 Vx_hourglass_pointer_shape = Qnil;
14483
14484 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
14485 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
14486 display_hourglass_p = 1;
14487
14488 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
14489 doc: /* *Seconds to wait before displaying an hourglass pointer.
14490 Value must be an integer or float. */);
14491 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
14492
14493 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
14494 &Vx_sensitive_text_pointer_shape,
14495 doc: /* The shape of the pointer when over mouse-sensitive text.
14496 This variable takes effect when you create a new frame
14497 or when you set the mouse color. */);
14498 Vx_sensitive_text_pointer_shape = Qnil;
14499
14500 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
14501 &Vx_window_horizontal_drag_shape,
14502 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
14503 This variable takes effect when you create a new frame
14504 or when you set the mouse color. */);
14505 Vx_window_horizontal_drag_shape = Qnil;
14506
14507 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
14508 doc: /* A string indicating the foreground color of the cursor box. */);
14509 Vx_cursor_fore_pixel = Qnil;
14510
14511 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
14512 doc: /* Maximum size for tooltips.
14513 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
14514 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
14515
14516 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
14517 doc: /* Non-nil if no window manager is in use.
14518 Emacs doesn't try to figure this out; this is always nil
14519 unless you set it to something else. */);
14520 /* We don't have any way to find this out, so set it to nil
14521 and maybe the user would like to set it to t. */
14522 Vx_no_window_manager = Qnil;
14523
14524 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
14525 &Vx_pixel_size_width_font_regexp,
14526 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
14527
14528 Since Emacs gets width of a font matching with this regexp from
14529 PIXEL_SIZE field of the name, font finding mechanism gets faster for
14530 such a font. This is especially effective for such large fonts as
14531 Chinese, Japanese, and Korean. */);
14532 Vx_pixel_size_width_font_regexp = Qnil;
14533
14534 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
14535 doc: /* Time after which cached images are removed from the cache.
14536 When an image has not been displayed this many seconds, remove it
14537 from the image cache. Value must be an integer or nil with nil
14538 meaning don't clear the cache. */);
14539 Vimage_cache_eviction_delay = make_number (30 * 60);
14540
14541 DEFVAR_LISP ("w32-bdf-filename-alist",
14542 &Vw32_bdf_filename_alist,
14543 doc: /* List of bdf fonts and their corresponding filenames. */);
14544 Vw32_bdf_filename_alist = Qnil;
14545
14546 DEFVAR_BOOL ("w32-strict-fontnames",
14547 &w32_strict_fontnames,
14548 doc: /* Non-nil means only use fonts that are exact matches for those requested.
14549 Default is nil, which allows old fontnames that are not XLFD compliant,
14550 and allows third-party CJK display to work by specifying false charset
14551 fields to trick Emacs into translating to Big5, SJIS etc.
14552 Setting this to t will prevent wrong fonts being selected when
14553 fontsets are automatically created. */);
14554 w32_strict_fontnames = 0;
14555
14556 DEFVAR_BOOL ("w32-strict-painting",
14557 &w32_strict_painting,
14558 doc: /* Non-nil means use strict rules for repainting frames.
14559 Set this to nil to get the old behaviour for repainting; this should
14560 only be necessary if the default setting causes problems. */);
14561 w32_strict_painting = 1;
14562
14563 DEFVAR_LISP ("w32-charset-info-alist",
14564 &Vw32_charset_info_alist,
14565 doc: /* Alist linking Emacs character sets to Windows fonts and codepages.
14566 Each entry should be of the form:
14567
14568 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))
14569
14570 where CHARSET_NAME is a string used in font names to identify the charset,
14571 WINDOWS_CHARSET is a symbol that can be one of:
14572 w32-charset-ansi, w32-charset-default, w32-charset-symbol,
14573 w32-charset-shiftjis, w32-charset-hangeul, w32-charset-gb2312,
14574 w32-charset-chinesebig5,
14575 #ifdef JOHAB_CHARSET
14576 w32-charset-johab, w32-charset-hebrew,
14577 w32-charset-arabic, w32-charset-greek, w32-charset-turkish,
14578 w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,
14579 w32-charset-russian, w32-charset-mac, w32-charset-baltic,
14580 #endif
14581 #ifdef UNICODE_CHARSET
14582 w32-charset-unicode,
14583 #endif
14584 or w32-charset-oem.
14585 CODEPAGE should be an integer specifying the codepage that should be used
14586 to display the character set, t to do no translation and output as Unicode,
14587 or nil to do no translation and output as 8 bit (or multibyte on far-east
14588 versions of Windows) characters. */);
14589 Vw32_charset_info_alist = Qnil;
14590
14591 staticpro (&Qw32_charset_ansi);
14592 Qw32_charset_ansi = intern ("w32-charset-ansi");
14593 staticpro (&Qw32_charset_symbol);
14594 Qw32_charset_symbol = intern ("w32-charset-symbol");
14595 staticpro (&Qw32_charset_shiftjis);
14596 Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
14597 staticpro (&Qw32_charset_hangeul);
14598 Qw32_charset_hangeul = intern ("w32-charset-hangeul");
14599 staticpro (&Qw32_charset_chinesebig5);
14600 Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
14601 staticpro (&Qw32_charset_gb2312);
14602 Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
14603 staticpro (&Qw32_charset_oem);
14604 Qw32_charset_oem = intern ("w32-charset-oem");
14605
14606 #ifdef JOHAB_CHARSET
14607 {
14608 static int w32_extra_charsets_defined = 1;
14609 DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined,
14610 doc: /* Internal variable. */);
14611
14612 staticpro (&Qw32_charset_johab);
14613 Qw32_charset_johab = intern ("w32-charset-johab");
14614 staticpro (&Qw32_charset_easteurope);
14615 Qw32_charset_easteurope = intern ("w32-charset-easteurope");
14616 staticpro (&Qw32_charset_turkish);
14617 Qw32_charset_turkish = intern ("w32-charset-turkish");
14618 staticpro (&Qw32_charset_baltic);
14619 Qw32_charset_baltic = intern ("w32-charset-baltic");
14620 staticpro (&Qw32_charset_russian);
14621 Qw32_charset_russian = intern ("w32-charset-russian");
14622 staticpro (&Qw32_charset_arabic);
14623 Qw32_charset_arabic = intern ("w32-charset-arabic");
14624 staticpro (&Qw32_charset_greek);
14625 Qw32_charset_greek = intern ("w32-charset-greek");
14626 staticpro (&Qw32_charset_hebrew);
14627 Qw32_charset_hebrew = intern ("w32-charset-hebrew");
14628 staticpro (&Qw32_charset_vietnamese);
14629 Qw32_charset_vietnamese = intern ("w32-charset-vietnamese");
14630 staticpro (&Qw32_charset_thai);
14631 Qw32_charset_thai = intern ("w32-charset-thai");
14632 staticpro (&Qw32_charset_mac);
14633 Qw32_charset_mac = intern ("w32-charset-mac");
14634 }
14635 #endif
14636
14637 #ifdef UNICODE_CHARSET
14638 {
14639 static int w32_unicode_charset_defined = 1;
14640 DEFVAR_BOOL ("w32-unicode-charset-defined",
14641 &w32_unicode_charset_defined,
14642 doc: /* Internal variable. */);
14643
14644 staticpro (&Qw32_charset_unicode);
14645 Qw32_charset_unicode = intern ("w32-charset-unicode");
14646 #endif
14647
14648 defsubr (&Sx_get_resource);
14649 #if 0 /* TODO: Port to W32 */
14650 defsubr (&Sx_change_window_property);
14651 defsubr (&Sx_delete_window_property);
14652 defsubr (&Sx_window_property);
14653 #endif
14654 defsubr (&Sxw_display_color_p);
14655 defsubr (&Sx_display_grayscale_p);
14656 defsubr (&Sxw_color_defined_p);
14657 defsubr (&Sxw_color_values);
14658 defsubr (&Sx_server_max_request_size);
14659 defsubr (&Sx_server_vendor);
14660 defsubr (&Sx_server_version);
14661 defsubr (&Sx_display_pixel_width);
14662 defsubr (&Sx_display_pixel_height);
14663 defsubr (&Sx_display_mm_width);
14664 defsubr (&Sx_display_mm_height);
14665 defsubr (&Sx_display_screens);
14666 defsubr (&Sx_display_planes);
14667 defsubr (&Sx_display_color_cells);
14668 defsubr (&Sx_display_visual_class);
14669 defsubr (&Sx_display_backing_store);
14670 defsubr (&Sx_display_save_under);
14671 defsubr (&Sx_parse_geometry);
14672 defsubr (&Sx_create_frame);
14673 defsubr (&Sx_open_connection);
14674 defsubr (&Sx_close_connection);
14675 defsubr (&Sx_display_list);
14676 defsubr (&Sx_synchronize);
14677
14678 /* W32 specific functions */
14679
14680 defsubr (&Sw32_focus_frame);
14681 defsubr (&Sw32_select_font);
14682 defsubr (&Sw32_define_rgb_color);
14683 defsubr (&Sw32_default_color_map);
14684 defsubr (&Sw32_load_color_file);
14685 defsubr (&Sw32_send_sys_command);
14686 defsubr (&Sw32_shell_execute);
14687 defsubr (&Sw32_register_hot_key);
14688 defsubr (&Sw32_unregister_hot_key);
14689 defsubr (&Sw32_registered_hot_keys);
14690 defsubr (&Sw32_reconstruct_hot_key);
14691 defsubr (&Sw32_toggle_lock_key);
14692 defsubr (&Sw32_find_bdf_fonts);
14693
14694 defsubr (&Sfile_system_info);
14695
14696 /* Setting callback functions for fontset handler. */
14697 get_font_info_func = w32_get_font_info;
14698
14699 #if 0 /* This function pointer doesn't seem to be used anywhere.
14700 And the pointer assigned has the wrong type, anyway. */
14701 list_fonts_func = w32_list_fonts;
14702 #endif
14703
14704 load_font_func = w32_load_font;
14705 find_ccl_program_func = w32_find_ccl_program;
14706 query_font_func = w32_query_font;
14707 set_frame_fontset_func = x_set_font;
14708 check_window_system_func = check_w32;
14709
14710 #if 0 /* TODO Image support for W32 */
14711 /* Images. */
14712 Qxbm = intern ("xbm");
14713 staticpro (&Qxbm);
14714 QCtype = intern (":type");
14715 staticpro (&QCtype);
14716 QCconversion = intern (":conversion");
14717 staticpro (&QCconversion);
14718 QCheuristic_mask = intern (":heuristic-mask");
14719 staticpro (&QCheuristic_mask);
14720 QCcolor_symbols = intern (":color-symbols");
14721 staticpro (&QCcolor_symbols);
14722 QCascent = intern (":ascent");
14723 staticpro (&QCascent);
14724 QCmargin = intern (":margin");
14725 staticpro (&QCmargin);
14726 QCrelief = intern (":relief");
14727 staticpro (&QCrelief);
14728 Qpostscript = intern ("postscript");
14729 staticpro (&Qpostscript);
14730 QCloader = intern (":loader");
14731 staticpro (&QCloader);
14732 QCbounding_box = intern (":bounding-box");
14733 staticpro (&QCbounding_box);
14734 QCpt_width = intern (":pt-width");
14735 staticpro (&QCpt_width);
14736 QCpt_height = intern (":pt-height");
14737 staticpro (&QCpt_height);
14738 QCindex = intern (":index");
14739 staticpro (&QCindex);
14740 Qpbm = intern ("pbm");
14741 staticpro (&Qpbm);
14742
14743 #if HAVE_XPM
14744 Qxpm = intern ("xpm");
14745 staticpro (&Qxpm);
14746 #endif
14747
14748 #if HAVE_JPEG
14749 Qjpeg = intern ("jpeg");
14750 staticpro (&Qjpeg);
14751 #endif
14752
14753 #if HAVE_TIFF
14754 Qtiff = intern ("tiff");
14755 staticpro (&Qtiff);
14756 #endif
14757
14758 #if HAVE_GIF
14759 Qgif = intern ("gif");
14760 staticpro (&Qgif);
14761 #endif
14762
14763 #if HAVE_PNG
14764 Qpng = intern ("png");
14765 staticpro (&Qpng);
14766 #endif
14767
14768 defsubr (&Sclear_image_cache);
14769
14770 #if GLYPH_DEBUG
14771 defsubr (&Simagep);
14772 defsubr (&Slookup_image);
14773 #endif
14774 #endif /* TODO */
14775
14776 hourglass_atimer = NULL;
14777 hourglass_shown_p = 0;
14778 defsubr (&Sx_show_tip);
14779 defsubr (&Sx_hide_tip);
14780 tip_timer = Qnil;
14781 staticpro (&tip_timer);
14782 tip_frame = Qnil;
14783 staticpro (&tip_frame);
14784
14785 last_show_tip_args = Qnil;
14786 staticpro (&last_show_tip_args);
14787
14788 defsubr (&Sx_file_dialog);
14789 }
14790
14791
14792 void
14793 init_xfns ()
14794 {
14795 image_types = NULL;
14796 Vimage_types = Qnil;
14797
14798 #if 0 /* TODO : Image support for W32 */
14799 define_image_type (&xbm_type);
14800 define_image_type (&gs_type);
14801 define_image_type (&pbm_type);
14802
14803 #if HAVE_XPM
14804 define_image_type (&xpm_type);
14805 #endif
14806
14807 #if HAVE_JPEG
14808 define_image_type (&jpeg_type);
14809 #endif
14810
14811 #if HAVE_TIFF
14812 define_image_type (&tiff_type);
14813 #endif
14814
14815 #if HAVE_GIF
14816 define_image_type (&gif_type);
14817 #endif
14818
14819 #if HAVE_PNG
14820 define_image_type (&png_type);
14821 #endif
14822 #endif /* TODO */
14823 }
14824
14825 #undef abort
14826
14827 void
14828 w32_abort()
14829 {
14830 int button;
14831 button = MessageBox (NULL,
14832 "A fatal error has occurred!\n\n"
14833 "Select Abort to exit, Retry to debug, Ignore to continue",
14834 "Emacs Abort Dialog",
14835 MB_ICONEXCLAMATION | MB_TASKMODAL
14836 | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
14837 switch (button)
14838 {
14839 case IDRETRY:
14840 DebugBreak ();
14841 break;
14842 case IDIGNORE:
14843 break;
14844 case IDABORT:
14845 default:
14846 abort ();
14847 break;
14848 }
14849 }
14850
14851 /* For convenience when debugging. */
14852 int
14853 w32_last_error()
14854 {
14855 return GetLastError ();
14856 }