]> code.delx.au - gnu-emacs/blob - src/w32fns.c
*** empty log message ***
[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 P_ ((struct frame *, int));
57 extern double atof ();
58 extern int w32_console_toggle_lock_key P_ ((int, Lisp_Object));
59 extern void w32_menu_display_help P_ ((HWND, HMENU, UINT, UINT));
60 extern void w32_free_menu_strings P_ ((HWND));
61
62 extern int quit_char;
63
64 /* A definition of XColor for non-X frames. */
65 #ifndef HAVE_X_WINDOWS
66 typedef struct {
67 unsigned long pixel;
68 unsigned short red, green, blue;
69 char flags;
70 char pad;
71 } XColor;
72 #endif
73
74 extern char *lispy_function_keys[];
75
76 /* The gray bitmap `bitmaps/gray'. This is done because w32term.c uses
77 it, and including `bitmaps/gray' more than once is a problem when
78 config.h defines `static' as an empty replacement string. */
79
80 int gray_bitmap_width = gray_width;
81 int gray_bitmap_height = gray_height;
82 unsigned char *gray_bitmap_bits = gray_bits;
83
84 /* The colormap for converting color names to RGB values */
85 Lisp_Object Vw32_color_map;
86
87 /* Non nil if alt key presses are passed on to Windows. */
88 Lisp_Object Vw32_pass_alt_to_system;
89
90 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
91 to alt_modifier. */
92 Lisp_Object Vw32_alt_is_meta;
93
94 /* If non-zero, the windows virtual key code for an alternative quit key. */
95 Lisp_Object Vw32_quit_key;
96
97 /* Non nil if left window key events are passed on to Windows (this only
98 affects whether "tapping" the key opens the Start menu). */
99 Lisp_Object Vw32_pass_lwindow_to_system;
100
101 /* Non nil if right window key events are passed on to Windows (this
102 only affects whether "tapping" the key opens the Start menu). */
103 Lisp_Object Vw32_pass_rwindow_to_system;
104
105 /* Virtual key code used to generate "phantom" key presses in order
106 to stop system from acting on Windows key events. */
107 Lisp_Object Vw32_phantom_key_code;
108
109 /* Modifier associated with the left "Windows" key, or nil to act as a
110 normal key. */
111 Lisp_Object Vw32_lwindow_modifier;
112
113 /* Modifier associated with the right "Windows" key, or nil to act as a
114 normal key. */
115 Lisp_Object Vw32_rwindow_modifier;
116
117 /* Modifier associated with the "Apps" key, or nil to act as a normal
118 key. */
119 Lisp_Object Vw32_apps_modifier;
120
121 /* Value is nil if Num Lock acts as a function key. */
122 Lisp_Object Vw32_enable_num_lock;
123
124 /* Value is nil if Caps Lock acts as a function key. */
125 Lisp_Object Vw32_enable_caps_lock;
126
127 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
128 Lisp_Object Vw32_scroll_lock_modifier;
129
130 /* Switch to control whether we inhibit requests for synthesized bold
131 and italic versions of fonts. */
132 int w32_enable_synthesized_fonts;
133
134 /* Enable palette management. */
135 Lisp_Object Vw32_enable_palette;
136
137 /* Control how close left/right button down events must be to
138 be converted to a middle button down event. */
139 Lisp_Object Vw32_mouse_button_tolerance;
140
141 /* Minimum interval between mouse movement (and scroll bar drag)
142 events that are passed on to the event loop. */
143 Lisp_Object Vw32_mouse_move_interval;
144
145 /* Flag to indicate if XBUTTON events should be passed on to Windows. */
146 int w32_pass_extra_mouse_buttons_to_system;
147
148 /* The name we're using in resource queries. */
149 Lisp_Object Vx_resource_name;
150
151 /* Non nil if no window manager is in use. */
152 Lisp_Object Vx_no_window_manager;
153
154 /* Non-zero means we're allowed to display a hourglass pointer. */
155
156 int display_hourglass_p;
157
158 /* The background and shape of the mouse pointer, and shape when not
159 over text or in the modeline. */
160
161 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
162 Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape;
163
164 /* The shape when over mouse-sensitive text. */
165
166 Lisp_Object Vx_sensitive_text_pointer_shape;
167
168 /* Color of chars displayed in cursor box. */
169
170 Lisp_Object Vx_cursor_fore_pixel;
171
172 /* Nonzero if using Windows. */
173
174 static int w32_in_use;
175
176 /* Search path for bitmap files. */
177
178 Lisp_Object Vx_bitmap_file_path;
179
180 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
181
182 Lisp_Object Vx_pixel_size_width_font_regexp;
183
184 /* Alist of bdf fonts and the files that define them. */
185 Lisp_Object Vw32_bdf_filename_alist;
186
187 /* A flag to control whether fonts are matched strictly or not. */
188 int w32_strict_fontnames;
189
190 /* A flag to control whether we should only repaint if GetUpdateRect
191 indicates there is an update region. */
192 int w32_strict_painting;
193
194 /* Associative list linking character set strings to Windows codepages. */
195 Lisp_Object Vw32_charset_info_alist;
196
197 /* VIETNAMESE_CHARSET is not defined in some versions of MSVC. */
198 #ifndef VIETNAMESE_CHARSET
199 #define VIETNAMESE_CHARSET 163
200 #endif
201
202 Lisp_Object Qauto_raise;
203 Lisp_Object Qauto_lower;
204 Lisp_Object Qbar;
205 Lisp_Object Qborder_color;
206 Lisp_Object Qborder_width;
207 Lisp_Object Qbox;
208 Lisp_Object Qcursor_color;
209 Lisp_Object Qcursor_type;
210 Lisp_Object Qgeometry;
211 Lisp_Object Qicon_left;
212 Lisp_Object Qicon_top;
213 Lisp_Object Qicon_type;
214 Lisp_Object Qicon_name;
215 Lisp_Object Qinternal_border_width;
216 Lisp_Object Qleft;
217 Lisp_Object Qright;
218 Lisp_Object Qmouse_color;
219 Lisp_Object Qnone;
220 Lisp_Object Qparent_id;
221 Lisp_Object Qscroll_bar_width;
222 Lisp_Object Qsuppress_icon;
223 Lisp_Object Qundefined_color;
224 Lisp_Object Qvertical_scroll_bars;
225 Lisp_Object Qvisibility;
226 Lisp_Object Qwindow_id;
227 Lisp_Object Qx_frame_parameter;
228 Lisp_Object Qx_resource_name;
229 Lisp_Object Quser_position;
230 Lisp_Object Quser_size;
231 Lisp_Object Qscreen_gamma;
232 Lisp_Object Qline_spacing;
233 Lisp_Object Qcenter;
234 Lisp_Object Qcancel_timer;
235 Lisp_Object Qhyper;
236 Lisp_Object Qsuper;
237 Lisp_Object Qmeta;
238 Lisp_Object Qalt;
239 Lisp_Object Qctrl;
240 Lisp_Object Qcontrol;
241 Lisp_Object Qshift;
242
243 Lisp_Object Qw32_charset_ansi;
244 Lisp_Object Qw32_charset_default;
245 Lisp_Object Qw32_charset_symbol;
246 Lisp_Object Qw32_charset_shiftjis;
247 Lisp_Object Qw32_charset_hangeul;
248 Lisp_Object Qw32_charset_gb2312;
249 Lisp_Object Qw32_charset_chinesebig5;
250 Lisp_Object Qw32_charset_oem;
251
252 #ifndef JOHAB_CHARSET
253 #define JOHAB_CHARSET 130
254 #endif
255 #ifdef JOHAB_CHARSET
256 Lisp_Object Qw32_charset_easteurope;
257 Lisp_Object Qw32_charset_turkish;
258 Lisp_Object Qw32_charset_baltic;
259 Lisp_Object Qw32_charset_russian;
260 Lisp_Object Qw32_charset_arabic;
261 Lisp_Object Qw32_charset_greek;
262 Lisp_Object Qw32_charset_hebrew;
263 Lisp_Object Qw32_charset_vietnamese;
264 Lisp_Object Qw32_charset_thai;
265 Lisp_Object Qw32_charset_johab;
266 Lisp_Object Qw32_charset_mac;
267 #endif
268
269 #ifdef UNICODE_CHARSET
270 Lisp_Object Qw32_charset_unicode;
271 #endif
272
273 extern Lisp_Object Qtop;
274 extern Lisp_Object Qdisplay;
275 extern Lisp_Object Qtool_bar_lines;
276
277 /* State variables for emulating a three button mouse. */
278 #define LMOUSE 1
279 #define MMOUSE 2
280 #define RMOUSE 4
281
282 static int button_state = 0;
283 static W32Msg saved_mouse_button_msg;
284 static unsigned mouse_button_timer; /* non-zero when timer is active */
285 static W32Msg saved_mouse_move_msg;
286 static unsigned mouse_move_timer;
287
288 /* Window that is tracking the mouse. */
289 static HWND track_mouse_window;
290 FARPROC track_mouse_event_fn;
291
292 /* W95 mousewheel handler */
293 unsigned int msh_mousewheel = 0;
294
295 #define MOUSE_BUTTON_ID 1
296 #define MOUSE_MOVE_ID 2
297
298 /* The below are defined in frame.c. */
299
300 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
301 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
302 extern Lisp_Object Qtool_bar_lines;
303
304 extern Lisp_Object Vwindow_system_version;
305
306 Lisp_Object Qface_set_after_frame_default;
307
308 #ifdef GLYPH_DEBUG
309 int image_cache_refcount, dpyinfo_refcount;
310 #endif
311
312
313 /* From w32term.c. */
314 extern Lisp_Object Vw32_num_mouse_buttons;
315 extern Lisp_Object Vw32_recognize_altgr;
316
317 extern HWND w32_system_caret_hwnd;
318
319 extern int w32_system_caret_height;
320 extern int w32_system_caret_x;
321 extern int w32_system_caret_y;
322 extern int w32_use_visible_system_caret;
323
324 static HWND w32_visible_system_caret_hwnd;
325
326 \f
327 /* Error if we are not connected to MS-Windows. */
328 void
329 check_w32 ()
330 {
331 if (! w32_in_use)
332 error ("MS-Windows not in use or not initialized");
333 }
334
335 /* Nonzero if we can use mouse menus.
336 You should not call this unless HAVE_MENUS is defined. */
337
338 int
339 have_menus_p ()
340 {
341 return w32_in_use;
342 }
343
344 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
345 and checking validity for W32. */
346
347 FRAME_PTR
348 check_x_frame (frame)
349 Lisp_Object frame;
350 {
351 FRAME_PTR f;
352
353 if (NILP (frame))
354 frame = selected_frame;
355 CHECK_LIVE_FRAME (frame);
356 f = XFRAME (frame);
357 if (! FRAME_W32_P (f))
358 error ("non-w32 frame used");
359 return f;
360 }
361
362 /* Let the user specify an display with a frame.
363 nil stands for the selected frame--or, if that is not a w32 frame,
364 the first display on the list. */
365
366 static struct w32_display_info *
367 check_x_display_info (frame)
368 Lisp_Object frame;
369 {
370 if (NILP (frame))
371 {
372 struct frame *sf = XFRAME (selected_frame);
373
374 if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
375 return FRAME_W32_DISPLAY_INFO (sf);
376 else
377 return &one_w32_display_info;
378 }
379 else if (STRINGP (frame))
380 return x_display_info_for_name (frame);
381 else
382 {
383 FRAME_PTR f;
384
385 CHECK_LIVE_FRAME (frame);
386 f = XFRAME (frame);
387 if (! FRAME_W32_P (f))
388 error ("non-w32 frame used");
389 return FRAME_W32_DISPLAY_INFO (f);
390 }
391 }
392 \f
393 /* Return the Emacs frame-object corresponding to an w32 window.
394 It could be the frame's main window or an icon window. */
395
396 /* This function can be called during GC, so use GC_xxx type test macros. */
397
398 struct frame *
399 x_window_to_frame (dpyinfo, wdesc)
400 struct w32_display_info *dpyinfo;
401 HWND wdesc;
402 {
403 Lisp_Object tail, frame;
404 struct frame *f;
405
406 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
407 {
408 frame = XCAR (tail);
409 if (!GC_FRAMEP (frame))
410 continue;
411 f = XFRAME (frame);
412 if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
413 continue;
414 if (f->output_data.w32->hourglass_window == wdesc)
415 return f;
416
417 if (FRAME_W32_WINDOW (f) == wdesc)
418 return f;
419 }
420 return 0;
421 }
422
423 \f
424
425 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
426 id, which is just an int that this section returns. Bitmaps are
427 reference counted so they can be shared among frames.
428
429 Bitmap indices are guaranteed to be > 0, so a negative number can
430 be used to indicate no bitmap.
431
432 If you use x_create_bitmap_from_data, then you must keep track of
433 the bitmaps yourself. That is, creating a bitmap from the same
434 data more than once will not be caught. */
435
436
437 /* Functions to access the contents of a bitmap, given an id. */
438
439 int
440 x_bitmap_height (f, id)
441 FRAME_PTR f;
442 int id;
443 {
444 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
445 }
446
447 int
448 x_bitmap_width (f, id)
449 FRAME_PTR f;
450 int id;
451 {
452 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
453 }
454
455 int
456 x_bitmap_pixmap (f, id)
457 FRAME_PTR f;
458 int id;
459 {
460 return (int) FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
461 }
462
463
464 /* Allocate a new bitmap record. Returns index of new record. */
465
466 static int
467 x_allocate_bitmap_record (f)
468 FRAME_PTR f;
469 {
470 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
471 int i;
472
473 if (dpyinfo->bitmaps == NULL)
474 {
475 dpyinfo->bitmaps_size = 10;
476 dpyinfo->bitmaps
477 = (struct w32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
478 dpyinfo->bitmaps_last = 1;
479 return 1;
480 }
481
482 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
483 return ++dpyinfo->bitmaps_last;
484
485 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
486 if (dpyinfo->bitmaps[i].refcount == 0)
487 return i + 1;
488
489 dpyinfo->bitmaps_size *= 2;
490 dpyinfo->bitmaps
491 = (struct w32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
492 dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
493 return ++dpyinfo->bitmaps_last;
494 }
495
496 /* Add one reference to the reference count of the bitmap with id ID. */
497
498 void
499 x_reference_bitmap (f, id)
500 FRAME_PTR f;
501 int id;
502 {
503 ++FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
504 }
505
506 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
507
508 int
509 x_create_bitmap_from_data (f, bits, width, height)
510 struct frame *f;
511 char *bits;
512 unsigned int width, height;
513 {
514 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
515 Pixmap bitmap;
516 int id;
517
518 bitmap = CreateBitmap (width, height,
519 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes,
520 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
521 bits);
522
523 if (! bitmap)
524 return -1;
525
526 id = x_allocate_bitmap_record (f);
527 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
528 dpyinfo->bitmaps[id - 1].file = NULL;
529 dpyinfo->bitmaps[id - 1].hinst = NULL;
530 dpyinfo->bitmaps[id - 1].refcount = 1;
531 dpyinfo->bitmaps[id - 1].depth = 1;
532 dpyinfo->bitmaps[id - 1].height = height;
533 dpyinfo->bitmaps[id - 1].width = width;
534
535 return id;
536 }
537
538 /* Create bitmap from file FILE for frame F. */
539
540 int
541 x_create_bitmap_from_file (f, file)
542 struct frame *f;
543 Lisp_Object file;
544 {
545 return -1;
546 #if 0 /* TODO : bitmap support */
547 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
548 unsigned int width, height;
549 HBITMAP bitmap;
550 int xhot, yhot, result, id;
551 Lisp_Object found;
552 int fd;
553 char *filename;
554 HINSTANCE hinst;
555
556 /* Look for an existing bitmap with the same name. */
557 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
558 {
559 if (dpyinfo->bitmaps[id].refcount
560 && dpyinfo->bitmaps[id].file
561 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
562 {
563 ++dpyinfo->bitmaps[id].refcount;
564 return id + 1;
565 }
566 }
567
568 /* Search bitmap-file-path for the file, if appropriate. */
569 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, 0);
570 if (fd < 0)
571 return -1;
572 emacs_close (fd);
573
574 filename = (char *) XSTRING (found)->data;
575
576 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
577
578 if (hinst == NULL)
579 return -1;
580
581
582 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
583 filename, &width, &height, &bitmap, &xhot, &yhot);
584 if (result != BitmapSuccess)
585 return -1;
586
587 id = x_allocate_bitmap_record (f);
588 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
589 dpyinfo->bitmaps[id - 1].refcount = 1;
590 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
591 dpyinfo->bitmaps[id - 1].depth = 1;
592 dpyinfo->bitmaps[id - 1].height = height;
593 dpyinfo->bitmaps[id - 1].width = width;
594 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
595
596 return id;
597 #endif /* TODO */
598 }
599
600 /* Remove reference to bitmap with id number ID. */
601
602 void
603 x_destroy_bitmap (f, id)
604 FRAME_PTR f;
605 int id;
606 {
607 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
608
609 if (id > 0)
610 {
611 --dpyinfo->bitmaps[id - 1].refcount;
612 if (dpyinfo->bitmaps[id - 1].refcount == 0)
613 {
614 BLOCK_INPUT;
615 DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
616 if (dpyinfo->bitmaps[id - 1].file)
617 {
618 xfree (dpyinfo->bitmaps[id - 1].file);
619 dpyinfo->bitmaps[id - 1].file = NULL;
620 }
621 UNBLOCK_INPUT;
622 }
623 }
624 }
625
626 /* Free all the bitmaps for the display specified by DPYINFO. */
627
628 static void
629 x_destroy_all_bitmaps (dpyinfo)
630 struct w32_display_info *dpyinfo;
631 {
632 int i;
633 for (i = 0; i < dpyinfo->bitmaps_last; i++)
634 if (dpyinfo->bitmaps[i].refcount > 0)
635 {
636 DeleteObject (dpyinfo->bitmaps[i].pixmap);
637 if (dpyinfo->bitmaps[i].file)
638 xfree (dpyinfo->bitmaps[i].file);
639 }
640 dpyinfo->bitmaps_last = 0;
641 }
642 \f
643 /* Connect the frame-parameter names for W32 frames
644 to the ways of passing the parameter values to the window system.
645
646 The name of a parameter, as a Lisp symbol,
647 has an `x-frame-parameter' property which is an integer in Lisp
648 but can be interpreted as an `enum x_frame_parm' in C. */
649
650 enum x_frame_parm
651 {
652 X_PARM_FOREGROUND_COLOR,
653 X_PARM_BACKGROUND_COLOR,
654 X_PARM_MOUSE_COLOR,
655 X_PARM_CURSOR_COLOR,
656 X_PARM_BORDER_COLOR,
657 X_PARM_ICON_TYPE,
658 X_PARM_FONT,
659 X_PARM_BORDER_WIDTH,
660 X_PARM_INTERNAL_BORDER_WIDTH,
661 X_PARM_NAME,
662 X_PARM_AUTORAISE,
663 X_PARM_AUTOLOWER,
664 X_PARM_VERT_SCROLL_BAR,
665 X_PARM_VISIBILITY,
666 X_PARM_MENU_BAR_LINES
667 };
668
669
670 struct x_frame_parm_table
671 {
672 char *name;
673 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
674 };
675
676 BOOL my_show_window P_ ((struct frame *, HWND, int));
677 void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
678 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
679 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
680 static void x_change_window_heights P_ ((Lisp_Object, int));
681 /* TODO: Native Input Method support; see x_create_im. */
682 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
683 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
684 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
685 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
686 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
687 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
688 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
689 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
690 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
691 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
692 static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
693 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
694 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
695 Lisp_Object));
696 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
697 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
698 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
699 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
700 Lisp_Object));
701 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
702 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
703 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
704 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
705 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
706 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
707 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
708 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
709 Lisp_Object));
710
711 static struct x_frame_parm_table x_frame_parms[] =
712 {
713 {"auto-raise", x_set_autoraise},
714 {"auto-lower", x_set_autolower},
715 {"background-color", x_set_background_color},
716 {"border-color", x_set_border_color},
717 {"border-width", x_set_border_width},
718 {"cursor-color", x_set_cursor_color},
719 {"cursor-type", x_set_cursor_type},
720 {"font", x_set_font},
721 {"foreground-color", x_set_foreground_color},
722 {"icon-name", x_set_icon_name},
723 {"icon-type", x_set_icon_type},
724 {"internal-border-width", x_set_internal_border_width},
725 {"menu-bar-lines", x_set_menu_bar_lines},
726 {"mouse-color", x_set_mouse_color},
727 {"name", x_explicitly_set_name},
728 {"scroll-bar-width", x_set_scroll_bar_width},
729 {"title", x_set_title},
730 {"unsplittable", x_set_unsplittable},
731 {"vertical-scroll-bars", x_set_vertical_scroll_bars},
732 {"visibility", x_set_visibility},
733 {"tool-bar-lines", x_set_tool_bar_lines},
734 {"screen-gamma", x_set_screen_gamma},
735 {"line-spacing", x_set_line_spacing},
736 {"left-fringe", x_set_fringe_width},
737 {"right-fringe", x_set_fringe_width}
738 };
739
740 /* Attach the `x-frame-parameter' properties to
741 the Lisp symbol names of parameters relevant to W32. */
742
743 void
744 init_x_parm_symbols ()
745 {
746 int i;
747
748 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
749 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
750 make_number (i));
751 }
752 \f
753 /* Change the parameters of frame F as specified by ALIST.
754 If a parameter is not specially recognized, do nothing;
755 otherwise call the `x_set_...' function for that parameter. */
756
757 void
758 x_set_frame_parameters (f, alist)
759 FRAME_PTR f;
760 Lisp_Object alist;
761 {
762 Lisp_Object tail;
763
764 /* If both of these parameters are present, it's more efficient to
765 set them both at once. So we wait until we've looked at the
766 entire list before we set them. */
767 int width, height;
768
769 /* Same here. */
770 Lisp_Object left, top;
771
772 /* Same with these. */
773 Lisp_Object icon_left, icon_top;
774
775 /* Record in these vectors all the parms specified. */
776 Lisp_Object *parms;
777 Lisp_Object *values;
778 int i, p;
779 int left_no_change = 0, top_no_change = 0;
780 int icon_left_no_change = 0, icon_top_no_change = 0;
781
782 struct gcpro gcpro1, gcpro2;
783
784 i = 0;
785 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
786 i++;
787
788 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
789 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
790
791 /* Extract parm names and values into those vectors. */
792
793 i = 0;
794 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
795 {
796 Lisp_Object elt;
797
798 elt = Fcar (tail);
799 parms[i] = Fcar (elt);
800 values[i] = Fcdr (elt);
801 i++;
802 }
803 /* TAIL and ALIST are not used again below here. */
804 alist = tail = Qnil;
805
806 GCPRO2 (*parms, *values);
807 gcpro1.nvars = i;
808 gcpro2.nvars = i;
809
810 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
811 because their values appear in VALUES and strings are not valid. */
812 top = left = Qunbound;
813 icon_left = icon_top = Qunbound;
814
815 /* Provide default values for HEIGHT and WIDTH. */
816 if (FRAME_NEW_WIDTH (f))
817 width = FRAME_NEW_WIDTH (f);
818 else
819 width = FRAME_WIDTH (f);
820
821 if (FRAME_NEW_HEIGHT (f))
822 height = FRAME_NEW_HEIGHT (f);
823 else
824 height = FRAME_HEIGHT (f);
825
826 /* Process foreground_color and background_color before anything else.
827 They are independent of other properties, but other properties (e.g.,
828 cursor_color) are dependent upon them. */
829 /* Process default font as well, since fringe widths depends on it. */
830 for (p = 0; p < i; p++)
831 {
832 Lisp_Object prop, val;
833
834 prop = parms[p];
835 val = values[p];
836 if (EQ (prop, Qforeground_color)
837 || EQ (prop, Qbackground_color)
838 || EQ (prop, Qfont))
839 {
840 register Lisp_Object param_index, old_value;
841
842 old_value = get_frame_param (f, prop);
843
844 if (NILP (Fequal (val, old_value)))
845 {
846 store_frame_param (f, prop, val);
847
848 param_index = Fget (prop, Qx_frame_parameter);
849 if (NATNUMP (param_index)
850 && (XFASTINT (param_index)
851 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
852 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
853 }
854 }
855 }
856
857 /* Now process them in reverse of specified order. */
858 for (i--; i >= 0; i--)
859 {
860 Lisp_Object prop, val;
861
862 prop = parms[i];
863 val = values[i];
864
865 if (EQ (prop, Qwidth) && NUMBERP (val))
866 width = XFASTINT (val);
867 else if (EQ (prop, Qheight) && NUMBERP (val))
868 height = XFASTINT (val);
869 else if (EQ (prop, Qtop))
870 top = val;
871 else if (EQ (prop, Qleft))
872 left = val;
873 else if (EQ (prop, Qicon_top))
874 icon_top = val;
875 else if (EQ (prop, Qicon_left))
876 icon_left = val;
877 else if (EQ (prop, Qforeground_color)
878 || EQ (prop, Qbackground_color)
879 || EQ (prop, Qfont))
880 /* Processed above. */
881 continue;
882 else
883 {
884 register Lisp_Object param_index, old_value;
885
886 old_value = get_frame_param (f, prop);
887
888 store_frame_param (f, prop, val);
889
890 param_index = Fget (prop, Qx_frame_parameter);
891 if (NATNUMP (param_index)
892 && (XFASTINT (param_index)
893 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
894 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
895 }
896 }
897
898 /* Don't die if just one of these was set. */
899 if (EQ (left, Qunbound))
900 {
901 left_no_change = 1;
902 if (f->output_data.w32->left_pos < 0)
903 left = Fcons (Qplus, Fcons (make_number (f->output_data.w32->left_pos), Qnil));
904 else
905 XSETINT (left, f->output_data.w32->left_pos);
906 }
907 if (EQ (top, Qunbound))
908 {
909 top_no_change = 1;
910 if (f->output_data.w32->top_pos < 0)
911 top = Fcons (Qplus, Fcons (make_number (f->output_data.w32->top_pos), Qnil));
912 else
913 XSETINT (top, f->output_data.w32->top_pos);
914 }
915
916 /* If one of the icon positions was not set, preserve or default it. */
917 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
918 {
919 icon_left_no_change = 1;
920 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
921 if (NILP (icon_left))
922 XSETINT (icon_left, 0);
923 }
924 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
925 {
926 icon_top_no_change = 1;
927 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
928 if (NILP (icon_top))
929 XSETINT (icon_top, 0);
930 }
931
932 /* Don't set these parameters unless they've been explicitly
933 specified. The window might be mapped or resized while we're in
934 this function, and we don't want to override that unless the lisp
935 code has asked for it.
936
937 Don't set these parameters unless they actually differ from the
938 window's current parameters; the window may not actually exist
939 yet. */
940 {
941 Lisp_Object frame;
942
943 check_frame_size (f, &height, &width);
944
945 XSETFRAME (frame, f);
946
947 if (width != FRAME_WIDTH (f)
948 || height != FRAME_HEIGHT (f)
949 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
950 Fset_frame_size (frame, make_number (width), make_number (height));
951
952 if ((!NILP (left) || !NILP (top))
953 && ! (left_no_change && top_no_change)
954 && ! (NUMBERP (left) && XINT (left) == f->output_data.w32->left_pos
955 && NUMBERP (top) && XINT (top) == f->output_data.w32->top_pos))
956 {
957 int leftpos = 0;
958 int toppos = 0;
959
960 /* Record the signs. */
961 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
962 if (EQ (left, Qminus))
963 f->output_data.w32->size_hint_flags |= XNegative;
964 else if (INTEGERP (left))
965 {
966 leftpos = XINT (left);
967 if (leftpos < 0)
968 f->output_data.w32->size_hint_flags |= XNegative;
969 }
970 else if (CONSP (left) && EQ (XCAR (left), Qminus)
971 && CONSP (XCDR (left))
972 && INTEGERP (XCAR (XCDR (left))))
973 {
974 leftpos = - XINT (XCAR (XCDR (left)));
975 f->output_data.w32->size_hint_flags |= XNegative;
976 }
977 else if (CONSP (left) && EQ (XCAR (left), Qplus)
978 && CONSP (XCDR (left))
979 && INTEGERP (XCAR (XCDR (left))))
980 {
981 leftpos = XINT (XCAR (XCDR (left)));
982 }
983
984 if (EQ (top, Qminus))
985 f->output_data.w32->size_hint_flags |= YNegative;
986 else if (INTEGERP (top))
987 {
988 toppos = XINT (top);
989 if (toppos < 0)
990 f->output_data.w32->size_hint_flags |= YNegative;
991 }
992 else if (CONSP (top) && EQ (XCAR (top), Qminus)
993 && CONSP (XCDR (top))
994 && INTEGERP (XCAR (XCDR (top))))
995 {
996 toppos = - XINT (XCAR (XCDR (top)));
997 f->output_data.w32->size_hint_flags |= YNegative;
998 }
999 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1000 && CONSP (XCDR (top))
1001 && INTEGERP (XCAR (XCDR (top))))
1002 {
1003 toppos = XINT (XCAR (XCDR (top)));
1004 }
1005
1006
1007 /* Store the numeric value of the position. */
1008 f->output_data.w32->top_pos = toppos;
1009 f->output_data.w32->left_pos = leftpos;
1010
1011 f->output_data.w32->win_gravity = NorthWestGravity;
1012
1013 /* Actually set that position, and convert to absolute. */
1014 x_set_offset (f, leftpos, toppos, -1);
1015 }
1016
1017 if ((!NILP (icon_left) || !NILP (icon_top))
1018 && ! (icon_left_no_change && icon_top_no_change))
1019 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1020 }
1021
1022 UNGCPRO;
1023 }
1024
1025 /* Store the screen positions of frame F into XPTR and YPTR.
1026 These are the positions of the containing window manager window,
1027 not Emacs's own window. */
1028
1029 void
1030 x_real_positions (f, xptr, yptr)
1031 FRAME_PTR f;
1032 int *xptr, *yptr;
1033 {
1034 POINT pt;
1035
1036 {
1037 RECT rect;
1038
1039 GetClientRect(FRAME_W32_WINDOW(f), &rect);
1040 AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
1041
1042 pt.x = rect.left;
1043 pt.y = rect.top;
1044 }
1045
1046 ClientToScreen (FRAME_W32_WINDOW(f), &pt);
1047
1048 *xptr = pt.x;
1049 *yptr = pt.y;
1050 }
1051
1052 /* Insert a description of internally-recorded parameters of frame X
1053 into the parameter alist *ALISTPTR that is to be given to the user.
1054 Only parameters that are specific to W32
1055 and whose values are not correctly recorded in the frame's
1056 param_alist need to be considered here. */
1057
1058 void
1059 x_report_frame_params (f, alistptr)
1060 struct frame *f;
1061 Lisp_Object *alistptr;
1062 {
1063 char buf[16];
1064 Lisp_Object tem;
1065
1066 /* Represent negative positions (off the top or left screen edge)
1067 in a way that Fmodify_frame_parameters will understand correctly. */
1068 XSETINT (tem, f->output_data.w32->left_pos);
1069 if (f->output_data.w32->left_pos >= 0)
1070 store_in_alist (alistptr, Qleft, tem);
1071 else
1072 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1073
1074 XSETINT (tem, f->output_data.w32->top_pos);
1075 if (f->output_data.w32->top_pos >= 0)
1076 store_in_alist (alistptr, Qtop, tem);
1077 else
1078 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1079
1080 store_in_alist (alistptr, Qborder_width,
1081 make_number (f->output_data.w32->border_width));
1082 store_in_alist (alistptr, Qinternal_border_width,
1083 make_number (f->output_data.w32->internal_border_width));
1084 store_in_alist (alistptr, Qleft_fringe,
1085 make_number (f->output_data.w32->left_fringe_width));
1086 store_in_alist (alistptr, Qright_fringe,
1087 make_number (f->output_data.w32->right_fringe_width));
1088 store_in_alist (alistptr, Qscroll_bar_width,
1089 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
1090 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f)
1091 : 0));
1092 sprintf (buf, "%ld", (long) FRAME_W32_WINDOW (f));
1093 store_in_alist (alistptr, Qwindow_id,
1094 build_string (buf));
1095 store_in_alist (alistptr, Qicon_name, f->icon_name);
1096 FRAME_SAMPLE_VISIBILITY (f);
1097 store_in_alist (alistptr, Qvisibility,
1098 (FRAME_VISIBLE_P (f) ? Qt
1099 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1100 store_in_alist (alistptr, Qdisplay,
1101 XCAR (FRAME_W32_DISPLAY_INFO (f)->name_list_element));
1102 }
1103 \f
1104
1105 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
1106 Sw32_define_rgb_color, 4, 4, 0,
1107 doc: /* Convert RGB numbers to a windows color reference and associate with NAME.
1108 This adds or updates a named color to w32-color-map, making it
1109 available for use. The original entry's RGB ref is returned, or nil
1110 if the entry is new. */)
1111 (red, green, blue, name)
1112 Lisp_Object red, green, blue, name;
1113 {
1114 Lisp_Object rgb;
1115 Lisp_Object oldrgb = Qnil;
1116 Lisp_Object entry;
1117
1118 CHECK_NUMBER (red);
1119 CHECK_NUMBER (green);
1120 CHECK_NUMBER (blue);
1121 CHECK_STRING (name);
1122
1123 XSET (rgb, Lisp_Int, RGB(XUINT (red), XUINT (green), XUINT (blue)));
1124
1125 BLOCK_INPUT;
1126
1127 /* replace existing entry in w32-color-map or add new entry. */
1128 entry = Fassoc (name, Vw32_color_map);
1129 if (NILP (entry))
1130 {
1131 entry = Fcons (name, rgb);
1132 Vw32_color_map = Fcons (entry, Vw32_color_map);
1133 }
1134 else
1135 {
1136 oldrgb = Fcdr (entry);
1137 Fsetcdr (entry, rgb);
1138 }
1139
1140 UNBLOCK_INPUT;
1141
1142 return (oldrgb);
1143 }
1144
1145 DEFUN ("w32-load-color-file", Fw32_load_color_file,
1146 Sw32_load_color_file, 1, 1, 0,
1147 doc: /* Create an alist of color entries from an external file.
1148 Assign this value to w32-color-map to replace the existing color map.
1149
1150 The file should define one named RGB color per line like so:
1151 R G B name
1152 where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
1153 (filename)
1154 Lisp_Object filename;
1155 {
1156 FILE *fp;
1157 Lisp_Object cmap = Qnil;
1158 Lisp_Object abspath;
1159
1160 CHECK_STRING (filename);
1161 abspath = Fexpand_file_name (filename, Qnil);
1162
1163 fp = fopen (XSTRING (filename)->data, "rt");
1164 if (fp)
1165 {
1166 char buf[512];
1167 int red, green, blue;
1168 int num;
1169
1170 BLOCK_INPUT;
1171
1172 while (fgets (buf, sizeof (buf), fp) != NULL) {
1173 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
1174 {
1175 char *name = buf + num;
1176 num = strlen (name) - 1;
1177 if (name[num] == '\n')
1178 name[num] = 0;
1179 cmap = Fcons (Fcons (build_string (name),
1180 make_number (RGB (red, green, blue))),
1181 cmap);
1182 }
1183 }
1184 fclose (fp);
1185
1186 UNBLOCK_INPUT;
1187 }
1188
1189 return cmap;
1190 }
1191
1192 /* The default colors for the w32 color map */
1193 typedef struct colormap_t
1194 {
1195 char *name;
1196 COLORREF colorref;
1197 } colormap_t;
1198
1199 colormap_t w32_color_map[] =
1200 {
1201 {"snow" , PALETTERGB (255,250,250)},
1202 {"ghost white" , PALETTERGB (248,248,255)},
1203 {"GhostWhite" , PALETTERGB (248,248,255)},
1204 {"white smoke" , PALETTERGB (245,245,245)},
1205 {"WhiteSmoke" , PALETTERGB (245,245,245)},
1206 {"gainsboro" , PALETTERGB (220,220,220)},
1207 {"floral white" , PALETTERGB (255,250,240)},
1208 {"FloralWhite" , PALETTERGB (255,250,240)},
1209 {"old lace" , PALETTERGB (253,245,230)},
1210 {"OldLace" , PALETTERGB (253,245,230)},
1211 {"linen" , PALETTERGB (250,240,230)},
1212 {"antique white" , PALETTERGB (250,235,215)},
1213 {"AntiqueWhite" , PALETTERGB (250,235,215)},
1214 {"papaya whip" , PALETTERGB (255,239,213)},
1215 {"PapayaWhip" , PALETTERGB (255,239,213)},
1216 {"blanched almond" , PALETTERGB (255,235,205)},
1217 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
1218 {"bisque" , PALETTERGB (255,228,196)},
1219 {"peach puff" , PALETTERGB (255,218,185)},
1220 {"PeachPuff" , PALETTERGB (255,218,185)},
1221 {"navajo white" , PALETTERGB (255,222,173)},
1222 {"NavajoWhite" , PALETTERGB (255,222,173)},
1223 {"moccasin" , PALETTERGB (255,228,181)},
1224 {"cornsilk" , PALETTERGB (255,248,220)},
1225 {"ivory" , PALETTERGB (255,255,240)},
1226 {"lemon chiffon" , PALETTERGB (255,250,205)},
1227 {"LemonChiffon" , PALETTERGB (255,250,205)},
1228 {"seashell" , PALETTERGB (255,245,238)},
1229 {"honeydew" , PALETTERGB (240,255,240)},
1230 {"mint cream" , PALETTERGB (245,255,250)},
1231 {"MintCream" , PALETTERGB (245,255,250)},
1232 {"azure" , PALETTERGB (240,255,255)},
1233 {"alice blue" , PALETTERGB (240,248,255)},
1234 {"AliceBlue" , PALETTERGB (240,248,255)},
1235 {"lavender" , PALETTERGB (230,230,250)},
1236 {"lavender blush" , PALETTERGB (255,240,245)},
1237 {"LavenderBlush" , PALETTERGB (255,240,245)},
1238 {"misty rose" , PALETTERGB (255,228,225)},
1239 {"MistyRose" , PALETTERGB (255,228,225)},
1240 {"white" , PALETTERGB (255,255,255)},
1241 {"black" , PALETTERGB ( 0, 0, 0)},
1242 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1243 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1244 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1245 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1246 {"dim gray" , PALETTERGB (105,105,105)},
1247 {"DimGray" , PALETTERGB (105,105,105)},
1248 {"dim grey" , PALETTERGB (105,105,105)},
1249 {"DimGrey" , PALETTERGB (105,105,105)},
1250 {"slate gray" , PALETTERGB (112,128,144)},
1251 {"SlateGray" , PALETTERGB (112,128,144)},
1252 {"slate grey" , PALETTERGB (112,128,144)},
1253 {"SlateGrey" , PALETTERGB (112,128,144)},
1254 {"light slate gray" , PALETTERGB (119,136,153)},
1255 {"LightSlateGray" , PALETTERGB (119,136,153)},
1256 {"light slate grey" , PALETTERGB (119,136,153)},
1257 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1258 {"gray" , PALETTERGB (190,190,190)},
1259 {"grey" , PALETTERGB (190,190,190)},
1260 {"light grey" , PALETTERGB (211,211,211)},
1261 {"LightGrey" , PALETTERGB (211,211,211)},
1262 {"light gray" , PALETTERGB (211,211,211)},
1263 {"LightGray" , PALETTERGB (211,211,211)},
1264 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1265 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1266 {"navy" , PALETTERGB ( 0, 0,128)},
1267 {"navy blue" , PALETTERGB ( 0, 0,128)},
1268 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1269 {"cornflower blue" , PALETTERGB (100,149,237)},
1270 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1271 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1272 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1273 {"slate blue" , PALETTERGB (106, 90,205)},
1274 {"SlateBlue" , PALETTERGB (106, 90,205)},
1275 {"medium slate blue" , PALETTERGB (123,104,238)},
1276 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1277 {"light slate blue" , PALETTERGB (132,112,255)},
1278 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1279 {"medium blue" , PALETTERGB ( 0, 0,205)},
1280 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1281 {"royal blue" , PALETTERGB ( 65,105,225)},
1282 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1283 {"blue" , PALETTERGB ( 0, 0,255)},
1284 {"dodger blue" , PALETTERGB ( 30,144,255)},
1285 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1286 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1287 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1288 {"sky blue" , PALETTERGB (135,206,235)},
1289 {"SkyBlue" , PALETTERGB (135,206,235)},
1290 {"light sky blue" , PALETTERGB (135,206,250)},
1291 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1292 {"steel blue" , PALETTERGB ( 70,130,180)},
1293 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1294 {"light steel blue" , PALETTERGB (176,196,222)},
1295 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1296 {"light blue" , PALETTERGB (173,216,230)},
1297 {"LightBlue" , PALETTERGB (173,216,230)},
1298 {"powder blue" , PALETTERGB (176,224,230)},
1299 {"PowderBlue" , PALETTERGB (176,224,230)},
1300 {"pale turquoise" , PALETTERGB (175,238,238)},
1301 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1302 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1303 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1304 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1305 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1306 {"turquoise" , PALETTERGB ( 64,224,208)},
1307 {"cyan" , PALETTERGB ( 0,255,255)},
1308 {"light cyan" , PALETTERGB (224,255,255)},
1309 {"LightCyan" , PALETTERGB (224,255,255)},
1310 {"cadet blue" , PALETTERGB ( 95,158,160)},
1311 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1312 {"medium aquamarine" , PALETTERGB (102,205,170)},
1313 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1314 {"aquamarine" , PALETTERGB (127,255,212)},
1315 {"dark green" , PALETTERGB ( 0,100, 0)},
1316 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1317 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1318 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1319 {"dark sea green" , PALETTERGB (143,188,143)},
1320 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1321 {"sea green" , PALETTERGB ( 46,139, 87)},
1322 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1323 {"medium sea green" , PALETTERGB ( 60,179,113)},
1324 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1325 {"light sea green" , PALETTERGB ( 32,178,170)},
1326 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1327 {"pale green" , PALETTERGB (152,251,152)},
1328 {"PaleGreen" , PALETTERGB (152,251,152)},
1329 {"spring green" , PALETTERGB ( 0,255,127)},
1330 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1331 {"lawn green" , PALETTERGB (124,252, 0)},
1332 {"LawnGreen" , PALETTERGB (124,252, 0)},
1333 {"green" , PALETTERGB ( 0,255, 0)},
1334 {"chartreuse" , PALETTERGB (127,255, 0)},
1335 {"medium spring green" , PALETTERGB ( 0,250,154)},
1336 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1337 {"green yellow" , PALETTERGB (173,255, 47)},
1338 {"GreenYellow" , PALETTERGB (173,255, 47)},
1339 {"lime green" , PALETTERGB ( 50,205, 50)},
1340 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1341 {"yellow green" , PALETTERGB (154,205, 50)},
1342 {"YellowGreen" , PALETTERGB (154,205, 50)},
1343 {"forest green" , PALETTERGB ( 34,139, 34)},
1344 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1345 {"olive drab" , PALETTERGB (107,142, 35)},
1346 {"OliveDrab" , PALETTERGB (107,142, 35)},
1347 {"dark khaki" , PALETTERGB (189,183,107)},
1348 {"DarkKhaki" , PALETTERGB (189,183,107)},
1349 {"khaki" , PALETTERGB (240,230,140)},
1350 {"pale goldenrod" , PALETTERGB (238,232,170)},
1351 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1352 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1353 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1354 {"light yellow" , PALETTERGB (255,255,224)},
1355 {"LightYellow" , PALETTERGB (255,255,224)},
1356 {"yellow" , PALETTERGB (255,255, 0)},
1357 {"gold" , PALETTERGB (255,215, 0)},
1358 {"light goldenrod" , PALETTERGB (238,221,130)},
1359 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1360 {"goldenrod" , PALETTERGB (218,165, 32)},
1361 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1362 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1363 {"rosy brown" , PALETTERGB (188,143,143)},
1364 {"RosyBrown" , PALETTERGB (188,143,143)},
1365 {"indian red" , PALETTERGB (205, 92, 92)},
1366 {"IndianRed" , PALETTERGB (205, 92, 92)},
1367 {"saddle brown" , PALETTERGB (139, 69, 19)},
1368 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1369 {"sienna" , PALETTERGB (160, 82, 45)},
1370 {"peru" , PALETTERGB (205,133, 63)},
1371 {"burlywood" , PALETTERGB (222,184,135)},
1372 {"beige" , PALETTERGB (245,245,220)},
1373 {"wheat" , PALETTERGB (245,222,179)},
1374 {"sandy brown" , PALETTERGB (244,164, 96)},
1375 {"SandyBrown" , PALETTERGB (244,164, 96)},
1376 {"tan" , PALETTERGB (210,180,140)},
1377 {"chocolate" , PALETTERGB (210,105, 30)},
1378 {"firebrick" , PALETTERGB (178,34, 34)},
1379 {"brown" , PALETTERGB (165,42, 42)},
1380 {"dark salmon" , PALETTERGB (233,150,122)},
1381 {"DarkSalmon" , PALETTERGB (233,150,122)},
1382 {"salmon" , PALETTERGB (250,128,114)},
1383 {"light salmon" , PALETTERGB (255,160,122)},
1384 {"LightSalmon" , PALETTERGB (255,160,122)},
1385 {"orange" , PALETTERGB (255,165, 0)},
1386 {"dark orange" , PALETTERGB (255,140, 0)},
1387 {"DarkOrange" , PALETTERGB (255,140, 0)},
1388 {"coral" , PALETTERGB (255,127, 80)},
1389 {"light coral" , PALETTERGB (240,128,128)},
1390 {"LightCoral" , PALETTERGB (240,128,128)},
1391 {"tomato" , PALETTERGB (255, 99, 71)},
1392 {"orange red" , PALETTERGB (255, 69, 0)},
1393 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1394 {"red" , PALETTERGB (255, 0, 0)},
1395 {"hot pink" , PALETTERGB (255,105,180)},
1396 {"HotPink" , PALETTERGB (255,105,180)},
1397 {"deep pink" , PALETTERGB (255, 20,147)},
1398 {"DeepPink" , PALETTERGB (255, 20,147)},
1399 {"pink" , PALETTERGB (255,192,203)},
1400 {"light pink" , PALETTERGB (255,182,193)},
1401 {"LightPink" , PALETTERGB (255,182,193)},
1402 {"pale violet red" , PALETTERGB (219,112,147)},
1403 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1404 {"maroon" , PALETTERGB (176, 48, 96)},
1405 {"medium violet red" , PALETTERGB (199, 21,133)},
1406 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1407 {"violet red" , PALETTERGB (208, 32,144)},
1408 {"VioletRed" , PALETTERGB (208, 32,144)},
1409 {"magenta" , PALETTERGB (255, 0,255)},
1410 {"violet" , PALETTERGB (238,130,238)},
1411 {"plum" , PALETTERGB (221,160,221)},
1412 {"orchid" , PALETTERGB (218,112,214)},
1413 {"medium orchid" , PALETTERGB (186, 85,211)},
1414 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1415 {"dark orchid" , PALETTERGB (153, 50,204)},
1416 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1417 {"dark violet" , PALETTERGB (148, 0,211)},
1418 {"DarkViolet" , PALETTERGB (148, 0,211)},
1419 {"blue violet" , PALETTERGB (138, 43,226)},
1420 {"BlueViolet" , PALETTERGB (138, 43,226)},
1421 {"purple" , PALETTERGB (160, 32,240)},
1422 {"medium purple" , PALETTERGB (147,112,219)},
1423 {"MediumPurple" , PALETTERGB (147,112,219)},
1424 {"thistle" , PALETTERGB (216,191,216)},
1425 {"gray0" , PALETTERGB ( 0, 0, 0)},
1426 {"grey0" , PALETTERGB ( 0, 0, 0)},
1427 {"dark grey" , PALETTERGB (169,169,169)},
1428 {"DarkGrey" , PALETTERGB (169,169,169)},
1429 {"dark gray" , PALETTERGB (169,169,169)},
1430 {"DarkGray" , PALETTERGB (169,169,169)},
1431 {"dark blue" , PALETTERGB ( 0, 0,139)},
1432 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1433 {"dark cyan" , PALETTERGB ( 0,139,139)},
1434 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1435 {"dark magenta" , PALETTERGB (139, 0,139)},
1436 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1437 {"dark red" , PALETTERGB (139, 0, 0)},
1438 {"DarkRed" , PALETTERGB (139, 0, 0)},
1439 {"light green" , PALETTERGB (144,238,144)},
1440 {"LightGreen" , PALETTERGB (144,238,144)},
1441 };
1442
1443 DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
1444 0, 0, 0, doc: /* Return the default color map. */)
1445 ()
1446 {
1447 int i;
1448 colormap_t *pc = w32_color_map;
1449 Lisp_Object cmap;
1450
1451 BLOCK_INPUT;
1452
1453 cmap = Qnil;
1454
1455 for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
1456 pc++, i++)
1457 cmap = Fcons (Fcons (build_string (pc->name),
1458 make_number (pc->colorref)),
1459 cmap);
1460
1461 UNBLOCK_INPUT;
1462
1463 return (cmap);
1464 }
1465
1466 Lisp_Object
1467 w32_to_x_color (rgb)
1468 Lisp_Object rgb;
1469 {
1470 Lisp_Object color;
1471
1472 CHECK_NUMBER (rgb);
1473
1474 BLOCK_INPUT;
1475
1476 color = Frassq (rgb, Vw32_color_map);
1477
1478 UNBLOCK_INPUT;
1479
1480 if (!NILP (color))
1481 return (Fcar (color));
1482 else
1483 return Qnil;
1484 }
1485
1486 COLORREF
1487 w32_color_map_lookup (colorname)
1488 char *colorname;
1489 {
1490 Lisp_Object tail, ret = Qnil;
1491
1492 BLOCK_INPUT;
1493
1494 for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail))
1495 {
1496 register Lisp_Object elt, tem;
1497
1498 elt = Fcar (tail);
1499 if (!CONSP (elt)) continue;
1500
1501 tem = Fcar (elt);
1502
1503 if (lstrcmpi (XSTRING (tem)->data, colorname) == 0)
1504 {
1505 ret = XUINT (Fcdr (elt));
1506 break;
1507 }
1508
1509 QUIT;
1510 }
1511
1512
1513 UNBLOCK_INPUT;
1514
1515 return ret;
1516 }
1517
1518 COLORREF
1519 x_to_w32_color (colorname)
1520 char * colorname;
1521 {
1522 register Lisp_Object ret = Qnil;
1523
1524 BLOCK_INPUT;
1525
1526 if (colorname[0] == '#')
1527 {
1528 /* Could be an old-style RGB Device specification. */
1529 char *color;
1530 int size;
1531 color = colorname + 1;
1532
1533 size = strlen(color);
1534 if (size == 3 || size == 6 || size == 9 || size == 12)
1535 {
1536 UINT colorval;
1537 int i, pos;
1538 pos = 0;
1539 size /= 3;
1540 colorval = 0;
1541
1542 for (i = 0; i < 3; i++)
1543 {
1544 char *end;
1545 char t;
1546 unsigned long value;
1547
1548 /* The check for 'x' in the following conditional takes into
1549 account the fact that strtol allows a "0x" in front of
1550 our numbers, and we don't. */
1551 if (!isxdigit(color[0]) || color[1] == 'x')
1552 break;
1553 t = color[size];
1554 color[size] = '\0';
1555 value = strtoul(color, &end, 16);
1556 color[size] = t;
1557 if (errno == ERANGE || end - color != size)
1558 break;
1559 switch (size)
1560 {
1561 case 1:
1562 value = value * 0x10;
1563 break;
1564 case 2:
1565 break;
1566 case 3:
1567 value /= 0x10;
1568 break;
1569 case 4:
1570 value /= 0x100;
1571 break;
1572 }
1573 colorval |= (value << pos);
1574 pos += 0x8;
1575 if (i == 2)
1576 {
1577 UNBLOCK_INPUT;
1578 return (colorval);
1579 }
1580 color = end;
1581 }
1582 }
1583 }
1584 else if (strnicmp(colorname, "rgb:", 4) == 0)
1585 {
1586 char *color;
1587 UINT colorval;
1588 int i, pos;
1589 pos = 0;
1590
1591 colorval = 0;
1592 color = colorname + 4;
1593 for (i = 0; i < 3; i++)
1594 {
1595 char *end;
1596 unsigned long value;
1597
1598 /* The check for 'x' in the following conditional takes into
1599 account the fact that strtol allows a "0x" in front of
1600 our numbers, and we don't. */
1601 if (!isxdigit(color[0]) || color[1] == 'x')
1602 break;
1603 value = strtoul(color, &end, 16);
1604 if (errno == ERANGE)
1605 break;
1606 switch (end - color)
1607 {
1608 case 1:
1609 value = value * 0x10 + value;
1610 break;
1611 case 2:
1612 break;
1613 case 3:
1614 value /= 0x10;
1615 break;
1616 case 4:
1617 value /= 0x100;
1618 break;
1619 default:
1620 value = ULONG_MAX;
1621 }
1622 if (value == ULONG_MAX)
1623 break;
1624 colorval |= (value << pos);
1625 pos += 0x8;
1626 if (i == 2)
1627 {
1628 if (*end != '\0')
1629 break;
1630 UNBLOCK_INPUT;
1631 return (colorval);
1632 }
1633 if (*end != '/')
1634 break;
1635 color = end + 1;
1636 }
1637 }
1638 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1639 {
1640 /* This is an RGB Intensity specification. */
1641 char *color;
1642 UINT colorval;
1643 int i, pos;
1644 pos = 0;
1645
1646 colorval = 0;
1647 color = colorname + 5;
1648 for (i = 0; i < 3; i++)
1649 {
1650 char *end;
1651 double value;
1652 UINT val;
1653
1654 value = strtod(color, &end);
1655 if (errno == ERANGE)
1656 break;
1657 if (value < 0.0 || value > 1.0)
1658 break;
1659 val = (UINT)(0x100 * value);
1660 /* We used 0x100 instead of 0xFF to give an continuous
1661 range between 0.0 and 1.0 inclusive. The next statement
1662 fixes the 1.0 case. */
1663 if (val == 0x100)
1664 val = 0xFF;
1665 colorval |= (val << pos);
1666 pos += 0x8;
1667 if (i == 2)
1668 {
1669 if (*end != '\0')
1670 break;
1671 UNBLOCK_INPUT;
1672 return (colorval);
1673 }
1674 if (*end != '/')
1675 break;
1676 color = end + 1;
1677 }
1678 }
1679 /* I am not going to attempt to handle any of the CIE color schemes
1680 or TekHVC, since I don't know the algorithms for conversion to
1681 RGB. */
1682
1683 /* If we fail to lookup the color name in w32_color_map, then check the
1684 colorname to see if it can be crudely approximated: If the X color
1685 ends in a number (e.g., "darkseagreen2"), strip the number and
1686 return the result of looking up the base color name. */
1687 ret = w32_color_map_lookup (colorname);
1688 if (NILP (ret))
1689 {
1690 int len = strlen (colorname);
1691
1692 if (isdigit (colorname[len - 1]))
1693 {
1694 char *ptr, *approx = alloca (len + 1);
1695
1696 strcpy (approx, colorname);
1697 ptr = &approx[len - 1];
1698 while (ptr > approx && isdigit (*ptr))
1699 *ptr-- = '\0';
1700
1701 ret = w32_color_map_lookup (approx);
1702 }
1703 }
1704
1705 UNBLOCK_INPUT;
1706 return ret;
1707 }
1708
1709
1710 void
1711 w32_regenerate_palette (FRAME_PTR f)
1712 {
1713 struct w32_palette_entry * list;
1714 LOGPALETTE * log_palette;
1715 HPALETTE new_palette;
1716 int i;
1717
1718 /* don't bother trying to create palette if not supported */
1719 if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
1720 return;
1721
1722 log_palette = (LOGPALETTE *)
1723 alloca (sizeof (LOGPALETTE) +
1724 FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
1725 log_palette->palVersion = 0x300;
1726 log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
1727
1728 list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1729 for (i = 0;
1730 i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
1731 i++, list = list->next)
1732 log_palette->palPalEntry[i] = list->entry;
1733
1734 new_palette = CreatePalette (log_palette);
1735
1736 enter_crit ();
1737
1738 if (FRAME_W32_DISPLAY_INFO (f)->palette)
1739 DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
1740 FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
1741
1742 /* Realize display palette and garbage all frames. */
1743 release_frame_dc (f, get_frame_dc (f));
1744
1745 leave_crit ();
1746 }
1747
1748 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1749 #define SET_W32_COLOR(pe, color) \
1750 do \
1751 { \
1752 pe.peRed = GetRValue (color); \
1753 pe.peGreen = GetGValue (color); \
1754 pe.peBlue = GetBValue (color); \
1755 pe.peFlags = 0; \
1756 } while (0)
1757
1758 #if 0
1759 /* Keep these around in case we ever want to track color usage. */
1760 void
1761 w32_map_color (FRAME_PTR f, COLORREF color)
1762 {
1763 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1764
1765 if (NILP (Vw32_enable_palette))
1766 return;
1767
1768 /* check if color is already mapped */
1769 while (list)
1770 {
1771 if (W32_COLOR (list->entry) == color)
1772 {
1773 ++list->refcount;
1774 return;
1775 }
1776 list = list->next;
1777 }
1778
1779 /* not already mapped, so add to list and recreate Windows palette */
1780 list = (struct w32_palette_entry *)
1781 xmalloc (sizeof (struct w32_palette_entry));
1782 SET_W32_COLOR (list->entry, color);
1783 list->refcount = 1;
1784 list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
1785 FRAME_W32_DISPLAY_INFO (f)->color_list = list;
1786 FRAME_W32_DISPLAY_INFO (f)->num_colors++;
1787
1788 /* set flag that palette must be regenerated */
1789 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1790 }
1791
1792 void
1793 w32_unmap_color (FRAME_PTR f, COLORREF color)
1794 {
1795 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1796 struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
1797
1798 if (NILP (Vw32_enable_palette))
1799 return;
1800
1801 /* check if color is already mapped */
1802 while (list)
1803 {
1804 if (W32_COLOR (list->entry) == color)
1805 {
1806 if (--list->refcount == 0)
1807 {
1808 *prev = list->next;
1809 xfree (list);
1810 FRAME_W32_DISPLAY_INFO (f)->num_colors--;
1811 break;
1812 }
1813 else
1814 return;
1815 }
1816 prev = &list->next;
1817 list = list->next;
1818 }
1819
1820 /* set flag that palette must be regenerated */
1821 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1822 }
1823 #endif
1824
1825
1826 /* Gamma-correct COLOR on frame F. */
1827
1828 void
1829 gamma_correct (f, color)
1830 struct frame *f;
1831 COLORREF *color;
1832 {
1833 if (f->gamma)
1834 {
1835 *color = PALETTERGB (
1836 pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1837 pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1838 pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5);
1839 }
1840 }
1841
1842
1843 /* Decide if color named COLOR is valid for the display associated with
1844 the selected frame; if so, return the rgb values in COLOR_DEF.
1845 If ALLOC is nonzero, allocate a new colormap cell. */
1846
1847 int
1848 w32_defined_color (f, color, color_def, alloc)
1849 FRAME_PTR f;
1850 char *color;
1851 XColor *color_def;
1852 int alloc;
1853 {
1854 register Lisp_Object tem;
1855 COLORREF w32_color_ref;
1856
1857 tem = x_to_w32_color (color);
1858
1859 if (!NILP (tem))
1860 {
1861 if (f)
1862 {
1863 /* Apply gamma correction. */
1864 w32_color_ref = XUINT (tem);
1865 gamma_correct (f, &w32_color_ref);
1866 XSETINT (tem, w32_color_ref);
1867 }
1868
1869 /* Map this color to the palette if it is enabled. */
1870 if (!NILP (Vw32_enable_palette))
1871 {
1872 struct w32_palette_entry * entry =
1873 one_w32_display_info.color_list;
1874 struct w32_palette_entry ** prev =
1875 &one_w32_display_info.color_list;
1876
1877 /* check if color is already mapped */
1878 while (entry)
1879 {
1880 if (W32_COLOR (entry->entry) == XUINT (tem))
1881 break;
1882 prev = &entry->next;
1883 entry = entry->next;
1884 }
1885
1886 if (entry == NULL && alloc)
1887 {
1888 /* not already mapped, so add to list */
1889 entry = (struct w32_palette_entry *)
1890 xmalloc (sizeof (struct w32_palette_entry));
1891 SET_W32_COLOR (entry->entry, XUINT (tem));
1892 entry->next = NULL;
1893 *prev = entry;
1894 one_w32_display_info.num_colors++;
1895
1896 /* set flag that palette must be regenerated */
1897 one_w32_display_info.regen_palette = TRUE;
1898 }
1899 }
1900 /* Ensure COLORREF value is snapped to nearest color in (default)
1901 palette by simulating the PALETTERGB macro. This works whether
1902 or not the display device has a palette. */
1903 w32_color_ref = XUINT (tem) | 0x2000000;
1904
1905 color_def->pixel = w32_color_ref;
1906 color_def->red = GetRValue (w32_color_ref);
1907 color_def->green = GetGValue (w32_color_ref);
1908 color_def->blue = GetBValue (w32_color_ref);
1909
1910 return 1;
1911 }
1912 else
1913 {
1914 return 0;
1915 }
1916 }
1917
1918 /* Given a string ARG naming a color, compute a pixel value from it
1919 suitable for screen F.
1920 If F is not a color screen, return DEF (default) regardless of what
1921 ARG says. */
1922
1923 int
1924 x_decode_color (f, arg, def)
1925 FRAME_PTR f;
1926 Lisp_Object arg;
1927 int def;
1928 {
1929 XColor cdef;
1930
1931 CHECK_STRING (arg);
1932
1933 if (strcmp (XSTRING (arg)->data, "black") == 0)
1934 return BLACK_PIX_DEFAULT (f);
1935 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1936 return WHITE_PIX_DEFAULT (f);
1937
1938 if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
1939 return def;
1940
1941 /* w32_defined_color is responsible for coping with failures
1942 by looking for a near-miss. */
1943 if (w32_defined_color (f, XSTRING (arg)->data, &cdef, 1))
1944 return cdef.pixel;
1945
1946 /* defined_color failed; return an ultimate default. */
1947 return def;
1948 }
1949 \f
1950 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1951 the previous value of that parameter, NEW_VALUE is the new value. */
1952
1953 static void
1954 x_set_line_spacing (f, new_value, old_value)
1955 struct frame *f;
1956 Lisp_Object new_value, old_value;
1957 {
1958 if (NILP (new_value))
1959 f->extra_line_spacing = 0;
1960 else if (NATNUMP (new_value))
1961 f->extra_line_spacing = XFASTINT (new_value);
1962 else
1963 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1964 Fcons (new_value, Qnil)));
1965 if (FRAME_VISIBLE_P (f))
1966 redraw_frame (f);
1967 }
1968
1969
1970 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1971 the previous value of that parameter, NEW_VALUE is the new value. */
1972
1973 static void
1974 x_set_screen_gamma (f, new_value, old_value)
1975 struct frame *f;
1976 Lisp_Object new_value, old_value;
1977 {
1978 if (NILP (new_value))
1979 f->gamma = 0;
1980 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1981 /* The value 0.4545 is the normal viewing gamma. */
1982 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1983 else
1984 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1985 Fcons (new_value, Qnil)));
1986
1987 clear_face_cache (0);
1988 }
1989
1990
1991 /* Functions called only from `x_set_frame_param'
1992 to set individual parameters.
1993
1994 If FRAME_W32_WINDOW (f) is 0,
1995 the frame is being created and its window does not exist yet.
1996 In that case, just record the parameter's new value
1997 in the standard place; do not attempt to change the window. */
1998
1999 void
2000 x_set_foreground_color (f, arg, oldval)
2001 struct frame *f;
2002 Lisp_Object arg, oldval;
2003 {
2004 struct w32_output *x = f->output_data.w32;
2005 PIX_TYPE fg, old_fg;
2006
2007 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2008 old_fg = FRAME_FOREGROUND_PIXEL (f);
2009 FRAME_FOREGROUND_PIXEL (f) = fg;
2010
2011 if (FRAME_W32_WINDOW (f) != 0)
2012 {
2013 if (x->cursor_pixel == old_fg)
2014 x->cursor_pixel = fg;
2015
2016 update_face_from_frame_parameter (f, Qforeground_color, arg);
2017 if (FRAME_VISIBLE_P (f))
2018 redraw_frame (f);
2019 }
2020 }
2021
2022 void
2023 x_set_background_color (f, arg, oldval)
2024 struct frame *f;
2025 Lisp_Object arg, oldval;
2026 {
2027 FRAME_BACKGROUND_PIXEL (f)
2028 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
2029
2030 if (FRAME_W32_WINDOW (f) != 0)
2031 {
2032 SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX,
2033 FRAME_BACKGROUND_PIXEL (f));
2034
2035 update_face_from_frame_parameter (f, Qbackground_color, arg);
2036
2037 if (FRAME_VISIBLE_P (f))
2038 redraw_frame (f);
2039 }
2040 }
2041
2042 void
2043 x_set_mouse_color (f, arg, oldval)
2044 struct frame *f;
2045 Lisp_Object arg, oldval;
2046 {
2047 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
2048 int count;
2049 int mask_color;
2050
2051 if (!EQ (Qnil, arg))
2052 f->output_data.w32->mouse_pixel
2053 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2054 mask_color = FRAME_BACKGROUND_PIXEL (f);
2055
2056 /* Don't let pointers be invisible. */
2057 if (mask_color == f->output_data.w32->mouse_pixel
2058 && mask_color == FRAME_BACKGROUND_PIXEL (f))
2059 f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
2060
2061 #if 0 /* TODO : cursor changes */
2062 BLOCK_INPUT;
2063
2064 /* It's not okay to crash if the user selects a screwy cursor. */
2065 count = x_catch_errors (FRAME_W32_DISPLAY (f));
2066
2067 if (!EQ (Qnil, Vx_pointer_shape))
2068 {
2069 CHECK_NUMBER (Vx_pointer_shape);
2070 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
2071 }
2072 else
2073 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2074 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
2075
2076 if (!EQ (Qnil, Vx_nontext_pointer_shape))
2077 {
2078 CHECK_NUMBER (Vx_nontext_pointer_shape);
2079 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2080 XINT (Vx_nontext_pointer_shape));
2081 }
2082 else
2083 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
2084 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2085
2086 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
2087 {
2088 CHECK_NUMBER (Vx_hourglass_pointer_shape);
2089 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2090 XINT (Vx_hourglass_pointer_shape));
2091 }
2092 else
2093 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
2094 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
2095
2096 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2097 if (!EQ (Qnil, Vx_mode_pointer_shape))
2098 {
2099 CHECK_NUMBER (Vx_mode_pointer_shape);
2100 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2101 XINT (Vx_mode_pointer_shape));
2102 }
2103 else
2104 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2105 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
2106
2107 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
2108 {
2109 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
2110 cross_cursor
2111 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2112 XINT (Vx_sensitive_text_pointer_shape));
2113 }
2114 else
2115 cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
2116
2117 if (!NILP (Vx_window_horizontal_drag_shape))
2118 {
2119 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
2120 horizontal_drag_cursor
2121 = XCreateFontCursor (FRAME_X_DISPLAY (f),
2122 XINT (Vx_window_horizontal_drag_shape));
2123 }
2124 else
2125 horizontal_drag_cursor
2126 = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
2127
2128 /* Check and report errors with the above calls. */
2129 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
2130 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
2131
2132 {
2133 XColor fore_color, back_color;
2134
2135 fore_color.pixel = f->output_data.w32->mouse_pixel;
2136 back_color.pixel = mask_color;
2137 XQueryColor (FRAME_W32_DISPLAY (f),
2138 DefaultColormap (FRAME_W32_DISPLAY (f),
2139 DefaultScreen (FRAME_W32_DISPLAY (f))),
2140 &fore_color);
2141 XQueryColor (FRAME_W32_DISPLAY (f),
2142 DefaultColormap (FRAME_W32_DISPLAY (f),
2143 DefaultScreen (FRAME_W32_DISPLAY (f))),
2144 &back_color);
2145 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
2146 &fore_color, &back_color);
2147 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
2148 &fore_color, &back_color);
2149 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
2150 &fore_color, &back_color);
2151 XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
2152 &fore_color, &back_color);
2153 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
2154 &fore_color, &back_color);
2155 }
2156
2157 if (FRAME_W32_WINDOW (f) != 0)
2158 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
2159
2160 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
2161 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
2162 f->output_data.w32->text_cursor = cursor;
2163
2164 if (nontext_cursor != f->output_data.w32->nontext_cursor
2165 && f->output_data.w32->nontext_cursor != 0)
2166 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
2167 f->output_data.w32->nontext_cursor = nontext_cursor;
2168
2169 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
2170 && f->output_data.w32->hourglass_cursor != 0)
2171 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
2172 f->output_data.w32->hourglass_cursor = hourglass_cursor;
2173
2174 if (mode_cursor != f->output_data.w32->modeline_cursor
2175 && f->output_data.w32->modeline_cursor != 0)
2176 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
2177 f->output_data.w32->modeline_cursor = mode_cursor;
2178
2179 if (cross_cursor != f->output_data.w32->cross_cursor
2180 && f->output_data.w32->cross_cursor != 0)
2181 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
2182 f->output_data.w32->cross_cursor = cross_cursor;
2183
2184 XFlush (FRAME_W32_DISPLAY (f));
2185 UNBLOCK_INPUT;
2186
2187 update_face_from_frame_parameter (f, Qmouse_color, arg);
2188 #endif /* TODO */
2189 }
2190
2191 /* Defined in w32term.c. */
2192 void x_update_cursor (struct frame *f, int on_p);
2193
2194 void
2195 x_set_cursor_color (f, arg, oldval)
2196 struct frame *f;
2197 Lisp_Object arg, oldval;
2198 {
2199 unsigned long fore_pixel, pixel;
2200
2201 if (!NILP (Vx_cursor_fore_pixel))
2202 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
2203 WHITE_PIX_DEFAULT (f));
2204 else
2205 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2206
2207 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2208
2209 /* Make sure that the cursor color differs from the background color. */
2210 if (pixel == FRAME_BACKGROUND_PIXEL (f))
2211 {
2212 pixel = f->output_data.w32->mouse_pixel;
2213 if (pixel == fore_pixel)
2214 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2215 }
2216
2217 FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
2218 f->output_data.w32->cursor_pixel = pixel;
2219
2220 if (FRAME_W32_WINDOW (f) != 0)
2221 {
2222 if (FRAME_VISIBLE_P (f))
2223 {
2224 x_update_cursor (f, 0);
2225 x_update_cursor (f, 1);
2226 }
2227 }
2228
2229 update_face_from_frame_parameter (f, Qcursor_color, arg);
2230 }
2231
2232 /* Set the border-color of frame F to pixel value PIX.
2233 Note that this does not fully take effect if done before
2234 F has an window. */
2235 void
2236 x_set_border_pixel (f, pix)
2237 struct frame *f;
2238 int pix;
2239 {
2240 f->output_data.w32->border_pixel = pix;
2241
2242 if (FRAME_W32_WINDOW (f) != 0 && f->output_data.w32->border_width > 0)
2243 {
2244 if (FRAME_VISIBLE_P (f))
2245 redraw_frame (f);
2246 }
2247 }
2248
2249 /* Set the border-color of frame F to value described by ARG.
2250 ARG can be a string naming a color.
2251 The border-color is used for the border that is drawn by the server.
2252 Note that this does not fully take effect if done before
2253 F has a window; it must be redone when the window is created. */
2254
2255 void
2256 x_set_border_color (f, arg, oldval)
2257 struct frame *f;
2258 Lisp_Object arg, oldval;
2259 {
2260 int pix;
2261
2262 CHECK_STRING (arg);
2263 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2264 x_set_border_pixel (f, pix);
2265 update_face_from_frame_parameter (f, Qborder_color, arg);
2266 }
2267
2268 /* Value is the internal representation of the specified cursor type
2269 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
2270 of the bar cursor. */
2271
2272 enum text_cursor_kinds
2273 x_specified_cursor_type (arg, width)
2274 Lisp_Object arg;
2275 int *width;
2276 {
2277 enum text_cursor_kinds type;
2278
2279 if (EQ (arg, Qbar))
2280 {
2281 type = BAR_CURSOR;
2282 *width = 2;
2283 }
2284 else if (CONSP (arg)
2285 && EQ (XCAR (arg), Qbar)
2286 && INTEGERP (XCDR (arg))
2287 && XINT (XCDR (arg)) >= 0)
2288 {
2289 type = BAR_CURSOR;
2290 *width = XINT (XCDR (arg));
2291 }
2292 else if (NILP (arg))
2293 type = NO_CURSOR;
2294 else
2295 /* Treat anything unknown as "box cursor".
2296 It was bad to signal an error; people have trouble fixing
2297 .Xdefaults with Emacs, when it has something bad in it. */
2298 type = FILLED_BOX_CURSOR;
2299
2300 return type;
2301 }
2302
2303 void
2304 x_set_cursor_type (f, arg, oldval)
2305 FRAME_PTR f;
2306 Lisp_Object arg, oldval;
2307 {
2308 int width;
2309
2310 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
2311 f->output_data.w32->cursor_width = width;
2312
2313 /* Make sure the cursor gets redrawn. This is overkill, but how
2314 often do people change cursor types? */
2315 update_mode_lines++;
2316 }
2317 \f
2318 void
2319 x_set_icon_type (f, arg, oldval)
2320 struct frame *f;
2321 Lisp_Object arg, oldval;
2322 {
2323 int result;
2324
2325 if (NILP (arg) && NILP (oldval))
2326 return;
2327
2328 if (STRINGP (arg) && STRINGP (oldval)
2329 && EQ (Fstring_equal (oldval, arg), Qt))
2330 return;
2331
2332 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
2333 return;
2334
2335 BLOCK_INPUT;
2336
2337 result = x_bitmap_icon (f, arg);
2338 if (result)
2339 {
2340 UNBLOCK_INPUT;
2341 error ("No icon window available");
2342 }
2343
2344 UNBLOCK_INPUT;
2345 }
2346
2347 /* Return non-nil if frame F wants a bitmap icon. */
2348
2349 Lisp_Object
2350 x_icon_type (f)
2351 FRAME_PTR f;
2352 {
2353 Lisp_Object tem;
2354
2355 tem = assq_no_quit (Qicon_type, f->param_alist);
2356 if (CONSP (tem))
2357 return XCDR (tem);
2358 else
2359 return Qnil;
2360 }
2361
2362 void
2363 x_set_icon_name (f, arg, oldval)
2364 struct frame *f;
2365 Lisp_Object arg, oldval;
2366 {
2367 if (STRINGP (arg))
2368 {
2369 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
2370 return;
2371 }
2372 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
2373 return;
2374
2375 f->icon_name = arg;
2376
2377 #if 0
2378 if (f->output_data.w32->icon_bitmap != 0)
2379 return;
2380
2381 BLOCK_INPUT;
2382
2383 result = x_text_icon (f,
2384 (char *) XSTRING ((!NILP (f->icon_name)
2385 ? f->icon_name
2386 : !NILP (f->title)
2387 ? f->title
2388 : f->name))->data);
2389
2390 if (result)
2391 {
2392 UNBLOCK_INPUT;
2393 error ("No icon window available");
2394 }
2395
2396 /* If the window was unmapped (and its icon was mapped),
2397 the new icon is not mapped, so map the window in its stead. */
2398 if (FRAME_VISIBLE_P (f))
2399 {
2400 #ifdef USE_X_TOOLKIT
2401 XtPopup (f->output_data.w32->widget, XtGrabNone);
2402 #endif
2403 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
2404 }
2405
2406 XFlush (FRAME_W32_DISPLAY (f));
2407 UNBLOCK_INPUT;
2408 #endif
2409 }
2410
2411 extern Lisp_Object x_new_font ();
2412 extern Lisp_Object x_new_fontset();
2413
2414 void
2415 x_set_font (f, arg, oldval)
2416 struct frame *f;
2417 Lisp_Object arg, oldval;
2418 {
2419 Lisp_Object result;
2420 Lisp_Object fontset_name;
2421 Lisp_Object frame;
2422 int old_fontset = FRAME_FONTSET(f);
2423
2424 CHECK_STRING (arg);
2425
2426 fontset_name = Fquery_fontset (arg, Qnil);
2427
2428 BLOCK_INPUT;
2429 result = (STRINGP (fontset_name)
2430 ? x_new_fontset (f, XSTRING (fontset_name)->data)
2431 : x_new_font (f, XSTRING (arg)->data));
2432 UNBLOCK_INPUT;
2433
2434 if (EQ (result, Qnil))
2435 error ("Font `%s' is not defined", XSTRING (arg)->data);
2436 else if (EQ (result, Qt))
2437 error ("The characters of the given font have varying widths");
2438 else if (STRINGP (result))
2439 {
2440 if (STRINGP (fontset_name))
2441 {
2442 /* Fontset names are built from ASCII font names, so the
2443 names may be equal despite there was a change. */
2444 if (old_fontset == FRAME_FONTSET (f))
2445 return;
2446 }
2447 else if (!NILP (Fequal (result, oldval)))
2448 return;
2449
2450 store_frame_param (f, Qfont, result);
2451 recompute_basic_faces (f);
2452 }
2453 else
2454 abort ();
2455
2456 do_pending_window_change (0);
2457
2458 /* Don't call `face-set-after-frame-default' when faces haven't been
2459 initialized yet. This is the case when called from
2460 Fx_create_frame. In that case, the X widget or window doesn't
2461 exist either, and we can end up in x_report_frame_params with a
2462 null widget which gives a segfault. */
2463 if (FRAME_FACE_CACHE (f))
2464 {
2465 XSETFRAME (frame, f);
2466 call1 (Qface_set_after_frame_default, frame);
2467 }
2468 }
2469
2470 static void
2471 x_set_fringe_width (f, new_value, old_value)
2472 struct frame *f;
2473 Lisp_Object new_value, old_value;
2474 {
2475 x_compute_fringe_widths (f, 1);
2476 }
2477
2478 void
2479 x_set_border_width (f, arg, oldval)
2480 struct frame *f;
2481 Lisp_Object arg, oldval;
2482 {
2483 CHECK_NUMBER (arg);
2484
2485 if (XINT (arg) == f->output_data.w32->border_width)
2486 return;
2487
2488 if (FRAME_W32_WINDOW (f) != 0)
2489 error ("Cannot change the border width of a window");
2490
2491 f->output_data.w32->border_width = XINT (arg);
2492 }
2493
2494 void
2495 x_set_internal_border_width (f, arg, oldval)
2496 struct frame *f;
2497 Lisp_Object arg, oldval;
2498 {
2499 int old = f->output_data.w32->internal_border_width;
2500
2501 CHECK_NUMBER (arg);
2502 f->output_data.w32->internal_border_width = XINT (arg);
2503 if (f->output_data.w32->internal_border_width < 0)
2504 f->output_data.w32->internal_border_width = 0;
2505
2506 if (f->output_data.w32->internal_border_width == old)
2507 return;
2508
2509 if (FRAME_W32_WINDOW (f) != 0)
2510 {
2511 x_set_window_size (f, 0, f->width, f->height);
2512 SET_FRAME_GARBAGED (f);
2513 do_pending_window_change (0);
2514 }
2515 else
2516 SET_FRAME_GARBAGED (f);
2517 }
2518
2519 void
2520 x_set_visibility (f, value, oldval)
2521 struct frame *f;
2522 Lisp_Object value, oldval;
2523 {
2524 Lisp_Object frame;
2525 XSETFRAME (frame, f);
2526
2527 if (NILP (value))
2528 Fmake_frame_invisible (frame, Qt);
2529 else if (EQ (value, Qicon))
2530 Ficonify_frame (frame);
2531 else
2532 Fmake_frame_visible (frame);
2533 }
2534
2535 \f
2536 /* Change window heights in windows rooted in WINDOW by N lines. */
2537
2538 static void
2539 x_change_window_heights (window, n)
2540 Lisp_Object window;
2541 int n;
2542 {
2543 struct window *w = XWINDOW (window);
2544
2545 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2546 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2547
2548 if (INTEGERP (w->orig_top))
2549 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2550 if (INTEGERP (w->orig_height))
2551 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2552
2553 /* Handle just the top child in a vertical split. */
2554 if (!NILP (w->vchild))
2555 x_change_window_heights (w->vchild, n);
2556
2557 /* Adjust all children in a horizontal split. */
2558 for (window = w->hchild; !NILP (window); window = w->next)
2559 {
2560 w = XWINDOW (window);
2561 x_change_window_heights (window, n);
2562 }
2563 }
2564
2565 void
2566 x_set_menu_bar_lines (f, value, oldval)
2567 struct frame *f;
2568 Lisp_Object value, oldval;
2569 {
2570 int nlines;
2571 int olines = FRAME_MENU_BAR_LINES (f);
2572
2573 /* Right now, menu bars don't work properly in minibuf-only frames;
2574 most of the commands try to apply themselves to the minibuffer
2575 frame itself, and get an error because you can't switch buffers
2576 in or split the minibuffer window. */
2577 if (FRAME_MINIBUF_ONLY_P (f))
2578 return;
2579
2580 if (INTEGERP (value))
2581 nlines = XINT (value);
2582 else
2583 nlines = 0;
2584
2585 FRAME_MENU_BAR_LINES (f) = 0;
2586 if (nlines)
2587 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2588 else
2589 {
2590 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2591 free_frame_menubar (f);
2592 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2593
2594 /* Adjust the frame size so that the client (text) dimensions
2595 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2596 set correctly. */
2597 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2598 do_pending_window_change (0);
2599 }
2600 adjust_glyphs (f);
2601 }
2602
2603
2604 /* Set the number of lines used for the tool bar of frame F to VALUE.
2605 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2606 is the old number of tool bar lines. This function changes the
2607 height of all windows on frame F to match the new tool bar height.
2608 The frame's height doesn't change. */
2609
2610 void
2611 x_set_tool_bar_lines (f, value, oldval)
2612 struct frame *f;
2613 Lisp_Object value, oldval;
2614 {
2615 int delta, nlines, root_height;
2616 Lisp_Object root_window;
2617
2618 /* Treat tool bars like menu bars. */
2619 if (FRAME_MINIBUF_ONLY_P (f))
2620 return;
2621
2622 /* Use VALUE only if an integer >= 0. */
2623 if (INTEGERP (value) && XINT (value) >= 0)
2624 nlines = XFASTINT (value);
2625 else
2626 nlines = 0;
2627
2628 /* Make sure we redisplay all windows in this frame. */
2629 ++windows_or_buffers_changed;
2630
2631 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2632
2633 /* Don't resize the tool-bar to more than we have room for. */
2634 root_window = FRAME_ROOT_WINDOW (f);
2635 root_height = XINT (XWINDOW (root_window)->height);
2636 if (root_height - delta < 1)
2637 {
2638 delta = root_height - 1;
2639 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2640 }
2641
2642 FRAME_TOOL_BAR_LINES (f) = nlines;
2643 x_change_window_heights (root_window, delta);
2644 adjust_glyphs (f);
2645
2646 /* We also have to make sure that the internal border at the top of
2647 the frame, below the menu bar or tool bar, is redrawn when the
2648 tool bar disappears. This is so because the internal border is
2649 below the tool bar if one is displayed, but is below the menu bar
2650 if there isn't a tool bar. The tool bar draws into the area
2651 below the menu bar. */
2652 if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2653 {
2654 updating_frame = f;
2655 clear_frame ();
2656 clear_current_matrices (f);
2657 updating_frame = NULL;
2658 }
2659
2660 /* If the tool bar gets smaller, the internal border below it
2661 has to be cleared. It was formerly part of the display
2662 of the larger tool bar, and updating windows won't clear it. */
2663 if (delta < 0)
2664 {
2665 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2666 int width = PIXEL_WIDTH (f);
2667 int y = nlines * CANON_Y_UNIT (f);
2668
2669 BLOCK_INPUT;
2670 {
2671 HDC hdc = get_frame_dc (f);
2672 w32_clear_area (f, hdc, 0, y, width, height);
2673 release_frame_dc (f, hdc);
2674 }
2675 UNBLOCK_INPUT;
2676
2677 if (WINDOWP (f->tool_bar_window))
2678 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2679 }
2680 }
2681
2682
2683 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2684 w32_id_name.
2685
2686 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2687 name; if NAME is a string, set F's name to NAME and set
2688 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2689
2690 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2691 suggesting a new name, which lisp code should override; if
2692 F->explicit_name is set, ignore the new name; otherwise, set it. */
2693
2694 void
2695 x_set_name (f, name, explicit)
2696 struct frame *f;
2697 Lisp_Object name;
2698 int explicit;
2699 {
2700 /* Make sure that requests from lisp code override requests from
2701 Emacs redisplay code. */
2702 if (explicit)
2703 {
2704 /* If we're switching from explicit to implicit, we had better
2705 update the mode lines and thereby update the title. */
2706 if (f->explicit_name && NILP (name))
2707 update_mode_lines = 1;
2708
2709 f->explicit_name = ! NILP (name);
2710 }
2711 else if (f->explicit_name)
2712 return;
2713
2714 /* If NAME is nil, set the name to the w32_id_name. */
2715 if (NILP (name))
2716 {
2717 /* Check for no change needed in this very common case
2718 before we do any consing. */
2719 if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
2720 XSTRING (f->name)->data))
2721 return;
2722 name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
2723 }
2724 else
2725 CHECK_STRING (name);
2726
2727 /* Don't change the name if it's already NAME. */
2728 if (! NILP (Fstring_equal (name, f->name)))
2729 return;
2730
2731 f->name = name;
2732
2733 /* For setting the frame title, the title parameter should override
2734 the name parameter. */
2735 if (! NILP (f->title))
2736 name = f->title;
2737
2738 if (FRAME_W32_WINDOW (f))
2739 {
2740 if (STRING_MULTIBYTE (name))
2741 name = ENCODE_SYSTEM (name);
2742
2743 BLOCK_INPUT;
2744 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
2745 UNBLOCK_INPUT;
2746 }
2747 }
2748
2749 /* This function should be called when the user's lisp code has
2750 specified a name for the frame; the name will override any set by the
2751 redisplay code. */
2752 void
2753 x_explicitly_set_name (f, arg, oldval)
2754 FRAME_PTR f;
2755 Lisp_Object arg, oldval;
2756 {
2757 x_set_name (f, arg, 1);
2758 }
2759
2760 /* This function should be called by Emacs redisplay code to set the
2761 name; names set this way will never override names set by the user's
2762 lisp code. */
2763 void
2764 x_implicitly_set_name (f, arg, oldval)
2765 FRAME_PTR f;
2766 Lisp_Object arg, oldval;
2767 {
2768 x_set_name (f, arg, 0);
2769 }
2770 \f
2771 /* Change the title of frame F to NAME.
2772 If NAME is nil, use the frame name as the title.
2773
2774 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2775 name; if NAME is a string, set F's name to NAME and set
2776 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2777
2778 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2779 suggesting a new name, which lisp code should override; if
2780 F->explicit_name is set, ignore the new name; otherwise, set it. */
2781
2782 void
2783 x_set_title (f, name, old_name)
2784 struct frame *f;
2785 Lisp_Object name, old_name;
2786 {
2787 /* Don't change the title if it's already NAME. */
2788 if (EQ (name, f->title))
2789 return;
2790
2791 update_mode_lines = 1;
2792
2793 f->title = name;
2794
2795 if (NILP (name))
2796 name = f->name;
2797
2798 if (FRAME_W32_WINDOW (f))
2799 {
2800 if (STRING_MULTIBYTE (name))
2801 name = ENCODE_SYSTEM (name);
2802
2803 BLOCK_INPUT;
2804 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
2805 UNBLOCK_INPUT;
2806 }
2807 }
2808 \f
2809 void
2810 x_set_autoraise (f, arg, oldval)
2811 struct frame *f;
2812 Lisp_Object arg, oldval;
2813 {
2814 f->auto_raise = !EQ (Qnil, arg);
2815 }
2816
2817 void
2818 x_set_autolower (f, arg, oldval)
2819 struct frame *f;
2820 Lisp_Object arg, oldval;
2821 {
2822 f->auto_lower = !EQ (Qnil, arg);
2823 }
2824
2825 void
2826 x_set_unsplittable (f, arg, oldval)
2827 struct frame *f;
2828 Lisp_Object arg, oldval;
2829 {
2830 f->no_split = !NILP (arg);
2831 }
2832
2833 void
2834 x_set_vertical_scroll_bars (f, arg, oldval)
2835 struct frame *f;
2836 Lisp_Object arg, oldval;
2837 {
2838 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2839 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2840 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2841 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2842 {
2843 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = NILP (arg) ?
2844 vertical_scroll_bar_none :
2845 /* Put scroll bars on the right by default, as is conventional
2846 on MS-Windows. */
2847 EQ (Qleft, arg)
2848 ? vertical_scroll_bar_left
2849 : vertical_scroll_bar_right;
2850
2851 /* We set this parameter before creating the window for the
2852 frame, so we can get the geometry right from the start.
2853 However, if the window hasn't been created yet, we shouldn't
2854 call x_set_window_size. */
2855 if (FRAME_W32_WINDOW (f))
2856 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2857 do_pending_window_change (0);
2858 }
2859 }
2860
2861 void
2862 x_set_scroll_bar_width (f, arg, oldval)
2863 struct frame *f;
2864 Lisp_Object arg, oldval;
2865 {
2866 int wid = FONT_WIDTH (f->output_data.w32->font);
2867
2868 if (NILP (arg))
2869 {
2870 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
2871 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) +
2872 wid - 1) / wid;
2873 if (FRAME_W32_WINDOW (f))
2874 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2875 do_pending_window_change (0);
2876 }
2877 else if (INTEGERP (arg) && XINT (arg) > 0
2878 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2879 {
2880 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2881 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2882 + wid-1) / wid;
2883 if (FRAME_W32_WINDOW (f))
2884 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2885 do_pending_window_change (0);
2886 }
2887 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2888 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2889 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2890 }
2891 \f
2892 /* Subroutines of creating an frame. */
2893
2894 /* Make sure that Vx_resource_name is set to a reasonable value.
2895 Fix it up, or set it to `emacs' if it is too hopeless. */
2896
2897 static void
2898 validate_x_resource_name ()
2899 {
2900 int len = 0;
2901 /* Number of valid characters in the resource name. */
2902 int good_count = 0;
2903 /* Number of invalid characters in the resource name. */
2904 int bad_count = 0;
2905 Lisp_Object new;
2906 int i;
2907
2908 if (STRINGP (Vx_resource_name))
2909 {
2910 unsigned char *p = XSTRING (Vx_resource_name)->data;
2911 int i;
2912
2913 len = STRING_BYTES (XSTRING (Vx_resource_name));
2914
2915 /* Only letters, digits, - and _ are valid in resource names.
2916 Count the valid characters and count the invalid ones. */
2917 for (i = 0; i < len; i++)
2918 {
2919 int c = p[i];
2920 if (! ((c >= 'a' && c <= 'z')
2921 || (c >= 'A' && c <= 'Z')
2922 || (c >= '0' && c <= '9')
2923 || c == '-' || c == '_'))
2924 bad_count++;
2925 else
2926 good_count++;
2927 }
2928 }
2929 else
2930 /* Not a string => completely invalid. */
2931 bad_count = 5, good_count = 0;
2932
2933 /* If name is valid already, return. */
2934 if (bad_count == 0)
2935 return;
2936
2937 /* If name is entirely invalid, or nearly so, use `emacs'. */
2938 if (good_count == 0
2939 || (good_count == 1 && bad_count > 0))
2940 {
2941 Vx_resource_name = build_string ("emacs");
2942 return;
2943 }
2944
2945 /* Name is partly valid. Copy it and replace the invalid characters
2946 with underscores. */
2947
2948 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2949
2950 for (i = 0; i < len; i++)
2951 {
2952 int c = XSTRING (new)->data[i];
2953 if (! ((c >= 'a' && c <= 'z')
2954 || (c >= 'A' && c <= 'Z')
2955 || (c >= '0' && c <= '9')
2956 || c == '-' || c == '_'))
2957 XSTRING (new)->data[i] = '_';
2958 }
2959 }
2960
2961
2962 extern char *x_get_string_resource ();
2963
2964 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2965 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2966 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2967 class, where INSTANCE is the name under which Emacs was invoked, or
2968 the name specified by the `-name' or `-rn' command-line arguments.
2969
2970 The optional arguments COMPONENT and SUBCLASS add to the key and the
2971 class, respectively. You must specify both of them or neither.
2972 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2973 and the class is `Emacs.CLASS.SUBCLASS'. */)
2974 (attribute, class, component, subclass)
2975 Lisp_Object attribute, class, component, subclass;
2976 {
2977 register char *value;
2978 char *name_key;
2979 char *class_key;
2980
2981 CHECK_STRING (attribute);
2982 CHECK_STRING (class);
2983
2984 if (!NILP (component))
2985 CHECK_STRING (component);
2986 if (!NILP (subclass))
2987 CHECK_STRING (subclass);
2988 if (NILP (component) != NILP (subclass))
2989 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2990
2991 validate_x_resource_name ();
2992
2993 /* Allocate space for the components, the dots which separate them,
2994 and the final '\0'. Make them big enough for the worst case. */
2995 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2996 + (STRINGP (component)
2997 ? STRING_BYTES (XSTRING (component)) : 0)
2998 + STRING_BYTES (XSTRING (attribute))
2999 + 3);
3000
3001 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3002 + STRING_BYTES (XSTRING (class))
3003 + (STRINGP (subclass)
3004 ? STRING_BYTES (XSTRING (subclass)) : 0)
3005 + 3);
3006
3007 /* Start with emacs.FRAMENAME for the name (the specific one)
3008 and with `Emacs' for the class key (the general one). */
3009 strcpy (name_key, XSTRING (Vx_resource_name)->data);
3010 strcpy (class_key, EMACS_CLASS);
3011
3012 strcat (class_key, ".");
3013 strcat (class_key, XSTRING (class)->data);
3014
3015 if (!NILP (component))
3016 {
3017 strcat (class_key, ".");
3018 strcat (class_key, XSTRING (subclass)->data);
3019
3020 strcat (name_key, ".");
3021 strcat (name_key, XSTRING (component)->data);
3022 }
3023
3024 strcat (name_key, ".");
3025 strcat (name_key, XSTRING (attribute)->data);
3026
3027 value = x_get_string_resource (Qnil,
3028 name_key, class_key);
3029
3030 if (value != (char *) 0)
3031 return build_string (value);
3032 else
3033 return Qnil;
3034 }
3035
3036 /* Used when C code wants a resource value. */
3037
3038 char *
3039 x_get_resource_string (attribute, class)
3040 char *attribute, *class;
3041 {
3042 char *name_key;
3043 char *class_key;
3044 struct frame *sf = SELECTED_FRAME ();
3045
3046 /* Allocate space for the components, the dots which separate them,
3047 and the final '\0'. */
3048 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
3049 + strlen (attribute) + 2);
3050 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3051 + strlen (class) + 2);
3052
3053 sprintf (name_key, "%s.%s",
3054 XSTRING (Vinvocation_name)->data,
3055 attribute);
3056 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3057
3058 return x_get_string_resource (sf, name_key, class_key);
3059 }
3060
3061 /* Types we might convert a resource string into. */
3062 enum resource_types
3063 {
3064 RES_TYPE_NUMBER,
3065 RES_TYPE_FLOAT,
3066 RES_TYPE_BOOLEAN,
3067 RES_TYPE_STRING,
3068 RES_TYPE_SYMBOL
3069 };
3070
3071 /* Return the value of parameter PARAM.
3072
3073 First search ALIST, then Vdefault_frame_alist, then the X defaults
3074 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3075
3076 Convert the resource to the type specified by desired_type.
3077
3078 If no default is specified, return Qunbound. If you call
3079 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
3080 and don't let it get stored in any Lisp-visible variables! */
3081
3082 static Lisp_Object
3083 w32_get_arg (alist, param, attribute, class, type)
3084 Lisp_Object alist, param;
3085 char *attribute;
3086 char *class;
3087 enum resource_types type;
3088 {
3089 register Lisp_Object tem;
3090
3091 tem = Fassq (param, alist);
3092 if (EQ (tem, Qnil))
3093 tem = Fassq (param, Vdefault_frame_alist);
3094 if (EQ (tem, Qnil))
3095 {
3096
3097 if (attribute)
3098 {
3099 tem = Fx_get_resource (build_string (attribute),
3100 build_string (class),
3101 Qnil, Qnil);
3102
3103 if (NILP (tem))
3104 return Qunbound;
3105
3106 switch (type)
3107 {
3108 case RES_TYPE_NUMBER:
3109 return make_number (atoi (XSTRING (tem)->data));
3110
3111 case RES_TYPE_FLOAT:
3112 return make_float (atof (XSTRING (tem)->data));
3113
3114 case RES_TYPE_BOOLEAN:
3115 tem = Fdowncase (tem);
3116 if (!strcmp (XSTRING (tem)->data, "on")
3117 || !strcmp (XSTRING (tem)->data, "true"))
3118 return Qt;
3119 else
3120 return Qnil;
3121
3122 case RES_TYPE_STRING:
3123 return tem;
3124
3125 case RES_TYPE_SYMBOL:
3126 /* As a special case, we map the values `true' and `on'
3127 to Qt, and `false' and `off' to Qnil. */
3128 {
3129 Lisp_Object lower;
3130 lower = Fdowncase (tem);
3131 if (!strcmp (XSTRING (lower)->data, "on")
3132 || !strcmp (XSTRING (lower)->data, "true"))
3133 return Qt;
3134 else if (!strcmp (XSTRING (lower)->data, "off")
3135 || !strcmp (XSTRING (lower)->data, "false"))
3136 return Qnil;
3137 else
3138 return Fintern (tem, Qnil);
3139 }
3140
3141 default:
3142 abort ();
3143 }
3144 }
3145 else
3146 return Qunbound;
3147 }
3148 return Fcdr (tem);
3149 }
3150
3151 /* Record in frame F the specified or default value according to ALIST
3152 of the parameter named PROP (a Lisp symbol).
3153 If no value is specified for PROP, look for an X default for XPROP
3154 on the frame named NAME.
3155 If that is not found either, use the value DEFLT. */
3156
3157 static Lisp_Object
3158 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3159 struct frame *f;
3160 Lisp_Object alist;
3161 Lisp_Object prop;
3162 Lisp_Object deflt;
3163 char *xprop;
3164 char *xclass;
3165 enum resource_types type;
3166 {
3167 Lisp_Object tem;
3168
3169 tem = w32_get_arg (alist, prop, xprop, xclass, type);
3170 if (EQ (tem, Qunbound))
3171 tem = deflt;
3172 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3173 return tem;
3174 }
3175 \f
3176 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3177 doc: /* Parse an X-style geometry string STRING.
3178 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3179 The properties returned may include `top', `left', `height', and `width'.
3180 The value of `left' or `top' may be an integer,
3181 or a list (+ N) meaning N pixels relative to top/left corner,
3182 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3183 (string)
3184 Lisp_Object string;
3185 {
3186 int geometry, x, y;
3187 unsigned int width, height;
3188 Lisp_Object result;
3189
3190 CHECK_STRING (string);
3191
3192 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3193 &x, &y, &width, &height);
3194
3195 result = Qnil;
3196 if (geometry & XValue)
3197 {
3198 Lisp_Object element;
3199
3200 if (x >= 0 && (geometry & XNegative))
3201 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3202 else if (x < 0 && ! (geometry & XNegative))
3203 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3204 else
3205 element = Fcons (Qleft, make_number (x));
3206 result = Fcons (element, result);
3207 }
3208
3209 if (geometry & YValue)
3210 {
3211 Lisp_Object element;
3212
3213 if (y >= 0 && (geometry & YNegative))
3214 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3215 else if (y < 0 && ! (geometry & YNegative))
3216 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3217 else
3218 element = Fcons (Qtop, make_number (y));
3219 result = Fcons (element, result);
3220 }
3221
3222 if (geometry & WidthValue)
3223 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3224 if (geometry & HeightValue)
3225 result = Fcons (Fcons (Qheight, make_number (height)), result);
3226
3227 return result;
3228 }
3229
3230 /* Calculate the desired size and position of this window,
3231 and return the flags saying which aspects were specified.
3232
3233 This function does not make the coordinates positive. */
3234
3235 #define DEFAULT_ROWS 40
3236 #define DEFAULT_COLS 80
3237
3238 static int
3239 x_figure_window_size (f, parms)
3240 struct frame *f;
3241 Lisp_Object parms;
3242 {
3243 register Lisp_Object tem0, tem1, tem2;
3244 long window_prompting = 0;
3245
3246 /* Default values if we fall through.
3247 Actually, if that happens we should get
3248 window manager prompting. */
3249 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3250 f->height = DEFAULT_ROWS;
3251 /* Window managers expect that if program-specified
3252 positions are not (0,0), they're intentional, not defaults. */
3253 f->output_data.w32->top_pos = 0;
3254 f->output_data.w32->left_pos = 0;
3255
3256 /* Ensure that old new_width and new_height will not override the
3257 values set here. */
3258 FRAME_NEW_WIDTH (f) = 0;
3259 FRAME_NEW_HEIGHT (f) = 0;
3260
3261 tem0 = w32_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3262 tem1 = w32_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3263 tem2 = w32_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3264 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3265 {
3266 if (!EQ (tem0, Qunbound))
3267 {
3268 CHECK_NUMBER (tem0);
3269 f->height = XINT (tem0);
3270 }
3271 if (!EQ (tem1, Qunbound))
3272 {
3273 CHECK_NUMBER (tem1);
3274 SET_FRAME_WIDTH (f, XINT (tem1));
3275 }
3276 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3277 window_prompting |= USSize;
3278 else
3279 window_prompting |= PSize;
3280 }
3281
3282 f->output_data.w32->vertical_scroll_bar_extra
3283 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3284 ? 0
3285 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3286 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3287 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
3288 x_compute_fringe_widths (f, 0);
3289 f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3290 f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3291
3292 tem0 = w32_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3293 tem1 = w32_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3294 tem2 = w32_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3295 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3296 {
3297 if (EQ (tem0, Qminus))
3298 {
3299 f->output_data.w32->top_pos = 0;
3300 window_prompting |= YNegative;
3301 }
3302 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3303 && CONSP (XCDR (tem0))
3304 && INTEGERP (XCAR (XCDR (tem0))))
3305 {
3306 f->output_data.w32->top_pos = - XINT (XCAR (XCDR (tem0)));
3307 window_prompting |= YNegative;
3308 }
3309 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3310 && CONSP (XCDR (tem0))
3311 && INTEGERP (XCAR (XCDR (tem0))))
3312 {
3313 f->output_data.w32->top_pos = XINT (XCAR (XCDR (tem0)));
3314 }
3315 else if (EQ (tem0, Qunbound))
3316 f->output_data.w32->top_pos = 0;
3317 else
3318 {
3319 CHECK_NUMBER (tem0);
3320 f->output_data.w32->top_pos = XINT (tem0);
3321 if (f->output_data.w32->top_pos < 0)
3322 window_prompting |= YNegative;
3323 }
3324
3325 if (EQ (tem1, Qminus))
3326 {
3327 f->output_data.w32->left_pos = 0;
3328 window_prompting |= XNegative;
3329 }
3330 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3331 && CONSP (XCDR (tem1))
3332 && INTEGERP (XCAR (XCDR (tem1))))
3333 {
3334 f->output_data.w32->left_pos = - XINT (XCAR (XCDR (tem1)));
3335 window_prompting |= XNegative;
3336 }
3337 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3338 && CONSP (XCDR (tem1))
3339 && INTEGERP (XCAR (XCDR (tem1))))
3340 {
3341 f->output_data.w32->left_pos = XINT (XCAR (XCDR (tem1)));
3342 }
3343 else if (EQ (tem1, Qunbound))
3344 f->output_data.w32->left_pos = 0;
3345 else
3346 {
3347 CHECK_NUMBER (tem1);
3348 f->output_data.w32->left_pos = XINT (tem1);
3349 if (f->output_data.w32->left_pos < 0)
3350 window_prompting |= XNegative;
3351 }
3352
3353 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3354 window_prompting |= USPosition;
3355 else
3356 window_prompting |= PPosition;
3357 }
3358
3359 return window_prompting;
3360 }
3361
3362 \f
3363
3364 extern LRESULT CALLBACK w32_wnd_proc ();
3365
3366 BOOL
3367 w32_init_class (hinst)
3368 HINSTANCE hinst;
3369 {
3370 WNDCLASS wc;
3371
3372 wc.style = CS_HREDRAW | CS_VREDRAW;
3373 wc.lpfnWndProc = (WNDPROC) w32_wnd_proc;
3374 wc.cbClsExtra = 0;
3375 wc.cbWndExtra = WND_EXTRA_BYTES;
3376 wc.hInstance = hinst;
3377 wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
3378 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
3379 wc.hbrBackground = NULL; /* GetStockObject (WHITE_BRUSH); */
3380 wc.lpszMenuName = NULL;
3381 wc.lpszClassName = EMACS_CLASS;
3382
3383 return (RegisterClass (&wc));
3384 }
3385
3386 HWND
3387 w32_createscrollbar (f, bar)
3388 struct frame *f;
3389 struct scroll_bar * bar;
3390 {
3391 return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
3392 /* Position and size of scroll bar. */
3393 XINT(bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3394 XINT(bar->top),
3395 XINT(bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3396 XINT(bar->height),
3397 FRAME_W32_WINDOW (f),
3398 NULL,
3399 hinst,
3400 NULL));
3401 }
3402
3403 void
3404 w32_createwindow (f)
3405 struct frame *f;
3406 {
3407 HWND hwnd;
3408 RECT rect;
3409
3410 rect.left = rect.top = 0;
3411 rect.right = PIXEL_WIDTH (f);
3412 rect.bottom = PIXEL_HEIGHT (f);
3413
3414 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
3415 FRAME_EXTERNAL_MENU_BAR (f));
3416
3417 /* Do first time app init */
3418
3419 if (!hprevinst)
3420 {
3421 w32_init_class (hinst);
3422 }
3423
3424 FRAME_W32_WINDOW (f) = hwnd
3425 = CreateWindow (EMACS_CLASS,
3426 f->namebuf,
3427 f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
3428 f->output_data.w32->left_pos,
3429 f->output_data.w32->top_pos,
3430 rect.right - rect.left,
3431 rect.bottom - rect.top,
3432 NULL,
3433 NULL,
3434 hinst,
3435 NULL);
3436
3437 if (hwnd)
3438 {
3439 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
3440 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
3441 SetWindowLong (hwnd, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
3442 SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
3443 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
3444
3445 /* Enable drag-n-drop. */
3446 DragAcceptFiles (hwnd, TRUE);
3447
3448 /* Do this to discard the default setting specified by our parent. */
3449 ShowWindow (hwnd, SW_HIDE);
3450 }
3451 }
3452
3453 void
3454 my_post_msg (wmsg, hwnd, msg, wParam, lParam)
3455 W32Msg * wmsg;
3456 HWND hwnd;
3457 UINT msg;
3458 WPARAM wParam;
3459 LPARAM lParam;
3460 {
3461 wmsg->msg.hwnd = hwnd;
3462 wmsg->msg.message = msg;
3463 wmsg->msg.wParam = wParam;
3464 wmsg->msg.lParam = lParam;
3465 wmsg->msg.time = GetMessageTime ();
3466
3467 post_msg (wmsg);
3468 }
3469
3470 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
3471 between left and right keys as advertised. We test for this
3472 support dynamically, and set a flag when the support is absent. If
3473 absent, we keep track of the left and right control and alt keys
3474 ourselves. This is particularly necessary on keyboards that rely
3475 upon the AltGr key, which is represented as having the left control
3476 and right alt keys pressed. For these keyboards, we need to know
3477 when the left alt key has been pressed in addition to the AltGr key
3478 so that we can properly support M-AltGr-key sequences (such as M-@
3479 on Swedish keyboards). */
3480
3481 #define EMACS_LCONTROL 0
3482 #define EMACS_RCONTROL 1
3483 #define EMACS_LMENU 2
3484 #define EMACS_RMENU 3
3485
3486 static int modifiers[4];
3487 static int modifiers_recorded;
3488 static int modifier_key_support_tested;
3489
3490 static void
3491 test_modifier_support (unsigned int wparam)
3492 {
3493 unsigned int l, r;
3494
3495 if (wparam != VK_CONTROL && wparam != VK_MENU)
3496 return;
3497 if (wparam == VK_CONTROL)
3498 {
3499 l = VK_LCONTROL;
3500 r = VK_RCONTROL;
3501 }
3502 else
3503 {
3504 l = VK_LMENU;
3505 r = VK_RMENU;
3506 }
3507 if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
3508 modifiers_recorded = 1;
3509 else
3510 modifiers_recorded = 0;
3511 modifier_key_support_tested = 1;
3512 }
3513
3514 static void
3515 record_keydown (unsigned int wparam, unsigned int lparam)
3516 {
3517 int i;
3518
3519 if (!modifier_key_support_tested)
3520 test_modifier_support (wparam);
3521
3522 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
3523 return;
3524
3525 if (wparam == VK_CONTROL)
3526 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
3527 else
3528 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
3529
3530 modifiers[i] = 1;
3531 }
3532
3533 static void
3534 record_keyup (unsigned int wparam, unsigned int lparam)
3535 {
3536 int i;
3537
3538 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
3539 return;
3540
3541 if (wparam == VK_CONTROL)
3542 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
3543 else
3544 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
3545
3546 modifiers[i] = 0;
3547 }
3548
3549 /* Emacs can lose focus while a modifier key has been pressed. When
3550 it regains focus, be conservative and clear all modifiers since
3551 we cannot reconstruct the left and right modifier state. */
3552 static void
3553 reset_modifiers ()
3554 {
3555 SHORT ctrl, alt;
3556
3557 if (GetFocus () == NULL)
3558 /* Emacs doesn't have keyboard focus. Do nothing. */
3559 return;
3560
3561 ctrl = GetAsyncKeyState (VK_CONTROL);
3562 alt = GetAsyncKeyState (VK_MENU);
3563
3564 if (!(ctrl & 0x08000))
3565 /* Clear any recorded control modifier state. */
3566 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3567
3568 if (!(alt & 0x08000))
3569 /* Clear any recorded alt modifier state. */
3570 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3571
3572 /* Update the state of all modifier keys, because modifiers used in
3573 hot-key combinations can get stuck on if Emacs loses focus as a
3574 result of a hot-key being pressed. */
3575 {
3576 BYTE keystate[256];
3577
3578 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
3579
3580 GetKeyboardState (keystate);
3581 keystate[VK_SHIFT] = CURRENT_STATE (VK_SHIFT);
3582 keystate[VK_CONTROL] = CURRENT_STATE (VK_CONTROL);
3583 keystate[VK_LCONTROL] = CURRENT_STATE (VK_LCONTROL);
3584 keystate[VK_RCONTROL] = CURRENT_STATE (VK_RCONTROL);
3585 keystate[VK_MENU] = CURRENT_STATE (VK_MENU);
3586 keystate[VK_LMENU] = CURRENT_STATE (VK_LMENU);
3587 keystate[VK_RMENU] = CURRENT_STATE (VK_RMENU);
3588 keystate[VK_LWIN] = CURRENT_STATE (VK_LWIN);
3589 keystate[VK_RWIN] = CURRENT_STATE (VK_RWIN);
3590 keystate[VK_APPS] = CURRENT_STATE (VK_APPS);
3591 SetKeyboardState (keystate);
3592 }
3593 }
3594
3595 /* Synchronize modifier state with what is reported with the current
3596 keystroke. Even if we cannot distinguish between left and right
3597 modifier keys, we know that, if no modifiers are set, then neither
3598 the left or right modifier should be set. */
3599 static void
3600 sync_modifiers ()
3601 {
3602 if (!modifiers_recorded)
3603 return;
3604
3605 if (!(GetKeyState (VK_CONTROL) & 0x8000))
3606 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3607
3608 if (!(GetKeyState (VK_MENU) & 0x8000))
3609 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3610 }
3611
3612 static int
3613 modifier_set (int vkey)
3614 {
3615 if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
3616 return (GetKeyState (vkey) & 0x1);
3617 if (!modifiers_recorded)
3618 return (GetKeyState (vkey) & 0x8000);
3619
3620 switch (vkey)
3621 {
3622 case VK_LCONTROL:
3623 return modifiers[EMACS_LCONTROL];
3624 case VK_RCONTROL:
3625 return modifiers[EMACS_RCONTROL];
3626 case VK_LMENU:
3627 return modifiers[EMACS_LMENU];
3628 case VK_RMENU:
3629 return modifiers[EMACS_RMENU];
3630 }
3631 return (GetKeyState (vkey) & 0x8000);
3632 }
3633
3634 /* Convert between the modifier bits W32 uses and the modifier bits
3635 Emacs uses. */
3636
3637 unsigned int
3638 w32_key_to_modifier (int key)
3639 {
3640 Lisp_Object key_mapping;
3641
3642 switch (key)
3643 {
3644 case VK_LWIN:
3645 key_mapping = Vw32_lwindow_modifier;
3646 break;
3647 case VK_RWIN:
3648 key_mapping = Vw32_rwindow_modifier;
3649 break;
3650 case VK_APPS:
3651 key_mapping = Vw32_apps_modifier;
3652 break;
3653 case VK_SCROLL:
3654 key_mapping = Vw32_scroll_lock_modifier;
3655 break;
3656 default:
3657 key_mapping = Qnil;
3658 }
3659
3660 /* NB. This code runs in the input thread, asychronously to the lisp
3661 thread, so we must be careful to ensure access to lisp data is
3662 thread-safe. The following code is safe because the modifier
3663 variable values are updated atomically from lisp and symbols are
3664 not relocated by GC. Also, we don't have to worry about seeing GC
3665 markbits here. */
3666 if (EQ (key_mapping, Qhyper))
3667 return hyper_modifier;
3668 if (EQ (key_mapping, Qsuper))
3669 return super_modifier;
3670 if (EQ (key_mapping, Qmeta))
3671 return meta_modifier;
3672 if (EQ (key_mapping, Qalt))
3673 return alt_modifier;
3674 if (EQ (key_mapping, Qctrl))
3675 return ctrl_modifier;
3676 if (EQ (key_mapping, Qcontrol)) /* synonym for ctrl */
3677 return ctrl_modifier;
3678 if (EQ (key_mapping, Qshift))
3679 return shift_modifier;
3680
3681 /* Don't generate any modifier if not explicitly requested. */
3682 return 0;
3683 }
3684
3685 unsigned int
3686 w32_get_modifiers ()
3687 {
3688 return ((modifier_set (VK_SHIFT) ? shift_modifier : 0) |
3689 (modifier_set (VK_CONTROL) ? ctrl_modifier : 0) |
3690 (modifier_set (VK_LWIN) ? w32_key_to_modifier (VK_LWIN) : 0) |
3691 (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) |
3692 (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) |
3693 (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) |
3694 (modifier_set (VK_MENU) ?
3695 ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
3696 }
3697
3698 /* We map the VK_* modifiers into console modifier constants
3699 so that we can use the same routines to handle both console
3700 and window input. */
3701
3702 static int
3703 construct_console_modifiers ()
3704 {
3705 int mods;
3706
3707 mods = 0;
3708 mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
3709 mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
3710 mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0;
3711 mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0;
3712 mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
3713 mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
3714 mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
3715 mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
3716 mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0;
3717 mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0;
3718 mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0;
3719
3720 return mods;
3721 }
3722
3723 static int
3724 w32_get_key_modifiers (unsigned int wparam, unsigned int lparam)
3725 {
3726 int mods;
3727
3728 /* Convert to emacs modifiers. */
3729 mods = w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam);
3730
3731 return mods;
3732 }
3733
3734 unsigned int
3735 map_keypad_keys (unsigned int virt_key, unsigned int extended)
3736 {
3737 if (virt_key < VK_CLEAR || virt_key > VK_DELETE)
3738 return virt_key;
3739
3740 if (virt_key == VK_RETURN)
3741 return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
3742
3743 if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN)
3744 return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key);
3745
3746 if (virt_key == VK_INSERT || virt_key == VK_DELETE)
3747 return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key);
3748
3749 if (virt_key == VK_CLEAR)
3750 return (!extended ? VK_NUMPAD_CLEAR : virt_key);
3751
3752 return virt_key;
3753 }
3754
3755 /* List of special key combinations which w32 would normally capture,
3756 but emacs should grab instead. Not directly visible to lisp, to
3757 simplify synchronization. Each item is an integer encoding a virtual
3758 key code and modifier combination to capture. */
3759 Lisp_Object w32_grabbed_keys;
3760
3761 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
3762 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
3763 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
3764 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
3765
3766 /* Register hot-keys for reserved key combinations when Emacs has
3767 keyboard focus, since this is the only way Emacs can receive key
3768 combinations like Alt-Tab which are used by the system. */
3769
3770 static void
3771 register_hot_keys (hwnd)
3772 HWND hwnd;
3773 {
3774 Lisp_Object keylist;
3775
3776 /* Use GC_CONSP, since we are called asynchronously. */
3777 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3778 {
3779 Lisp_Object key = XCAR (keylist);
3780
3781 /* Deleted entries get set to nil. */
3782 if (!INTEGERP (key))
3783 continue;
3784
3785 RegisterHotKey (hwnd, HOTKEY_ID (key),
3786 HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
3787 }
3788 }
3789
3790 static void
3791 unregister_hot_keys (hwnd)
3792 HWND hwnd;
3793 {
3794 Lisp_Object keylist;
3795
3796 /* Use GC_CONSP, since we are called asynchronously. */
3797 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3798 {
3799 Lisp_Object key = XCAR (keylist);
3800
3801 if (!INTEGERP (key))
3802 continue;
3803
3804 UnregisterHotKey (hwnd, HOTKEY_ID (key));
3805 }
3806 }
3807
3808 /* Main message dispatch loop. */
3809
3810 static void
3811 w32_msg_pump (deferred_msg * msg_buf)
3812 {
3813 MSG msg;
3814 int result;
3815 HWND focus_window;
3816
3817 msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
3818
3819 while (GetMessage (&msg, NULL, 0, 0))
3820 {
3821 if (msg.hwnd == NULL)
3822 {
3823 switch (msg.message)
3824 {
3825 case WM_NULL:
3826 /* Produced by complete_deferred_msg; just ignore. */
3827 break;
3828 case WM_EMACS_CREATEWINDOW:
3829 w32_createwindow ((struct frame *) msg.wParam);
3830 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3831 abort ();
3832 break;
3833 case WM_EMACS_SETLOCALE:
3834 SetThreadLocale (msg.wParam);
3835 /* Reply is not expected. */
3836 break;
3837 case WM_EMACS_SETKEYBOARDLAYOUT:
3838 result = (int) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
3839 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
3840 result, 0))
3841 abort ();
3842 break;
3843 case WM_EMACS_REGISTER_HOT_KEY:
3844 focus_window = GetFocus ();
3845 if (focus_window != NULL)
3846 RegisterHotKey (focus_window,
3847 HOTKEY_ID (msg.wParam),
3848 HOTKEY_MODIFIERS (msg.wParam),
3849 HOTKEY_VK_CODE (msg.wParam));
3850 /* Reply is not expected. */
3851 break;
3852 case WM_EMACS_UNREGISTER_HOT_KEY:
3853 focus_window = GetFocus ();
3854 if (focus_window != NULL)
3855 UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam));
3856 /* Mark item as erased. NB: this code must be
3857 thread-safe. The next line is okay because the cons
3858 cell is never made into garbage and is not relocated by
3859 GC. */
3860 XSETCAR ((Lisp_Object) msg.lParam, Qnil);
3861 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3862 abort ();
3863 break;
3864 case WM_EMACS_TOGGLE_LOCK_KEY:
3865 {
3866 int vk_code = (int) msg.wParam;
3867 int cur_state = (GetKeyState (vk_code) & 1);
3868 Lisp_Object new_state = (Lisp_Object) msg.lParam;
3869
3870 /* NB: This code must be thread-safe. It is safe to
3871 call NILP because symbols are not relocated by GC,
3872 and pointer here is not touched by GC (so the markbit
3873 can't be set). Numbers are safe because they are
3874 immediate values. */
3875 if (NILP (new_state)
3876 || (NUMBERP (new_state)
3877 && ((XUINT (new_state)) & 1) != cur_state))
3878 {
3879 one_w32_display_info.faked_key = vk_code;
3880
3881 keybd_event ((BYTE) vk_code,
3882 (BYTE) MapVirtualKey (vk_code, 0),
3883 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3884 keybd_event ((BYTE) vk_code,
3885 (BYTE) MapVirtualKey (vk_code, 0),
3886 KEYEVENTF_EXTENDEDKEY | 0, 0);
3887 keybd_event ((BYTE) vk_code,
3888 (BYTE) MapVirtualKey (vk_code, 0),
3889 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3890 cur_state = !cur_state;
3891 }
3892 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
3893 cur_state, 0))
3894 abort ();
3895 }
3896 break;
3897 default:
3898 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
3899 }
3900 }
3901 else
3902 {
3903 DispatchMessage (&msg);
3904 }
3905
3906 /* Exit nested loop when our deferred message has completed. */
3907 if (msg_buf->completed)
3908 break;
3909 }
3910 }
3911
3912 deferred_msg * deferred_msg_head;
3913
3914 static deferred_msg *
3915 find_deferred_msg (HWND hwnd, UINT msg)
3916 {
3917 deferred_msg * item;
3918
3919 /* Don't actually need synchronization for read access, since
3920 modification of single pointer is always atomic. */
3921 /* enter_crit (); */
3922
3923 for (item = deferred_msg_head; item != NULL; item = item->next)
3924 if (item->w32msg.msg.hwnd == hwnd
3925 && item->w32msg.msg.message == msg)
3926 break;
3927
3928 /* leave_crit (); */
3929
3930 return item;
3931 }
3932
3933 static LRESULT
3934 send_deferred_msg (deferred_msg * msg_buf,
3935 HWND hwnd,
3936 UINT msg,
3937 WPARAM wParam,
3938 LPARAM lParam)
3939 {
3940 /* Only input thread can send deferred messages. */
3941 if (GetCurrentThreadId () != dwWindowsThreadId)
3942 abort ();
3943
3944 /* It is an error to send a message that is already deferred. */
3945 if (find_deferred_msg (hwnd, msg) != NULL)
3946 abort ();
3947
3948 /* Enforced synchronization is not needed because this is the only
3949 function that alters deferred_msg_head, and the following critical
3950 section is guaranteed to only be serially reentered (since only the
3951 input thread can call us). */
3952
3953 /* enter_crit (); */
3954
3955 msg_buf->completed = 0;
3956 msg_buf->next = deferred_msg_head;
3957 deferred_msg_head = msg_buf;
3958 my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam);
3959
3960 /* leave_crit (); */
3961
3962 /* Start a new nested message loop to process other messages until
3963 this one is completed. */
3964 w32_msg_pump (msg_buf);
3965
3966 deferred_msg_head = msg_buf->next;
3967
3968 return msg_buf->result;
3969 }
3970
3971 void
3972 complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
3973 {
3974 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
3975
3976 if (msg_buf == NULL)
3977 /* Message may have been cancelled, so don't abort(). */
3978 return;
3979
3980 msg_buf->result = result;
3981 msg_buf->completed = 1;
3982
3983 /* Ensure input thread is woken so it notices the completion. */
3984 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
3985 }
3986
3987 void
3988 cancel_all_deferred_msgs ()
3989 {
3990 deferred_msg * item;
3991
3992 /* Don't actually need synchronization for read access, since
3993 modification of single pointer is always atomic. */
3994 /* enter_crit (); */
3995
3996 for (item = deferred_msg_head; item != NULL; item = item->next)
3997 {
3998 item->result = 0;
3999 item->completed = 1;
4000 }
4001
4002 /* leave_crit (); */
4003
4004 /* Ensure input thread is woken so it notices the completion. */
4005 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
4006 }
4007
4008 DWORD
4009 w32_msg_worker (dw)
4010 DWORD dw;
4011 {
4012 MSG msg;
4013 deferred_msg dummy_buf;
4014
4015 /* Ensure our message queue is created */
4016
4017 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
4018
4019 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
4020 abort ();
4021
4022 memset (&dummy_buf, 0, sizeof (dummy_buf));
4023 dummy_buf.w32msg.msg.hwnd = NULL;
4024 dummy_buf.w32msg.msg.message = WM_NULL;
4025
4026 /* This is the inital message loop which should only exit when the
4027 application quits. */
4028 w32_msg_pump (&dummy_buf);
4029
4030 return 0;
4031 }
4032
4033 static void
4034 post_character_message (hwnd, msg, wParam, lParam, modifiers)
4035 HWND hwnd;
4036 UINT msg;
4037 WPARAM wParam;
4038 LPARAM lParam;
4039 DWORD modifiers;
4040
4041 {
4042 W32Msg wmsg;
4043
4044 wmsg.dwModifiers = modifiers;
4045
4046 /* Detect quit_char and set quit-flag directly. Note that we
4047 still need to post a message to ensure the main thread will be
4048 woken up if blocked in sys_select(), but we do NOT want to post
4049 the quit_char message itself (because it will usually be as if
4050 the user had typed quit_char twice). Instead, we post a dummy
4051 message that has no particular effect. */
4052 {
4053 int c = wParam;
4054 if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
4055 c = make_ctrl_char (c) & 0377;
4056 if (c == quit_char
4057 || (wmsg.dwModifiers == 0 &&
4058 XFASTINT (Vw32_quit_key) && wParam == XFASTINT (Vw32_quit_key)))
4059 {
4060 Vquit_flag = Qt;
4061
4062 /* The choice of message is somewhat arbitrary, as long as
4063 the main thread handler just ignores it. */
4064 msg = WM_NULL;
4065
4066 /* Interrupt any blocking system calls. */
4067 signal_quit ();
4068
4069 /* As a safety precaution, forcibly complete any deferred
4070 messages. This is a kludge, but I don't see any particularly
4071 clean way to handle the situation where a deferred message is
4072 "dropped" in the lisp thread, and will thus never be
4073 completed, eg. by the user trying to activate the menubar
4074 when the lisp thread is busy, and then typing C-g when the
4075 menubar doesn't open promptly (with the result that the
4076 menubar never responds at all because the deferred
4077 WM_INITMENU message is never completed). Another problem
4078 situation is when the lisp thread calls SendMessage (to send
4079 a window manager command) when a message has been deferred;
4080 the lisp thread gets blocked indefinitely waiting for the
4081 deferred message to be completed, which itself is waiting for
4082 the lisp thread to respond.
4083
4084 Note that we don't want to block the input thread waiting for
4085 a reponse from the lisp thread (although that would at least
4086 solve the deadlock problem above), because we want to be able
4087 to receive C-g to interrupt the lisp thread. */
4088 cancel_all_deferred_msgs ();
4089 }
4090 }
4091
4092 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4093 }
4094
4095 /* Main window procedure */
4096
4097 LRESULT CALLBACK
4098 w32_wnd_proc (hwnd, msg, wParam, lParam)
4099 HWND hwnd;
4100 UINT msg;
4101 WPARAM wParam;
4102 LPARAM lParam;
4103 {
4104 struct frame *f;
4105 struct w32_display_info *dpyinfo = &one_w32_display_info;
4106 W32Msg wmsg;
4107 int windows_translate;
4108 int key;
4109
4110 /* Note that it is okay to call x_window_to_frame, even though we are
4111 not running in the main lisp thread, because frame deletion
4112 requires the lisp thread to synchronize with this thread. Thus, if
4113 a frame struct is returned, it can be used without concern that the
4114 lisp thread might make it disappear while we are using it.
4115
4116 NB. Walking the frame list in this thread is safe (as long as
4117 writes of Lisp_Object slots are atomic, which they are on Windows).
4118 Although delete-frame can destructively modify the frame list while
4119 we are walking it, a garbage collection cannot occur until after
4120 delete-frame has synchronized with this thread.
4121
4122 It is also safe to use functions that make GDI calls, such as
4123 w32_clear_rect, because these functions must obtain a DC handle
4124 from the frame struct using get_frame_dc which is thread-aware. */
4125
4126 switch (msg)
4127 {
4128 case WM_ERASEBKGND:
4129 f = x_window_to_frame (dpyinfo, hwnd);
4130 if (f)
4131 {
4132 HDC hdc = get_frame_dc (f);
4133 GetUpdateRect (hwnd, &wmsg.rect, FALSE);
4134 w32_clear_rect (f, hdc, &wmsg.rect);
4135 release_frame_dc (f, hdc);
4136
4137 #if defined (W32_DEBUG_DISPLAY)
4138 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
4139 f,
4140 wmsg.rect.left, wmsg.rect.top,
4141 wmsg.rect.right, wmsg.rect.bottom));
4142 #endif /* W32_DEBUG_DISPLAY */
4143 }
4144 return 1;
4145 case WM_PALETTECHANGED:
4146 /* ignore our own changes */
4147 if ((HWND)wParam != hwnd)
4148 {
4149 f = x_window_to_frame (dpyinfo, hwnd);
4150 if (f)
4151 /* get_frame_dc will realize our palette and force all
4152 frames to be redrawn if needed. */
4153 release_frame_dc (f, get_frame_dc (f));
4154 }
4155 return 0;
4156 case WM_PAINT:
4157 {
4158 PAINTSTRUCT paintStruct;
4159 RECT update_rect;
4160 bzero (&update_rect, sizeof (update_rect));
4161
4162 f = x_window_to_frame (dpyinfo, hwnd);
4163 if (f == 0)
4164 {
4165 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd));
4166 return 0;
4167 }
4168
4169 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
4170 fails. Apparently this can happen under some
4171 circumstances. */
4172 if (GetUpdateRect (hwnd, &update_rect, FALSE) || !w32_strict_painting)
4173 {
4174 enter_crit ();
4175 BeginPaint (hwnd, &paintStruct);
4176
4177 /* The rectangles returned by GetUpdateRect and BeginPaint
4178 do not always match. Play it safe by assuming both areas
4179 are invalid. */
4180 UnionRect (&(wmsg.rect), &update_rect, &(paintStruct.rcPaint));
4181
4182 #if defined (W32_DEBUG_DISPLAY)
4183 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
4184 f,
4185 wmsg.rect.left, wmsg.rect.top,
4186 wmsg.rect.right, wmsg.rect.bottom));
4187 DebPrint ((" [update region is %d,%d-%d,%d]\n",
4188 update_rect.left, update_rect.top,
4189 update_rect.right, update_rect.bottom));
4190 #endif
4191 EndPaint (hwnd, &paintStruct);
4192 leave_crit ();
4193
4194 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4195
4196 return 0;
4197 }
4198
4199 /* If GetUpdateRect returns 0 (meaning there is no update
4200 region), assume the whole window needs to be repainted. */
4201 GetClientRect(hwnd, &wmsg.rect);
4202 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4203 return 0;
4204 }
4205
4206 case WM_INPUTLANGCHANGE:
4207 /* Inform lisp thread of keyboard layout changes. */
4208 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4209
4210 /* Clear dead keys in the keyboard state; for simplicity only
4211 preserve modifier key states. */
4212 {
4213 int i;
4214 BYTE keystate[256];
4215
4216 GetKeyboardState (keystate);
4217 for (i = 0; i < 256; i++)
4218 if (1
4219 && i != VK_SHIFT
4220 && i != VK_LSHIFT
4221 && i != VK_RSHIFT
4222 && i != VK_CAPITAL
4223 && i != VK_NUMLOCK
4224 && i != VK_SCROLL
4225 && i != VK_CONTROL
4226 && i != VK_LCONTROL
4227 && i != VK_RCONTROL
4228 && i != VK_MENU
4229 && i != VK_LMENU
4230 && i != VK_RMENU
4231 && i != VK_LWIN
4232 && i != VK_RWIN)
4233 keystate[i] = 0;
4234 SetKeyboardState (keystate);
4235 }
4236 goto dflt;
4237
4238 case WM_HOTKEY:
4239 /* Synchronize hot keys with normal input. */
4240 PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
4241 return (0);
4242
4243 case WM_KEYUP:
4244 case WM_SYSKEYUP:
4245 record_keyup (wParam, lParam);
4246 goto dflt;
4247
4248 case WM_KEYDOWN:
4249 case WM_SYSKEYDOWN:
4250 /* Ignore keystrokes we fake ourself; see below. */
4251 if (dpyinfo->faked_key == wParam)
4252 {
4253 dpyinfo->faked_key = 0;
4254 /* Make sure TranslateMessage sees them though (as long as
4255 they don't produce WM_CHAR messages). This ensures that
4256 indicator lights are toggled promptly on Windows 9x, for
4257 example. */
4258 if (lispy_function_keys[wParam] != 0)
4259 {
4260 windows_translate = 1;
4261 goto translate;
4262 }
4263 return 0;
4264 }
4265
4266 /* Synchronize modifiers with current keystroke. */
4267 sync_modifiers ();
4268 record_keydown (wParam, lParam);
4269 wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
4270
4271 windows_translate = 0;
4272
4273 switch (wParam)
4274 {
4275 case VK_LWIN:
4276 if (NILP (Vw32_pass_lwindow_to_system))
4277 {
4278 /* Prevent system from acting on keyup (which opens the
4279 Start menu if no other key was pressed) by simulating a
4280 press of Space which we will ignore. */
4281 if (GetAsyncKeyState (wParam) & 1)
4282 {
4283 if (NUMBERP (Vw32_phantom_key_code))
4284 key = XUINT (Vw32_phantom_key_code) & 255;
4285 else
4286 key = VK_SPACE;
4287 dpyinfo->faked_key = key;
4288 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
4289 }
4290 }
4291 if (!NILP (Vw32_lwindow_modifier))
4292 return 0;
4293 break;
4294 case VK_RWIN:
4295 if (NILP (Vw32_pass_rwindow_to_system))
4296 {
4297 if (GetAsyncKeyState (wParam) & 1)
4298 {
4299 if (NUMBERP (Vw32_phantom_key_code))
4300 key = XUINT (Vw32_phantom_key_code) & 255;
4301 else
4302 key = VK_SPACE;
4303 dpyinfo->faked_key = key;
4304 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
4305 }
4306 }
4307 if (!NILP (Vw32_rwindow_modifier))
4308 return 0;
4309 break;
4310 case VK_APPS:
4311 if (!NILP (Vw32_apps_modifier))
4312 return 0;
4313 break;
4314 case VK_MENU:
4315 if (NILP (Vw32_pass_alt_to_system))
4316 /* Prevent DefWindowProc from activating the menu bar if an
4317 Alt key is pressed and released by itself. */
4318 return 0;
4319 windows_translate = 1;
4320 break;
4321 case VK_CAPITAL:
4322 /* Decide whether to treat as modifier or function key. */
4323 if (NILP (Vw32_enable_caps_lock))
4324 goto disable_lock_key;
4325 windows_translate = 1;
4326 break;
4327 case VK_NUMLOCK:
4328 /* Decide whether to treat as modifier or function key. */
4329 if (NILP (Vw32_enable_num_lock))
4330 goto disable_lock_key;
4331 windows_translate = 1;
4332 break;
4333 case VK_SCROLL:
4334 /* Decide whether to treat as modifier or function key. */
4335 if (NILP (Vw32_scroll_lock_modifier))
4336 goto disable_lock_key;
4337 windows_translate = 1;
4338 break;
4339 disable_lock_key:
4340 /* Ensure the appropriate lock key state (and indicator light)
4341 remains in the same state. We do this by faking another
4342 press of the relevant key. Apparently, this really is the
4343 only way to toggle the state of the indicator lights. */
4344 dpyinfo->faked_key = wParam;
4345 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4346 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
4347 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4348 KEYEVENTF_EXTENDEDKEY | 0, 0);
4349 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4350 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
4351 /* Ensure indicator lights are updated promptly on Windows 9x
4352 (TranslateMessage apparently does this), after forwarding
4353 input event. */
4354 post_character_message (hwnd, msg, wParam, lParam,
4355 w32_get_key_modifiers (wParam, lParam));
4356 windows_translate = 1;
4357 break;
4358 case VK_CONTROL:
4359 case VK_SHIFT:
4360 case VK_PROCESSKEY: /* Generated by IME. */
4361 windows_translate = 1;
4362 break;
4363 case VK_CANCEL:
4364 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
4365 which is confusing for purposes of key binding; convert
4366 VK_CANCEL events into VK_PAUSE events. */
4367 wParam = VK_PAUSE;
4368 break;
4369 case VK_PAUSE:
4370 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
4371 for purposes of key binding; convert these back into
4372 VK_NUMLOCK events, at least when we want to see NumLock key
4373 presses. (Note that there is never any possibility that
4374 VK_PAUSE with Ctrl really is C-Pause as per above.) */
4375 if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL))
4376 wParam = VK_NUMLOCK;
4377 break;
4378 default:
4379 /* If not defined as a function key, change it to a WM_CHAR message. */
4380 if (lispy_function_keys[wParam] == 0)
4381 {
4382 DWORD modifiers = construct_console_modifiers ();
4383
4384 if (!NILP (Vw32_recognize_altgr)
4385 && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))
4386 {
4387 /* Always let TranslateMessage handle AltGr key chords;
4388 for some reason, ToAscii doesn't always process AltGr
4389 chords correctly. */
4390 windows_translate = 1;
4391 }
4392 else if ((modifiers & (~SHIFT_PRESSED & ~CAPSLOCK_ON)) != 0)
4393 {
4394 /* Handle key chords including any modifiers other
4395 than shift directly, in order to preserve as much
4396 modifier information as possible. */
4397 if ('A' <= wParam && wParam <= 'Z')
4398 {
4399 /* Don't translate modified alphabetic keystrokes,
4400 so the user doesn't need to constantly switch
4401 layout to type control or meta keystrokes when
4402 the normal layout translates alphabetic
4403 characters to non-ascii characters. */
4404 if (!modifier_set (VK_SHIFT))
4405 wParam += ('a' - 'A');
4406 msg = WM_CHAR;
4407 }
4408 else
4409 {
4410 /* Try to handle other keystrokes by determining the
4411 base character (ie. translating the base key plus
4412 shift modifier). */
4413 int add;
4414 int isdead = 0;
4415 KEY_EVENT_RECORD key;
4416
4417 key.bKeyDown = TRUE;
4418 key.wRepeatCount = 1;
4419 key.wVirtualKeyCode = wParam;
4420 key.wVirtualScanCode = (lParam & 0xFF0000) >> 16;
4421 key.uChar.AsciiChar = 0;
4422 key.dwControlKeyState = modifiers;
4423
4424 add = w32_kbd_patch_key (&key);
4425 /* 0 means an unrecognised keycode, negative means
4426 dead key. Ignore both. */
4427 while (--add >= 0)
4428 {
4429 /* Forward asciified character sequence. */
4430 post_character_message
4431 (hwnd, WM_CHAR, key.uChar.AsciiChar, lParam,
4432 w32_get_key_modifiers (wParam, lParam));
4433 w32_kbd_patch_key (&key);
4434 }
4435 return 0;
4436 }
4437 }
4438 else
4439 {
4440 /* Let TranslateMessage handle everything else. */
4441 windows_translate = 1;
4442 }
4443 }
4444 }
4445
4446 translate:
4447 if (windows_translate)
4448 {
4449 MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
4450
4451 windows_msg.time = GetMessageTime ();
4452 TranslateMessage (&windows_msg);
4453 goto dflt;
4454 }
4455
4456 /* Fall through */
4457
4458 case WM_SYSCHAR:
4459 case WM_CHAR:
4460 post_character_message (hwnd, msg, wParam, lParam,
4461 w32_get_key_modifiers (wParam, lParam));
4462 break;
4463
4464 /* Simulate middle mouse button events when left and right buttons
4465 are used together, but only if user has two button mouse. */
4466 case WM_LBUTTONDOWN:
4467 case WM_RBUTTONDOWN:
4468 if (XINT (Vw32_num_mouse_buttons) > 2)
4469 goto handle_plain_button;
4470
4471 {
4472 int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
4473 int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
4474
4475 if (button_state & this)
4476 return 0;
4477
4478 if (button_state == 0)
4479 SetCapture (hwnd);
4480
4481 button_state |= this;
4482
4483 if (button_state & other)
4484 {
4485 if (mouse_button_timer)
4486 {
4487 KillTimer (hwnd, mouse_button_timer);
4488 mouse_button_timer = 0;
4489
4490 /* Generate middle mouse event instead. */
4491 msg = WM_MBUTTONDOWN;
4492 button_state |= MMOUSE;
4493 }
4494 else if (button_state & MMOUSE)
4495 {
4496 /* Ignore button event if we've already generated a
4497 middle mouse down event. This happens if the
4498 user releases and press one of the two buttons
4499 after we've faked a middle mouse event. */
4500 return 0;
4501 }
4502 else
4503 {
4504 /* Flush out saved message. */
4505 post_msg (&saved_mouse_button_msg);
4506 }
4507 wmsg.dwModifiers = w32_get_modifiers ();
4508 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4509
4510 /* Clear message buffer. */
4511 saved_mouse_button_msg.msg.hwnd = 0;
4512 }
4513 else
4514 {
4515 /* Hold onto message for now. */
4516 mouse_button_timer =
4517 SetTimer (hwnd, MOUSE_BUTTON_ID,
4518 XINT (Vw32_mouse_button_tolerance), NULL);
4519 saved_mouse_button_msg.msg.hwnd = hwnd;
4520 saved_mouse_button_msg.msg.message = msg;
4521 saved_mouse_button_msg.msg.wParam = wParam;
4522 saved_mouse_button_msg.msg.lParam = lParam;
4523 saved_mouse_button_msg.msg.time = GetMessageTime ();
4524 saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
4525 }
4526 }
4527 return 0;
4528
4529 case WM_LBUTTONUP:
4530 case WM_RBUTTONUP:
4531 if (XINT (Vw32_num_mouse_buttons) > 2)
4532 goto handle_plain_button;
4533
4534 {
4535 int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
4536 int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
4537
4538 if ((button_state & this) == 0)
4539 return 0;
4540
4541 button_state &= ~this;
4542
4543 if (button_state & MMOUSE)
4544 {
4545 /* Only generate event when second button is released. */
4546 if ((button_state & other) == 0)
4547 {
4548 msg = WM_MBUTTONUP;
4549 button_state &= ~MMOUSE;
4550
4551 if (button_state) abort ();
4552 }
4553 else
4554 return 0;
4555 }
4556 else
4557 {
4558 /* Flush out saved message if necessary. */
4559 if (saved_mouse_button_msg.msg.hwnd)
4560 {
4561 post_msg (&saved_mouse_button_msg);
4562 }
4563 }
4564 wmsg.dwModifiers = w32_get_modifiers ();
4565 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4566
4567 /* Always clear message buffer and cancel timer. */
4568 saved_mouse_button_msg.msg.hwnd = 0;
4569 KillTimer (hwnd, mouse_button_timer);
4570 mouse_button_timer = 0;
4571
4572 if (button_state == 0)
4573 ReleaseCapture ();
4574 }
4575 return 0;
4576
4577 case WM_XBUTTONDOWN:
4578 case WM_XBUTTONUP:
4579 if (w32_pass_extra_mouse_buttons_to_system)
4580 goto dflt;
4581 /* else fall through and process them. */
4582 case WM_MBUTTONDOWN:
4583 case WM_MBUTTONUP:
4584 handle_plain_button:
4585 {
4586 BOOL up;
4587 int button;
4588
4589 if (parse_button (msg, HIWORD (wParam), &button, &up))
4590 {
4591 if (up) ReleaseCapture ();
4592 else SetCapture (hwnd);
4593 button = (button == 0) ? LMOUSE :
4594 ((button == 1) ? MMOUSE : RMOUSE);
4595 if (up)
4596 button_state &= ~button;
4597 else
4598 button_state |= button;
4599 }
4600 }
4601
4602 wmsg.dwModifiers = w32_get_modifiers ();
4603 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4604
4605 /* Need to return true for XBUTTON messages, false for others,
4606 to indicate that we processed the message. */
4607 return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
4608
4609 case WM_MOUSEMOVE:
4610 /* If the mouse has just moved into the frame, start tracking
4611 it, so we will be notified when it leaves the frame. Mouse
4612 tracking only works under W98 and NT4 and later. On earlier
4613 versions, there is no way of telling when the mouse leaves the
4614 frame, so we just have to put up with help-echo and mouse
4615 highlighting remaining while the frame is not active. */
4616 if (track_mouse_event_fn && !track_mouse_window)
4617 {
4618 TRACKMOUSEEVENT tme;
4619 tme.cbSize = sizeof (tme);
4620 tme.dwFlags = TME_LEAVE;
4621 tme.hwndTrack = hwnd;
4622
4623 track_mouse_event_fn (&tme);
4624 track_mouse_window = hwnd;
4625 }
4626 case WM_VSCROLL:
4627 if (XINT (Vw32_mouse_move_interval) <= 0
4628 || (msg == WM_MOUSEMOVE && button_state == 0))
4629 {
4630 wmsg.dwModifiers = w32_get_modifiers ();
4631 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4632 return 0;
4633 }
4634
4635 /* Hang onto mouse move and scroll messages for a bit, to avoid
4636 sending such events to Emacs faster than it can process them.
4637 If we get more events before the timer from the first message
4638 expires, we just replace the first message. */
4639
4640 if (saved_mouse_move_msg.msg.hwnd == 0)
4641 mouse_move_timer =
4642 SetTimer (hwnd, MOUSE_MOVE_ID,
4643 XINT (Vw32_mouse_move_interval), NULL);
4644
4645 /* Hold onto message for now. */
4646 saved_mouse_move_msg.msg.hwnd = hwnd;
4647 saved_mouse_move_msg.msg.message = msg;
4648 saved_mouse_move_msg.msg.wParam = wParam;
4649 saved_mouse_move_msg.msg.lParam = lParam;
4650 saved_mouse_move_msg.msg.time = GetMessageTime ();
4651 saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
4652
4653 return 0;
4654
4655 case WM_MOUSEWHEEL:
4656 wmsg.dwModifiers = w32_get_modifiers ();
4657 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4658 return 0;
4659
4660 case WM_DROPFILES:
4661 wmsg.dwModifiers = w32_get_modifiers ();
4662 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4663 return 0;
4664
4665 case WM_TIMER:
4666 /* Flush out saved messages if necessary. */
4667 if (wParam == mouse_button_timer)
4668 {
4669 if (saved_mouse_button_msg.msg.hwnd)
4670 {
4671 post_msg (&saved_mouse_button_msg);
4672 saved_mouse_button_msg.msg.hwnd = 0;
4673 }
4674 KillTimer (hwnd, mouse_button_timer);
4675 mouse_button_timer = 0;
4676 }
4677 else if (wParam == mouse_move_timer)
4678 {
4679 if (saved_mouse_move_msg.msg.hwnd)
4680 {
4681 post_msg (&saved_mouse_move_msg);
4682 saved_mouse_move_msg.msg.hwnd = 0;
4683 }
4684 KillTimer (hwnd, mouse_move_timer);
4685 mouse_move_timer = 0;
4686 }
4687 return 0;
4688
4689 case WM_NCACTIVATE:
4690 /* Windows doesn't send us focus messages when putting up and
4691 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
4692 The only indication we get that something happened is receiving
4693 this message afterwards. So this is a good time to reset our
4694 keyboard modifiers' state. */
4695 reset_modifiers ();
4696 goto dflt;
4697
4698 case WM_INITMENU:
4699 button_state = 0;
4700 ReleaseCapture ();
4701 /* We must ensure menu bar is fully constructed and up to date
4702 before allowing user interaction with it. To achieve this
4703 we send this message to the lisp thread and wait for a
4704 reply (whose value is not actually needed) to indicate that
4705 the menu bar is now ready for use, so we can now return.
4706
4707 To remain responsive in the meantime, we enter a nested message
4708 loop that can process all other messages.
4709
4710 However, we skip all this if the message results from calling
4711 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
4712 thread a message because it is blocked on us at this point. We
4713 set menubar_active before calling TrackPopupMenu to indicate
4714 this (there is no possibility of confusion with real menubar
4715 being active). */
4716
4717 f = x_window_to_frame (dpyinfo, hwnd);
4718 if (f
4719 && (f->output_data.w32->menubar_active
4720 /* We can receive this message even in the absence of a
4721 menubar (ie. when the system menu is activated) - in this
4722 case we do NOT want to forward the message, otherwise it
4723 will cause the menubar to suddenly appear when the user
4724 had requested it to be turned off! */
4725 || f->output_data.w32->menubar_widget == NULL))
4726 return 0;
4727
4728 {
4729 deferred_msg msg_buf;
4730
4731 /* Detect if message has already been deferred; in this case
4732 we cannot return any sensible value to ignore this. */
4733 if (find_deferred_msg (hwnd, msg) != NULL)
4734 abort ();
4735
4736 return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
4737 }
4738
4739 case WM_EXITMENULOOP:
4740 f = x_window_to_frame (dpyinfo, hwnd);
4741
4742 /* Free memory used by owner-drawn and help-echo strings. */
4743 w32_free_menu_strings (hwnd);
4744
4745 /* Indicate that menubar can be modified again. */
4746 if (f)
4747 f->output_data.w32->menubar_active = 0;
4748 goto dflt;
4749
4750 case WM_MENUSELECT:
4751 /* Direct handling of help_echo in menus. Should be safe now
4752 that we generate the help_echo by placing a help event in the
4753 keyboard buffer. */
4754 {
4755 HMENU menu = (HMENU) lParam;
4756 UINT menu_item = (UINT) LOWORD (wParam);
4757 UINT flags = (UINT) HIWORD (wParam);
4758
4759 w32_menu_display_help (hwnd, menu, menu_item, flags);
4760 }
4761 return 0;
4762
4763 case WM_MEASUREITEM:
4764 f = x_window_to_frame (dpyinfo, hwnd);
4765 if (f)
4766 {
4767 MEASUREITEMSTRUCT * pMis = (MEASUREITEMSTRUCT *) lParam;
4768
4769 if (pMis->CtlType == ODT_MENU)
4770 {
4771 /* Work out dimensions for popup menu titles. */
4772 char * title = (char *) pMis->itemData;
4773 HDC hdc = GetDC (hwnd);
4774 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
4775 LOGFONT menu_logfont;
4776 HFONT old_font;
4777 SIZE size;
4778
4779 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
4780 menu_logfont.lfWeight = FW_BOLD;
4781 menu_font = CreateFontIndirect (&menu_logfont);
4782 old_font = SelectObject (hdc, menu_font);
4783
4784 pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE);
4785 if (title)
4786 {
4787 GetTextExtentPoint32 (hdc, title, strlen (title), &size);
4788 pMis->itemWidth = size.cx;
4789 if (pMis->itemHeight < size.cy)
4790 pMis->itemHeight = size.cy;
4791 }
4792 else
4793 pMis->itemWidth = 0;
4794
4795 SelectObject (hdc, old_font);
4796 DeleteObject (menu_font);
4797 ReleaseDC (hwnd, hdc);
4798 return TRUE;
4799 }
4800 }
4801 return 0;
4802
4803 case WM_DRAWITEM:
4804 f = x_window_to_frame (dpyinfo, hwnd);
4805 if (f)
4806 {
4807 DRAWITEMSTRUCT * pDis = (DRAWITEMSTRUCT *) lParam;
4808
4809 if (pDis->CtlType == ODT_MENU)
4810 {
4811 /* Draw popup menu title. */
4812 char * title = (char *) pDis->itemData;
4813 if (title)
4814 {
4815 HDC hdc = pDis->hDC;
4816 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
4817 LOGFONT menu_logfont;
4818 HFONT old_font;
4819
4820 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
4821 menu_logfont.lfWeight = FW_BOLD;
4822 menu_font = CreateFontIndirect (&menu_logfont);
4823 old_font = SelectObject (hdc, menu_font);
4824
4825 /* Always draw title as if not selected. */
4826 ExtTextOut (hdc,
4827 pDis->rcItem.left
4828 + GetSystemMetrics (SM_CXMENUCHECK),
4829 pDis->rcItem.top,
4830 ETO_OPAQUE, &pDis->rcItem,
4831 title, strlen (title), NULL);
4832
4833 SelectObject (hdc, old_font);
4834 DeleteObject (menu_font);
4835 }
4836 return TRUE;
4837 }
4838 }
4839 return 0;
4840
4841 #if 0
4842 /* Still not right - can't distinguish between clicks in the
4843 client area of the frame from clicks forwarded from the scroll
4844 bars - may have to hook WM_NCHITTEST to remember the mouse
4845 position and then check if it is in the client area ourselves. */
4846 case WM_MOUSEACTIVATE:
4847 /* Discard the mouse click that activates a frame, allowing the
4848 user to click anywhere without changing point (or worse!).
4849 Don't eat mouse clicks on scrollbars though!! */
4850 if (LOWORD (lParam) == HTCLIENT )
4851 return MA_ACTIVATEANDEAT;
4852 goto dflt;
4853 #endif
4854
4855 case WM_MOUSELEAVE:
4856 /* No longer tracking mouse. */
4857 track_mouse_window = NULL;
4858
4859 case WM_ACTIVATEAPP:
4860 case WM_ACTIVATE:
4861 case WM_WINDOWPOSCHANGED:
4862 case WM_SHOWWINDOW:
4863 /* Inform lisp thread that a frame might have just been obscured
4864 or exposed, so should recheck visibility of all frames. */
4865 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4866 goto dflt;
4867
4868 case WM_SETFOCUS:
4869 dpyinfo->faked_key = 0;
4870 reset_modifiers ();
4871 register_hot_keys (hwnd);
4872 goto command;
4873 case WM_KILLFOCUS:
4874 unregister_hot_keys (hwnd);
4875 button_state = 0;
4876 ReleaseCapture ();
4877 /* Relinquish the system caret. */
4878 if (w32_system_caret_hwnd)
4879 {
4880 w32_visible_system_caret_hwnd = NULL;
4881 w32_system_caret_hwnd = NULL;
4882 DestroyCaret ();
4883 }
4884 case WM_MOVE:
4885 case WM_SIZE:
4886 case WM_COMMAND:
4887 command:
4888 wmsg.dwModifiers = w32_get_modifiers ();
4889 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4890 goto dflt;
4891
4892 case WM_CLOSE:
4893 wmsg.dwModifiers = w32_get_modifiers ();
4894 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4895 return 0;
4896
4897 case WM_WINDOWPOSCHANGING:
4898 /* Don't restrict the sizing of tip frames. */
4899 if (hwnd == tip_window)
4900 return 0;
4901 {
4902 WINDOWPLACEMENT wp;
4903 LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
4904
4905 wp.length = sizeof (WINDOWPLACEMENT);
4906 GetWindowPlacement (hwnd, &wp);
4907
4908 if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0)
4909 {
4910 RECT rect;
4911 int wdiff;
4912 int hdiff;
4913 DWORD font_width;
4914 DWORD line_height;
4915 DWORD internal_border;
4916 DWORD scrollbar_extra;
4917 RECT wr;
4918
4919 wp.length = sizeof(wp);
4920 GetWindowRect (hwnd, &wr);
4921
4922 enter_crit ();
4923
4924 font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
4925 line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
4926 internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
4927 scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
4928
4929 leave_crit ();
4930
4931 memset (&rect, 0, sizeof (rect));
4932 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
4933 GetMenu (hwnd) != NULL);
4934
4935 /* Force width and height of client area to be exact
4936 multiples of the character cell dimensions. */
4937 wdiff = (lppos->cx - (rect.right - rect.left)
4938 - 2 * internal_border - scrollbar_extra)
4939 % font_width;
4940 hdiff = (lppos->cy - (rect.bottom - rect.top)
4941 - 2 * internal_border)
4942 % line_height;
4943
4944 if (wdiff || hdiff)
4945 {
4946 /* For right/bottom sizing we can just fix the sizes.
4947 However for top/left sizing we will need to fix the X
4948 and Y positions as well. */
4949
4950 lppos->cx -= wdiff;
4951 lppos->cy -= hdiff;
4952
4953 if (wp.showCmd != SW_SHOWMAXIMIZED
4954 && (lppos->flags & SWP_NOMOVE) == 0)
4955 {
4956 if (lppos->x != wr.left || lppos->y != wr.top)
4957 {
4958 lppos->x += wdiff;
4959 lppos->y += hdiff;
4960 }
4961 else
4962 {
4963 lppos->flags |= SWP_NOMOVE;
4964 }
4965 }
4966
4967 return 0;
4968 }
4969 }
4970 }
4971
4972 goto dflt;
4973
4974 case WM_GETMINMAXINFO:
4975 /* Hack to correct bug that allows Emacs frames to be resized
4976 below the Minimum Tracking Size. */
4977 ((LPMINMAXINFO) lParam)->ptMinTrackSize.y++;
4978 /* Hack to allow resizing the Emacs frame above the screen size.
4979 Note that Windows 9x limits coordinates to 16-bits. */
4980 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767;
4981 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767;
4982 return 0;
4983
4984 case WM_EMACS_CREATESCROLLBAR:
4985 return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
4986 (struct scroll_bar *) lParam);
4987
4988 case WM_EMACS_SHOWWINDOW:
4989 return ShowWindow ((HWND) wParam, (WPARAM) lParam);
4990
4991 case WM_EMACS_SETFOREGROUND:
4992 {
4993 HWND foreground_window;
4994 DWORD foreground_thread, retval;
4995
4996 /* On NT 5.0, and apparently Windows 98, it is necessary to
4997 attach to the thread that currently has focus in order to
4998 pull the focus away from it. */
4999 foreground_window = GetForegroundWindow ();
5000 foreground_thread = GetWindowThreadProcessId (foreground_window, NULL);
5001 if (!foreground_window
5002 || foreground_thread == GetCurrentThreadId ()
5003 || !AttachThreadInput (GetCurrentThreadId (),
5004 foreground_thread, TRUE))
5005 foreground_thread = 0;
5006
5007 retval = SetForegroundWindow ((HWND) wParam);
5008
5009 /* Detach from the previous foreground thread. */
5010 if (foreground_thread)
5011 AttachThreadInput (GetCurrentThreadId (),
5012 foreground_thread, FALSE);
5013
5014 return retval;
5015 }
5016
5017 case WM_EMACS_SETWINDOWPOS:
5018 {
5019 WINDOWPOS * pos = (WINDOWPOS *) wParam;
5020 return SetWindowPos (hwnd, pos->hwndInsertAfter,
5021 pos->x, pos->y, pos->cx, pos->cy, pos->flags);
5022 }
5023
5024 case WM_EMACS_DESTROYWINDOW:
5025 DragAcceptFiles ((HWND) wParam, FALSE);
5026 return DestroyWindow ((HWND) wParam);
5027
5028 case WM_EMACS_HIDE_CARET:
5029 return HideCaret (hwnd);
5030
5031 case WM_EMACS_SHOW_CARET:
5032 return ShowCaret (hwnd);
5033
5034 case WM_EMACS_DESTROY_CARET:
5035 w32_system_caret_hwnd = NULL;
5036 w32_visible_system_caret_hwnd = NULL;
5037 return DestroyCaret ();
5038
5039 case WM_EMACS_TRACK_CARET:
5040 /* If there is currently no system caret, create one. */
5041 if (w32_system_caret_hwnd == NULL)
5042 {
5043 /* Use the default caret width, and avoid changing it
5044 unneccesarily, as it confuses screen reader software. */
5045 w32_system_caret_hwnd = hwnd;
5046 CreateCaret (hwnd, NULL, 0,
5047 w32_system_caret_height);
5048 }
5049
5050 if (!SetCaretPos (w32_system_caret_x, w32_system_caret_y))
5051 return 0;
5052 /* Ensure visible caret gets turned on when requested. */
5053 else if (w32_use_visible_system_caret
5054 && w32_visible_system_caret_hwnd != hwnd)
5055 {
5056 w32_visible_system_caret_hwnd = hwnd;
5057 return ShowCaret (hwnd);
5058 }
5059 /* Ensure visible caret gets turned off when requested. */
5060 else if (!w32_use_visible_system_caret
5061 && w32_visible_system_caret_hwnd)
5062 {
5063 w32_visible_system_caret_hwnd = NULL;
5064 return HideCaret (hwnd);
5065 }
5066 else
5067 return 1;
5068
5069 case WM_EMACS_TRACKPOPUPMENU:
5070 {
5071 UINT flags;
5072 POINT *pos;
5073 int retval;
5074 pos = (POINT *)lParam;
5075 flags = TPM_CENTERALIGN;
5076 if (button_state & LMOUSE)
5077 flags |= TPM_LEFTBUTTON;
5078 else if (button_state & RMOUSE)
5079 flags |= TPM_RIGHTBUTTON;
5080
5081 /* Remember we did a SetCapture on the initial mouse down event,
5082 so for safety, we make sure the capture is cancelled now. */
5083 ReleaseCapture ();
5084 button_state = 0;
5085
5086 /* Use menubar_active to indicate that WM_INITMENU is from
5087 TrackPopupMenu below, and should be ignored. */
5088 f = x_window_to_frame (dpyinfo, hwnd);
5089 if (f)
5090 f->output_data.w32->menubar_active = 1;
5091
5092 if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
5093 0, hwnd, NULL))
5094 {
5095 MSG amsg;
5096 /* Eat any mouse messages during popupmenu */
5097 while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
5098 PM_REMOVE));
5099 /* Get the menu selection, if any */
5100 if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE))
5101 {
5102 retval = LOWORD (amsg.wParam);
5103 }
5104 else
5105 {
5106 retval = 0;
5107 }
5108 }
5109 else
5110 {
5111 retval = -1;
5112 }
5113
5114 return retval;
5115 }
5116
5117 default:
5118 /* Check for messages registered at runtime. */
5119 if (msg == msh_mousewheel)
5120 {
5121 wmsg.dwModifiers = w32_get_modifiers ();
5122 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
5123 return 0;
5124 }
5125
5126 dflt:
5127 return DefWindowProc (hwnd, msg, wParam, lParam);
5128 }
5129
5130
5131 /* The most common default return code for handled messages is 0. */
5132 return 0;
5133 }
5134
5135 void
5136 my_create_window (f)
5137 struct frame * f;
5138 {
5139 MSG msg;
5140
5141 if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
5142 abort ();
5143 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
5144 }
5145
5146
5147 /* Create a tooltip window. Unlike my_create_window, we do not do this
5148 indirectly via the Window thread, as we do not need to process Window
5149 messages for the tooltip. Creating tooltips indirectly also creates
5150 deadlocks when tooltips are created for menu items. */
5151 void
5152 my_create_tip_window (f)
5153 struct frame *f;
5154 {
5155 RECT rect;
5156
5157 rect.left = rect.top = 0;
5158 rect.right = PIXEL_WIDTH (f);
5159 rect.bottom = PIXEL_HEIGHT (f);
5160
5161 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
5162 FRAME_EXTERNAL_MENU_BAR (f));
5163
5164 tip_window = FRAME_W32_WINDOW (f)
5165 = CreateWindow (EMACS_CLASS,
5166 f->namebuf,
5167 f->output_data.w32->dwStyle,
5168 f->output_data.w32->left_pos,
5169 f->output_data.w32->top_pos,
5170 rect.right - rect.left,
5171 rect.bottom - rect.top,
5172 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
5173 NULL,
5174 hinst,
5175 NULL);
5176
5177 if (tip_window)
5178 {
5179 SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
5180 SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
5181 SetWindowLong (tip_window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
5182 SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
5183
5184 /* Tip frames have no scrollbars. */
5185 SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
5186
5187 /* Do this to discard the default setting specified by our parent. */
5188 ShowWindow (tip_window, SW_HIDE);
5189 }
5190 }
5191
5192
5193 /* Create and set up the w32 window for frame F. */
5194
5195 static void
5196 w32_window (f, window_prompting, minibuffer_only)
5197 struct frame *f;
5198 long window_prompting;
5199 int minibuffer_only;
5200 {
5201 BLOCK_INPUT;
5202
5203 /* Use the resource name as the top-level window name
5204 for looking up resources. Make a non-Lisp copy
5205 for the window manager, so GC relocation won't bother it.
5206
5207 Elsewhere we specify the window name for the window manager. */
5208
5209 {
5210 char *str = (char *) XSTRING (Vx_resource_name)->data;
5211 f->namebuf = (char *) xmalloc (strlen (str) + 1);
5212 strcpy (f->namebuf, str);
5213 }
5214
5215 my_create_window (f);
5216
5217 validate_x_resource_name ();
5218
5219 /* x_set_name normally ignores requests to set the name if the
5220 requested name is the same as the current name. This is the one
5221 place where that assumption isn't correct; f->name is set, but
5222 the server hasn't been told. */
5223 {
5224 Lisp_Object name;
5225 int explicit = f->explicit_name;
5226
5227 f->explicit_name = 0;
5228 name = f->name;
5229 f->name = Qnil;
5230 x_set_name (f, name, explicit);
5231 }
5232
5233 UNBLOCK_INPUT;
5234
5235 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
5236 initialize_frame_menubar (f);
5237
5238 if (FRAME_W32_WINDOW (f) == 0)
5239 error ("Unable to create window");
5240 }
5241
5242 /* Handle the icon stuff for this window. Perhaps later we might
5243 want an x_set_icon_position which can be called interactively as
5244 well. */
5245
5246 static void
5247 x_icon (f, parms)
5248 struct frame *f;
5249 Lisp_Object parms;
5250 {
5251 Lisp_Object icon_x, icon_y;
5252
5253 /* Set the position of the icon. Note that Windows 95 groups all
5254 icons in the tray. */
5255 icon_x = w32_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
5256 icon_y = w32_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
5257 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
5258 {
5259 CHECK_NUMBER (icon_x);
5260 CHECK_NUMBER (icon_y);
5261 }
5262 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
5263 error ("Both left and top icon corners of icon must be specified");
5264
5265 BLOCK_INPUT;
5266
5267 if (! EQ (icon_x, Qunbound))
5268 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
5269
5270 #if 0 /* TODO */
5271 /* Start up iconic or window? */
5272 x_wm_set_window_state
5273 (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
5274 ? IconicState
5275 : NormalState));
5276
5277 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
5278 ? f->icon_name
5279 : f->name))->data);
5280 #endif
5281
5282 UNBLOCK_INPUT;
5283 }
5284
5285
5286 static void
5287 x_make_gc (f)
5288 struct frame *f;
5289 {
5290 XGCValues gc_values;
5291
5292 BLOCK_INPUT;
5293
5294 /* Create the GC's of this frame.
5295 Note that many default values are used. */
5296
5297 /* Normal video */
5298 gc_values.font = f->output_data.w32->font;
5299
5300 /* Cursor has cursor-color background, background-color foreground. */
5301 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
5302 gc_values.background = f->output_data.w32->cursor_pixel;
5303 f->output_data.w32->cursor_gc
5304 = XCreateGC (NULL, FRAME_W32_WINDOW (f),
5305 (GCFont | GCForeground | GCBackground),
5306 &gc_values);
5307
5308 /* Reliefs. */
5309 f->output_data.w32->white_relief.gc = 0;
5310 f->output_data.w32->black_relief.gc = 0;
5311
5312 UNBLOCK_INPUT;
5313 }
5314
5315
5316 /* Handler for signals raised during x_create_frame and
5317 x_create_top_frame. FRAME is the frame which is partially
5318 constructed. */
5319
5320 static Lisp_Object
5321 unwind_create_frame (frame)
5322 Lisp_Object frame;
5323 {
5324 struct frame *f = XFRAME (frame);
5325
5326 /* If frame is ``official'', nothing to do. */
5327 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
5328 {
5329 #ifdef GLYPH_DEBUG
5330 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5331 #endif
5332
5333 x_free_frame_resources (f);
5334
5335 /* Check that reference counts are indeed correct. */
5336 xassert (dpyinfo->reference_count == dpyinfo_refcount);
5337 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
5338
5339 return Qt;
5340 }
5341
5342 return Qnil;
5343 }
5344
5345
5346 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
5347 1, 1, 0,
5348 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
5349 Returns an Emacs frame object.
5350 ALIST is an alist of frame parameters.
5351 If the parameters specify that the frame should not have a minibuffer,
5352 and do not specify a specific minibuffer window to use,
5353 then `default-minibuffer-frame' must be a frame whose minibuffer can
5354 be shared by the new frame.
5355
5356 This function is an internal primitive--use `make-frame' instead. */)
5357 (parms)
5358 Lisp_Object parms;
5359 {
5360 struct frame *f;
5361 Lisp_Object frame, tem;
5362 Lisp_Object name;
5363 int minibuffer_only = 0;
5364 long window_prompting = 0;
5365 int width, height;
5366 int count = BINDING_STACK_SIZE ();
5367 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5368 Lisp_Object display;
5369 struct w32_display_info *dpyinfo = NULL;
5370 Lisp_Object parent;
5371 struct kboard *kb;
5372
5373 check_w32 ();
5374
5375 /* Use this general default value to start with
5376 until we know if this frame has a specified name. */
5377 Vx_resource_name = Vinvocation_name;
5378
5379 display = w32_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
5380 if (EQ (display, Qunbound))
5381 display = Qnil;
5382 dpyinfo = check_x_display_info (display);
5383 #ifdef MULTI_KBOARD
5384 kb = dpyinfo->kboard;
5385 #else
5386 kb = &the_only_kboard;
5387 #endif
5388
5389 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
5390 if (!STRINGP (name)
5391 && ! EQ (name, Qunbound)
5392 && ! NILP (name))
5393 error ("Invalid frame name--not a string or nil");
5394
5395 if (STRINGP (name))
5396 Vx_resource_name = name;
5397
5398 /* See if parent window is specified. */
5399 parent = w32_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
5400 if (EQ (parent, Qunbound))
5401 parent = Qnil;
5402 if (! NILP (parent))
5403 CHECK_NUMBER (parent);
5404
5405 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
5406 /* No need to protect DISPLAY because that's not used after passing
5407 it to make_frame_without_minibuffer. */
5408 frame = Qnil;
5409 GCPRO4 (parms, parent, name, frame);
5410 tem = w32_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
5411 RES_TYPE_SYMBOL);
5412 if (EQ (tem, Qnone) || NILP (tem))
5413 f = make_frame_without_minibuffer (Qnil, kb, display);
5414 else if (EQ (tem, Qonly))
5415 {
5416 f = make_minibuffer_frame ();
5417 minibuffer_only = 1;
5418 }
5419 else if (WINDOWP (tem))
5420 f = make_frame_without_minibuffer (tem, kb, display);
5421 else
5422 f = make_frame (1);
5423
5424 XSETFRAME (frame, f);
5425
5426 /* Note that Windows does support scroll bars. */
5427 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
5428 /* By default, make scrollbars the system standard width. */
5429 f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL);
5430
5431 f->output_method = output_w32;
5432 f->output_data.w32 =
5433 (struct w32_output *) xmalloc (sizeof (struct w32_output));
5434 bzero (f->output_data.w32, sizeof (struct w32_output));
5435 FRAME_FONTSET (f) = -1;
5436 record_unwind_protect (unwind_create_frame, frame);
5437
5438 f->icon_name
5439 = w32_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
5440 if (! STRINGP (f->icon_name))
5441 f->icon_name = Qnil;
5442
5443 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
5444 #ifdef MULTI_KBOARD
5445 FRAME_KBOARD (f) = kb;
5446 #endif
5447
5448 /* Specify the parent under which to make this window. */
5449
5450 if (!NILP (parent))
5451 {
5452 f->output_data.w32->parent_desc = (Window) XFASTINT (parent);
5453 f->output_data.w32->explicit_parent = 1;
5454 }
5455 else
5456 {
5457 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5458 f->output_data.w32->explicit_parent = 0;
5459 }
5460
5461 /* Set the name; the functions to which we pass f expect the name to
5462 be set. */
5463 if (EQ (name, Qunbound) || NILP (name))
5464 {
5465 f->name = build_string (dpyinfo->w32_id_name);
5466 f->explicit_name = 0;
5467 }
5468 else
5469 {
5470 f->name = name;
5471 f->explicit_name = 1;
5472 /* use the frame's title when getting resources for this frame. */
5473 specbind (Qx_resource_name, name);
5474 }
5475
5476 /* Extract the window parameters from the supplied values
5477 that are needed to determine window geometry. */
5478 {
5479 Lisp_Object font;
5480
5481 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
5482
5483 BLOCK_INPUT;
5484 /* First, try whatever font the caller has specified. */
5485 if (STRINGP (font))
5486 {
5487 tem = Fquery_fontset (font, Qnil);
5488 if (STRINGP (tem))
5489 font = x_new_fontset (f, XSTRING (tem)->data);
5490 else
5491 font = x_new_font (f, XSTRING (font)->data);
5492 }
5493 /* Try out a font which we hope has bold and italic variations. */
5494 if (!STRINGP (font))
5495 font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
5496 if (! STRINGP (font))
5497 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
5498 /* If those didn't work, look for something which will at least work. */
5499 if (! STRINGP (font))
5500 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
5501 UNBLOCK_INPUT;
5502 if (! STRINGP (font))
5503 font = build_string ("Fixedsys");
5504
5505 x_default_parameter (f, parms, Qfont, font,
5506 "font", "Font", RES_TYPE_STRING);
5507 }
5508
5509 x_default_parameter (f, parms, Qborder_width, make_number (2),
5510 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
5511 /* This defaults to 2 in order to match xterm. We recognize either
5512 internalBorderWidth or internalBorder (which is what xterm calls
5513 it). */
5514 if (NILP (Fassq (Qinternal_border_width, parms)))
5515 {
5516 Lisp_Object value;
5517
5518 value = w32_get_arg (parms, Qinternal_border_width,
5519 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
5520 if (! EQ (value, Qunbound))
5521 parms = Fcons (Fcons (Qinternal_border_width, value),
5522 parms);
5523 }
5524 /* Default internalBorderWidth to 0 on Windows to match other programs. */
5525 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
5526 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
5527 x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
5528 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
5529
5530 /* Also do the stuff which must be set before the window exists. */
5531 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5532 "foreground", "Foreground", RES_TYPE_STRING);
5533 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5534 "background", "Background", RES_TYPE_STRING);
5535 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5536 "pointerColor", "Foreground", RES_TYPE_STRING);
5537 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
5538 "cursorColor", "Foreground", RES_TYPE_STRING);
5539 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5540 "borderColor", "BorderColor", RES_TYPE_STRING);
5541 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
5542 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
5543 x_default_parameter (f, parms, Qline_spacing, Qnil,
5544 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
5545 x_default_parameter (f, parms, Qleft_fringe, Qnil,
5546 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
5547 x_default_parameter (f, parms, Qright_fringe, Qnil,
5548 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
5549
5550
5551 /* Init faces before x_default_parameter is called for scroll-bar
5552 parameters because that function calls x_set_scroll_bar_width,
5553 which calls change_frame_size, which calls Fset_window_buffer,
5554 which runs hooks, which call Fvertical_motion. At the end, we
5555 end up in init_iterator with a null face cache, which should not
5556 happen. */
5557 init_frame_faces (f);
5558
5559 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
5560 "menuBar", "MenuBar", RES_TYPE_NUMBER);
5561 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
5562 "toolBar", "ToolBar", RES_TYPE_NUMBER);
5563 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
5564 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
5565 x_default_parameter (f, parms, Qtitle, Qnil,
5566 "title", "Title", RES_TYPE_STRING);
5567
5568 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
5569 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5570
5571 /* Add the tool-bar height to the initial frame height so that the
5572 user gets a text display area of the size he specified with -g or
5573 via .Xdefaults. Later changes of the tool-bar height don't
5574 change the frame size. This is done so that users can create
5575 tall Emacs frames without having to guess how tall the tool-bar
5576 will get. */
5577 if (FRAME_TOOL_BAR_LINES (f))
5578 {
5579 int margin, relief, bar_height;
5580
5581 relief = (tool_bar_button_relief >= 0
5582 ? tool_bar_button_relief
5583 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
5584
5585 if (INTEGERP (Vtool_bar_button_margin)
5586 && XINT (Vtool_bar_button_margin) > 0)
5587 margin = XFASTINT (Vtool_bar_button_margin);
5588 else if (CONSP (Vtool_bar_button_margin)
5589 && INTEGERP (XCDR (Vtool_bar_button_margin))
5590 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
5591 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
5592 else
5593 margin = 0;
5594
5595 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5596 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
5597 }
5598
5599 window_prompting = x_figure_window_size (f, parms);
5600
5601 if (window_prompting & XNegative)
5602 {
5603 if (window_prompting & YNegative)
5604 f->output_data.w32->win_gravity = SouthEastGravity;
5605 else
5606 f->output_data.w32->win_gravity = NorthEastGravity;
5607 }
5608 else
5609 {
5610 if (window_prompting & YNegative)
5611 f->output_data.w32->win_gravity = SouthWestGravity;
5612 else
5613 f->output_data.w32->win_gravity = NorthWestGravity;
5614 }
5615
5616 f->output_data.w32->size_hint_flags = window_prompting;
5617
5618 tem = w32_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
5619 f->no_split = minibuffer_only || EQ (tem, Qt);
5620
5621 w32_window (f, window_prompting, minibuffer_only);
5622 x_icon (f, parms);
5623
5624 x_make_gc (f);
5625
5626 /* Now consider the frame official. */
5627 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
5628 Vframe_list = Fcons (frame, Vframe_list);
5629
5630 /* We need to do this after creating the window, so that the
5631 icon-creation functions can say whose icon they're describing. */
5632 x_default_parameter (f, parms, Qicon_type, Qnil,
5633 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
5634
5635 x_default_parameter (f, parms, Qauto_raise, Qnil,
5636 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5637 x_default_parameter (f, parms, Qauto_lower, Qnil,
5638 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5639 x_default_parameter (f, parms, Qcursor_type, Qbox,
5640 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5641 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
5642 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
5643
5644 /* Dimensions, especially f->height, must be done via change_frame_size.
5645 Change will not be effected unless different from the current
5646 f->height. */
5647 width = f->width;
5648 height = f->height;
5649
5650 f->height = 0;
5651 SET_FRAME_WIDTH (f, 0);
5652 change_frame_size (f, height, width, 1, 0, 0);
5653
5654 /* Tell the server what size and position, etc, we want, and how
5655 badly we want them. This should be done after we have the menu
5656 bar so that its size can be taken into account. */
5657 BLOCK_INPUT;
5658 x_wm_set_size_hint (f, window_prompting, 0);
5659 UNBLOCK_INPUT;
5660
5661 /* Avoid a bug that causes the new frame to never become visible if
5662 an echo area message is displayed during the following call1. */
5663 specbind(Qredisplay_dont_pause, Qt);
5664
5665 /* Set up faces after all frame parameters are known. This call
5666 also merges in face attributes specified for new frames. If we
5667 don't do this, the `menu' face for instance won't have the right
5668 colors, and the menu bar won't appear in the specified colors for
5669 new frames. */
5670 call1 (Qface_set_after_frame_default, frame);
5671
5672 /* Make the window appear on the frame and enable display, unless
5673 the caller says not to. However, with explicit parent, Emacs
5674 cannot control visibility, so don't try. */
5675 if (! f->output_data.w32->explicit_parent)
5676 {
5677 Lisp_Object visibility;
5678
5679 visibility = w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
5680 if (EQ (visibility, Qunbound))
5681 visibility = Qt;
5682
5683 if (EQ (visibility, Qicon))
5684 x_iconify_frame (f);
5685 else if (! NILP (visibility))
5686 x_make_frame_visible (f);
5687 else
5688 /* Must have been Qnil. */
5689 ;
5690 }
5691 UNGCPRO;
5692
5693 /* Make sure windows on this frame appear in calls to next-window
5694 and similar functions. */
5695 Vwindow_list = Qnil;
5696
5697 return unbind_to (count, frame);
5698 }
5699
5700 /* FRAME is used only to get a handle on the X display. We don't pass the
5701 display info directly because we're called from frame.c, which doesn't
5702 know about that structure. */
5703 Lisp_Object
5704 x_get_focus_frame (frame)
5705 struct frame *frame;
5706 {
5707 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
5708 Lisp_Object xfocus;
5709 if (! dpyinfo->w32_focus_frame)
5710 return Qnil;
5711
5712 XSETFRAME (xfocus, dpyinfo->w32_focus_frame);
5713 return xfocus;
5714 }
5715
5716 DEFUN ("w32-focus-frame", Fw32_focus_frame, Sw32_focus_frame, 1, 1, 0,
5717 doc: /* Give FRAME input focus, raising to foreground if necessary. */)
5718 (frame)
5719 Lisp_Object frame;
5720 {
5721 x_focus_on_frame (check_x_frame (frame));
5722 return Qnil;
5723 }
5724
5725 \f
5726 /* Return the charset portion of a font name. */
5727 char * xlfd_charset_of_font (char * fontname)
5728 {
5729 char *charset, *encoding;
5730
5731 encoding = strrchr(fontname, '-');
5732 if (!encoding || encoding == fontname)
5733 return NULL;
5734
5735 for (charset = encoding - 1; charset >= fontname; charset--)
5736 if (*charset == '-')
5737 break;
5738
5739 if (charset == fontname || strcmp(charset, "-*-*") == 0)
5740 return NULL;
5741
5742 return charset + 1;
5743 }
5744
5745 struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
5746 int size, char* filename);
5747 static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names);
5748 static BOOL w32_to_x_font (LOGFONT * lplf, char * lpxstr, int len,
5749 char * charset);
5750 static BOOL x_to_w32_font (char *lpxstr, LOGFONT *lplogfont);
5751
5752 static struct font_info *
5753 w32_load_system_font (f,fontname,size)
5754 struct frame *f;
5755 char * fontname;
5756 int size;
5757 {
5758 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5759 Lisp_Object font_names;
5760
5761 /* Get a list of all the fonts that match this name. Once we
5762 have a list of matching fonts, we compare them against the fonts
5763 we already have loaded by comparing names. */
5764 font_names = w32_list_fonts (f, build_string (fontname), size, 100);
5765
5766 if (!NILP (font_names))
5767 {
5768 Lisp_Object tail;
5769 int i;
5770
5771 /* First check if any are already loaded, as that is cheaper
5772 than loading another one. */
5773 for (i = 0; i < dpyinfo->n_fonts; i++)
5774 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
5775 if (dpyinfo->font_table[i].name
5776 && (!strcmp (dpyinfo->font_table[i].name,
5777 XSTRING (XCAR (tail))->data)
5778 || !strcmp (dpyinfo->font_table[i].full_name,
5779 XSTRING (XCAR (tail))->data)))
5780 return (dpyinfo->font_table + i);
5781
5782 fontname = (char *) XSTRING (XCAR (font_names))->data;
5783 }
5784 else if (w32_strict_fontnames)
5785 {
5786 /* If EnumFontFamiliesEx was available, we got a full list of
5787 fonts back so stop now to avoid the possibility of loading a
5788 random font. If we had to fall back to EnumFontFamilies, the
5789 list is incomplete, so continue whether the font we want was
5790 listed or not. */
5791 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
5792 FARPROC enum_font_families_ex
5793 = GetProcAddress (gdi32, "EnumFontFamiliesExA");
5794 if (enum_font_families_ex)
5795 return NULL;
5796 }
5797
5798 /* Load the font and add it to the table. */
5799 {
5800 char *full_name, *encoding, *charset;
5801 XFontStruct *font;
5802 struct font_info *fontp;
5803 LOGFONT lf;
5804 BOOL ok;
5805 int codepage;
5806 int i;
5807
5808 if (!fontname || !x_to_w32_font (fontname, &lf))
5809 return (NULL);
5810
5811 if (!*lf.lfFaceName)
5812 /* If no name was specified for the font, we get a random font
5813 from CreateFontIndirect - this is not particularly
5814 desirable, especially since CreateFontIndirect does not
5815 fill out the missing name in lf, so we never know what we
5816 ended up with. */
5817 return NULL;
5818
5819 /* Specify anti-aliasing to prevent Cleartype fonts being used,
5820 since those fonts leave garbage behind. */
5821 lf.lfQuality = ANTIALIASED_QUALITY;
5822
5823 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
5824 bzero (font, sizeof (*font));
5825
5826 /* Set bdf to NULL to indicate that this is a Windows font. */
5827 font->bdf = NULL;
5828
5829 BLOCK_INPUT;
5830
5831 font->hfont = CreateFontIndirect (&lf);
5832
5833 if (font->hfont == NULL)
5834 {
5835 ok = FALSE;
5836 }
5837 else
5838 {
5839 HDC hdc;
5840 HANDLE oldobj;
5841
5842 codepage = w32_codepage_for_font (fontname);
5843
5844 hdc = GetDC (dpyinfo->root_window);
5845 oldobj = SelectObject (hdc, font->hfont);
5846
5847 ok = GetTextMetrics (hdc, &font->tm);
5848 if (codepage == CP_UNICODE)
5849 font->double_byte_p = 1;
5850 else
5851 {
5852 /* Unfortunately, some fonts (eg. MingLiU, a big5 ttf font)
5853 don't report themselves as double byte fonts, when
5854 patently they are. So instead of trusting
5855 GetFontLanguageInfo, we check the properties of the
5856 codepage directly, since that is ultimately what we are
5857 working from anyway. */
5858 /* font->double_byte_p = GetFontLanguageInfo(hdc) & GCP_DBCS; */
5859 CPINFO cpi = {0};
5860 GetCPInfo (codepage, &cpi);
5861 font->double_byte_p = cpi.MaxCharSize > 1;
5862 }
5863
5864 SelectObject (hdc, oldobj);
5865 ReleaseDC (dpyinfo->root_window, hdc);
5866 /* Fill out details in lf according to the font that was
5867 actually loaded. */
5868 lf.lfHeight = font->tm.tmInternalLeading - font->tm.tmHeight;
5869 lf.lfWidth = font->tm.tmAveCharWidth;
5870 lf.lfWeight = font->tm.tmWeight;
5871 lf.lfItalic = font->tm.tmItalic;
5872 lf.lfCharSet = font->tm.tmCharSet;
5873 lf.lfPitchAndFamily = ((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
5874 ? VARIABLE_PITCH : FIXED_PITCH);
5875 lf.lfOutPrecision = ((font->tm.tmPitchAndFamily & TMPF_VECTOR)
5876 ? OUT_STROKE_PRECIS : OUT_STRING_PRECIS);
5877
5878 w32_cache_char_metrics (font);
5879 }
5880
5881 UNBLOCK_INPUT;
5882
5883 if (!ok)
5884 {
5885 w32_unload_font (dpyinfo, font);
5886 return (NULL);
5887 }
5888
5889 /* Find a free slot in the font table. */
5890 for (i = 0; i < dpyinfo->n_fonts; ++i)
5891 if (dpyinfo->font_table[i].name == NULL)
5892 break;
5893
5894 /* If no free slot found, maybe enlarge the font table. */
5895 if (i == dpyinfo->n_fonts
5896 && dpyinfo->n_fonts == dpyinfo->font_table_size)
5897 {
5898 int sz;
5899 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
5900 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
5901 dpyinfo->font_table
5902 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
5903 }
5904
5905 fontp = dpyinfo->font_table + i;
5906 if (i == dpyinfo->n_fonts)
5907 ++dpyinfo->n_fonts;
5908
5909 /* Now fill in the slots of *FONTP. */
5910 BLOCK_INPUT;
5911 fontp->font = font;
5912 fontp->font_idx = i;
5913 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
5914 bcopy (fontname, fontp->name, strlen (fontname) + 1);
5915
5916 charset = xlfd_charset_of_font (fontname);
5917
5918 /* Cache the W32 codepage for a font. This makes w32_encode_char
5919 (called for every glyph during redisplay) much faster. */
5920 fontp->codepage = codepage;
5921
5922 /* Work out the font's full name. */
5923 full_name = (char *)xmalloc (100);
5924 if (full_name && w32_to_x_font (&lf, full_name, 100, charset))
5925 fontp->full_name = full_name;
5926 else
5927 {
5928 /* If all else fails - just use the name we used to load it. */
5929 xfree (full_name);
5930 fontp->full_name = fontp->name;
5931 }
5932
5933 fontp->size = FONT_WIDTH (font);
5934 fontp->height = FONT_HEIGHT (font);
5935
5936 /* The slot `encoding' specifies how to map a character
5937 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
5938 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
5939 (0:0x20..0x7F, 1:0xA0..0xFF,
5940 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
5941 2:0xA020..0xFF7F). For the moment, we don't know which charset
5942 uses this font. So, we set information in fontp->encoding[1]
5943 which is never used by any charset. If mapping can't be
5944 decided, set FONT_ENCODING_NOT_DECIDED. */
5945
5946 /* SJIS fonts need to be set to type 4, all others seem to work as
5947 type FONT_ENCODING_NOT_DECIDED. */
5948 encoding = strrchr (fontp->name, '-');
5949 if (encoding && strnicmp (encoding+1, "sjis", 4) == 0)
5950 fontp->encoding[1] = 4;
5951 else
5952 fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
5953
5954 /* The following three values are set to 0 under W32, which is
5955 what they get set to if XGetFontProperty fails under X. */
5956 fontp->baseline_offset = 0;
5957 fontp->relative_compose = 0;
5958 fontp->default_ascent = 0;
5959
5960 /* Set global flag fonts_changed_p to non-zero if the font loaded
5961 has a character with a smaller width than any other character
5962 before, or if the font loaded has a smalle>r height than any
5963 other font loaded before. If this happens, it will make a
5964 glyph matrix reallocation necessary. */
5965 fonts_changed_p = x_compute_min_glyph_bounds (f);
5966 UNBLOCK_INPUT;
5967 return fontp;
5968 }
5969 }
5970
5971 /* Load font named FONTNAME of size SIZE for frame F, and return a
5972 pointer to the structure font_info while allocating it dynamically.
5973 If loading fails, return NULL. */
5974 struct font_info *
5975 w32_load_font (f,fontname,size)
5976 struct frame *f;
5977 char * fontname;
5978 int size;
5979 {
5980 Lisp_Object bdf_fonts;
5981 struct font_info *retval = NULL;
5982
5983 bdf_fonts = w32_list_bdf_fonts (build_string (fontname), 1);
5984
5985 while (!retval && CONSP (bdf_fonts))
5986 {
5987 char *bdf_name, *bdf_file;
5988 Lisp_Object bdf_pair;
5989
5990 bdf_name = XSTRING (XCAR (bdf_fonts))->data;
5991 bdf_pair = Fassoc (XCAR (bdf_fonts), Vw32_bdf_filename_alist);
5992 bdf_file = XSTRING (XCDR (bdf_pair))->data;
5993
5994 retval = w32_load_bdf_font (f, bdf_name, size, bdf_file);
5995
5996 bdf_fonts = XCDR (bdf_fonts);
5997 }
5998
5999 if (retval)
6000 return retval;
6001
6002 return w32_load_system_font(f, fontname, size);
6003 }
6004
6005
6006 void
6007 w32_unload_font (dpyinfo, font)
6008 struct w32_display_info *dpyinfo;
6009 XFontStruct * font;
6010 {
6011 if (font)
6012 {
6013 if (font->per_char) xfree (font->per_char);
6014 if (font->bdf) w32_free_bdf_font (font->bdf);
6015
6016 if (font->hfont) DeleteObject(font->hfont);
6017 xfree (font);
6018 }
6019 }
6020
6021 /* The font conversion stuff between x and w32 */
6022
6023 /* X font string is as follows (from faces.el)
6024 * (let ((- "[-?]")
6025 * (foundry "[^-]+")
6026 * (family "[^-]+")
6027 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
6028 * (weight\? "\\([^-]*\\)") ; 1
6029 * (slant "\\([ior]\\)") ; 2
6030 * (slant\? "\\([^-]?\\)") ; 2
6031 * (swidth "\\([^-]*\\)") ; 3
6032 * (adstyle "[^-]*") ; 4
6033 * (pixelsize "[0-9]+")
6034 * (pointsize "[0-9][0-9]+")
6035 * (resx "[0-9][0-9]+")
6036 * (resy "[0-9][0-9]+")
6037 * (spacing "[cmp?*]")
6038 * (avgwidth "[0-9]+")
6039 * (registry "[^-]+")
6040 * (encoding "[^-]+")
6041 * )
6042 */
6043
6044 static LONG
6045 x_to_w32_weight (lpw)
6046 char * lpw;
6047 {
6048 if (!lpw) return (FW_DONTCARE);
6049
6050 if (stricmp (lpw,"heavy") == 0) return FW_HEAVY;
6051 else if (stricmp (lpw,"extrabold") == 0) return FW_EXTRABOLD;
6052 else if (stricmp (lpw,"bold") == 0) return FW_BOLD;
6053 else if (stricmp (lpw,"demibold") == 0) return FW_SEMIBOLD;
6054 else if (stricmp (lpw,"semibold") == 0) return FW_SEMIBOLD;
6055 else if (stricmp (lpw,"medium") == 0) return FW_MEDIUM;
6056 else if (stricmp (lpw,"normal") == 0) return FW_NORMAL;
6057 else if (stricmp (lpw,"light") == 0) return FW_LIGHT;
6058 else if (stricmp (lpw,"extralight") == 0) return FW_EXTRALIGHT;
6059 else if (stricmp (lpw,"thin") == 0) return FW_THIN;
6060 else
6061 return FW_DONTCARE;
6062 }
6063
6064
6065 static char *
6066 w32_to_x_weight (fnweight)
6067 int fnweight;
6068 {
6069 if (fnweight >= FW_HEAVY) return "heavy";
6070 if (fnweight >= FW_EXTRABOLD) return "extrabold";
6071 if (fnweight >= FW_BOLD) return "bold";
6072 if (fnweight >= FW_SEMIBOLD) return "demibold";
6073 if (fnweight >= FW_MEDIUM) return "medium";
6074 if (fnweight >= FW_NORMAL) return "normal";
6075 if (fnweight >= FW_LIGHT) return "light";
6076 if (fnweight >= FW_EXTRALIGHT) return "extralight";
6077 if (fnweight >= FW_THIN) return "thin";
6078 else
6079 return "*";
6080 }
6081
6082 static LONG
6083 x_to_w32_charset (lpcs)
6084 char * lpcs;
6085 {
6086 Lisp_Object this_entry, w32_charset;
6087 char *charset;
6088 int len = strlen (lpcs);
6089
6090 /* Support "*-#nnn" format for unknown charsets. */
6091 if (strncmp (lpcs, "*-#", 3) == 0)
6092 return atoi (lpcs + 3);
6093
6094 /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5". */
6095 charset = alloca (len + 1);
6096 strcpy (charset, lpcs);
6097 lpcs = strchr (charset, '*');
6098 if (lpcs)
6099 *lpcs = 0;
6100
6101 /* Look through w32-charset-info-alist for the character set.
6102 Format of each entry is
6103 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
6104 */
6105 this_entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
6106
6107 if (NILP(this_entry))
6108 {
6109 /* At startup, we want iso8859-1 fonts to come up properly. */
6110 if (stricmp(charset, "iso8859-1") == 0)
6111 return ANSI_CHARSET;
6112 else
6113 return DEFAULT_CHARSET;
6114 }
6115
6116 w32_charset = Fcar (Fcdr (this_entry));
6117
6118 /* Translate Lisp symbol to number. */
6119 if (w32_charset == Qw32_charset_ansi)
6120 return ANSI_CHARSET;
6121 if (w32_charset == Qw32_charset_symbol)
6122 return SYMBOL_CHARSET;
6123 if (w32_charset == Qw32_charset_shiftjis)
6124 return SHIFTJIS_CHARSET;
6125 if (w32_charset == Qw32_charset_hangeul)
6126 return HANGEUL_CHARSET;
6127 if (w32_charset == Qw32_charset_chinesebig5)
6128 return CHINESEBIG5_CHARSET;
6129 if (w32_charset == Qw32_charset_gb2312)
6130 return GB2312_CHARSET;
6131 if (w32_charset == Qw32_charset_oem)
6132 return OEM_CHARSET;
6133 #ifdef JOHAB_CHARSET
6134 if (w32_charset == Qw32_charset_johab)
6135 return JOHAB_CHARSET;
6136 if (w32_charset == Qw32_charset_easteurope)
6137 return EASTEUROPE_CHARSET;
6138 if (w32_charset == Qw32_charset_turkish)
6139 return TURKISH_CHARSET;
6140 if (w32_charset == Qw32_charset_baltic)
6141 return BALTIC_CHARSET;
6142 if (w32_charset == Qw32_charset_russian)
6143 return RUSSIAN_CHARSET;
6144 if (w32_charset == Qw32_charset_arabic)
6145 return ARABIC_CHARSET;
6146 if (w32_charset == Qw32_charset_greek)
6147 return GREEK_CHARSET;
6148 if (w32_charset == Qw32_charset_hebrew)
6149 return HEBREW_CHARSET;
6150 if (w32_charset == Qw32_charset_vietnamese)
6151 return VIETNAMESE_CHARSET;
6152 if (w32_charset == Qw32_charset_thai)
6153 return THAI_CHARSET;
6154 if (w32_charset == Qw32_charset_mac)
6155 return MAC_CHARSET;
6156 #endif /* JOHAB_CHARSET */
6157 #ifdef UNICODE_CHARSET
6158 if (w32_charset == Qw32_charset_unicode)
6159 return UNICODE_CHARSET;
6160 #endif
6161
6162 return DEFAULT_CHARSET;
6163 }
6164
6165
6166 static char *
6167 w32_to_x_charset (fncharset)
6168 int fncharset;
6169 {
6170 static char buf[32];
6171 Lisp_Object charset_type;
6172
6173 switch (fncharset)
6174 {
6175 case ANSI_CHARSET:
6176 /* Handle startup case of w32-charset-info-alist not
6177 being set up yet. */
6178 if (NILP(Vw32_charset_info_alist))
6179 return "iso8859-1";
6180 charset_type = Qw32_charset_ansi;
6181 break;
6182 case DEFAULT_CHARSET:
6183 charset_type = Qw32_charset_default;
6184 break;
6185 case SYMBOL_CHARSET:
6186 charset_type = Qw32_charset_symbol;
6187 break;
6188 case SHIFTJIS_CHARSET:
6189 charset_type = Qw32_charset_shiftjis;
6190 break;
6191 case HANGEUL_CHARSET:
6192 charset_type = Qw32_charset_hangeul;
6193 break;
6194 case GB2312_CHARSET:
6195 charset_type = Qw32_charset_gb2312;
6196 break;
6197 case CHINESEBIG5_CHARSET:
6198 charset_type = Qw32_charset_chinesebig5;
6199 break;
6200 case OEM_CHARSET:
6201 charset_type = Qw32_charset_oem;
6202 break;
6203
6204 /* More recent versions of Windows (95 and NT4.0) define more
6205 character sets. */
6206 #ifdef EASTEUROPE_CHARSET
6207 case EASTEUROPE_CHARSET:
6208 charset_type = Qw32_charset_easteurope;
6209 break;
6210 case TURKISH_CHARSET:
6211 charset_type = Qw32_charset_turkish;
6212 break;
6213 case BALTIC_CHARSET:
6214 charset_type = Qw32_charset_baltic;
6215 break;
6216 case RUSSIAN_CHARSET:
6217 charset_type = Qw32_charset_russian;
6218 break;
6219 case ARABIC_CHARSET:
6220 charset_type = Qw32_charset_arabic;
6221 break;
6222 case GREEK_CHARSET:
6223 charset_type = Qw32_charset_greek;
6224 break;
6225 case HEBREW_CHARSET:
6226 charset_type = Qw32_charset_hebrew;
6227 break;
6228 case VIETNAMESE_CHARSET:
6229 charset_type = Qw32_charset_vietnamese;
6230 break;
6231 case THAI_CHARSET:
6232 charset_type = Qw32_charset_thai;
6233 break;
6234 case MAC_CHARSET:
6235 charset_type = Qw32_charset_mac;
6236 break;
6237 case JOHAB_CHARSET:
6238 charset_type = Qw32_charset_johab;
6239 break;
6240 #endif
6241
6242 #ifdef UNICODE_CHARSET
6243 case UNICODE_CHARSET:
6244 charset_type = Qw32_charset_unicode;
6245 break;
6246 #endif
6247 default:
6248 /* Encode numerical value of unknown charset. */
6249 sprintf (buf, "*-#%u", fncharset);
6250 return buf;
6251 }
6252
6253 {
6254 Lisp_Object rest;
6255 char * best_match = NULL;
6256
6257 /* Look through w32-charset-info-alist for the character set.
6258 Prefer ISO codepages, and prefer lower numbers in the ISO
6259 range. Only return charsets for codepages which are installed.
6260
6261 Format of each entry is
6262 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
6263 */
6264 for (rest = Vw32_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6265 {
6266 char * x_charset;
6267 Lisp_Object w32_charset;
6268 Lisp_Object codepage;
6269
6270 Lisp_Object this_entry = XCAR (rest);
6271
6272 /* Skip invalid entries in alist. */
6273 if (!CONSP (this_entry) || !STRINGP (XCAR (this_entry))
6274 || !CONSP (XCDR (this_entry))
6275 || !SYMBOLP (XCAR (XCDR (this_entry))))
6276 continue;
6277
6278 x_charset = XSTRING (XCAR (this_entry))->data;
6279 w32_charset = XCAR (XCDR (this_entry));
6280 codepage = XCDR (XCDR (this_entry));
6281
6282 /* Look for Same charset and a valid codepage (or non-int
6283 which means ignore). */
6284 if (w32_charset == charset_type
6285 && (!INTEGERP (codepage) || codepage == CP_DEFAULT
6286 || IsValidCodePage (XINT (codepage))))
6287 {
6288 /* If we don't have a match already, then this is the
6289 best. */
6290 if (!best_match)
6291 best_match = x_charset;
6292 /* If this is an ISO codepage, and the best so far isn't,
6293 then this is better. */
6294 else if (strnicmp (best_match, "iso", 3) != 0
6295 && strnicmp (x_charset, "iso", 3) == 0)
6296 best_match = x_charset;
6297 /* If both are ISO8859 codepages, choose the one with the
6298 lowest number in the encoding field. */
6299 else if (strnicmp (best_match, "iso8859-", 8) == 0
6300 && strnicmp (x_charset, "iso8859-", 8) == 0)
6301 {
6302 int best_enc = atoi (best_match + 8);
6303 int this_enc = atoi (x_charset + 8);
6304 if (this_enc > 0 && this_enc < best_enc)
6305 best_match = x_charset;
6306 }
6307 }
6308 }
6309
6310 /* If no match, encode the numeric value. */
6311 if (!best_match)
6312 {
6313 sprintf (buf, "*-#%u", fncharset);
6314 return buf;
6315 }
6316
6317 strncpy(buf, best_match, 31);
6318 buf[31] = '\0';
6319 return buf;
6320 }
6321 }
6322
6323
6324 /* Return all the X charsets that map to a font. */
6325 static Lisp_Object
6326 w32_to_all_x_charsets (fncharset)
6327 int fncharset;
6328 {
6329 static char buf[32];
6330 Lisp_Object charset_type;
6331 Lisp_Object retval = Qnil;
6332
6333 switch (fncharset)
6334 {
6335 case ANSI_CHARSET:
6336 /* Handle startup case of w32-charset-info-alist not
6337 being set up yet. */
6338 if (NILP(Vw32_charset_info_alist))
6339 return "iso8859-1";
6340 charset_type = Qw32_charset_ansi;
6341 break;
6342 case DEFAULT_CHARSET:
6343 charset_type = Qw32_charset_default;
6344 break;
6345 case SYMBOL_CHARSET:
6346 charset_type = Qw32_charset_symbol;
6347 break;
6348 case SHIFTJIS_CHARSET:
6349 charset_type = Qw32_charset_shiftjis;
6350 break;
6351 case HANGEUL_CHARSET:
6352 charset_type = Qw32_charset_hangeul;
6353 break;
6354 case GB2312_CHARSET:
6355 charset_type = Qw32_charset_gb2312;
6356 break;
6357 case CHINESEBIG5_CHARSET:
6358 charset_type = Qw32_charset_chinesebig5;
6359 break;
6360 case OEM_CHARSET:
6361 charset_type = Qw32_charset_oem;
6362 break;
6363
6364 /* More recent versions of Windows (95 and NT4.0) define more
6365 character sets. */
6366 #ifdef EASTEUROPE_CHARSET
6367 case EASTEUROPE_CHARSET:
6368 charset_type = Qw32_charset_easteurope;
6369 break;
6370 case TURKISH_CHARSET:
6371 charset_type = Qw32_charset_turkish;
6372 break;
6373 case BALTIC_CHARSET:
6374 charset_type = Qw32_charset_baltic;
6375 break;
6376 case RUSSIAN_CHARSET:
6377 charset_type = Qw32_charset_russian;
6378 break;
6379 case ARABIC_CHARSET:
6380 charset_type = Qw32_charset_arabic;
6381 break;
6382 case GREEK_CHARSET:
6383 charset_type = Qw32_charset_greek;
6384 break;
6385 case HEBREW_CHARSET:
6386 charset_type = Qw32_charset_hebrew;
6387 break;
6388 case VIETNAMESE_CHARSET:
6389 charset_type = Qw32_charset_vietnamese;
6390 break;
6391 case THAI_CHARSET:
6392 charset_type = Qw32_charset_thai;
6393 break;
6394 case MAC_CHARSET:
6395 charset_type = Qw32_charset_mac;
6396 break;
6397 case JOHAB_CHARSET:
6398 charset_type = Qw32_charset_johab;
6399 break;
6400 #endif
6401
6402 #ifdef UNICODE_CHARSET
6403 case UNICODE_CHARSET:
6404 charset_type = Qw32_charset_unicode;
6405 break;
6406 #endif
6407 default:
6408 /* Encode numerical value of unknown charset. */
6409 sprintf (buf, "*-#%u", fncharset);
6410 return Fcons (build_string (buf), Qnil);
6411 }
6412
6413 {
6414 Lisp_Object rest;
6415 /* Look through w32-charset-info-alist for the character set.
6416 Only return charsets for codepages which are installed.
6417
6418 Format of each entry in Vw32_charset_info_alist is
6419 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
6420 */
6421 for (rest = Vw32_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6422 {
6423 Lisp_Object x_charset;
6424 Lisp_Object w32_charset;
6425 Lisp_Object codepage;
6426
6427 Lisp_Object this_entry = XCAR (rest);
6428
6429 /* Skip invalid entries in alist. */
6430 if (!CONSP (this_entry) || !STRINGP (XCAR (this_entry))
6431 || !CONSP (XCDR (this_entry))
6432 || !SYMBOLP (XCAR (XCDR (this_entry))))
6433 continue;
6434
6435 x_charset = XCAR (this_entry);
6436 w32_charset = XCAR (XCDR (this_entry));
6437 codepage = XCDR (XCDR (this_entry));
6438
6439 /* Look for Same charset and a valid codepage (or non-int
6440 which means ignore). */
6441 if (w32_charset == charset_type
6442 && (!INTEGERP (codepage) || codepage == CP_DEFAULT
6443 || IsValidCodePage (XINT (codepage))))
6444 {
6445 retval = Fcons (x_charset, retval);
6446 }
6447 }
6448
6449 /* If no match, encode the numeric value. */
6450 if (NILP (retval))
6451 {
6452 sprintf (buf, "*-#%u", fncharset);
6453 return Fcons (build_string (buf), Qnil);
6454 }
6455
6456 return retval;
6457 }
6458 }
6459
6460 /* Get the Windows codepage corresponding to the specified font. The
6461 charset info in the font name is used to look up
6462 w32-charset-to-codepage-alist. */
6463 int
6464 w32_codepage_for_font (char *fontname)
6465 {
6466 Lisp_Object codepage, entry;
6467 char *charset_str, *charset, *end;
6468
6469 if (NILP (Vw32_charset_info_alist))
6470 return CP_DEFAULT;
6471
6472 /* Extract charset part of font string. */
6473 charset = xlfd_charset_of_font (fontname);
6474
6475 if (!charset)
6476 return CP_UNKNOWN;
6477
6478 charset_str = (char *) alloca (strlen (charset) + 1);
6479 strcpy (charset_str, charset);
6480
6481 #if 0
6482 /* Remove leading "*-". */
6483 if (strncmp ("*-", charset_str, 2) == 0)
6484 charset = charset_str + 2;
6485 else
6486 #endif
6487 charset = charset_str;
6488
6489 /* Stop match at wildcard (including preceding '-'). */
6490 if (end = strchr (charset, '*'))
6491 {
6492 if (end > charset && *(end-1) == '-')
6493 end--;
6494 *end = '\0';
6495 }
6496
6497 entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
6498 if (NILP (entry))
6499 return CP_UNKNOWN;
6500
6501 codepage = Fcdr (Fcdr (entry));
6502
6503 if (NILP (codepage))
6504 return CP_8BIT;
6505 else if (XFASTINT (codepage) == XFASTINT (Qt))
6506 return CP_UNICODE;
6507 else if (INTEGERP (codepage))
6508 return XINT (codepage);
6509 else
6510 return CP_UNKNOWN;
6511 }
6512
6513
6514 static BOOL
6515 w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
6516 LOGFONT * lplogfont;
6517 char * lpxstr;
6518 int len;
6519 char * specific_charset;
6520 {
6521 char* fonttype;
6522 char *fontname;
6523 char height_pixels[8];
6524 char height_dpi[8];
6525 char width_pixels[8];
6526 char *fontname_dash;
6527 int display_resy = one_w32_display_info.resy;
6528 int display_resx = one_w32_display_info.resx;
6529 int bufsz;
6530 struct coding_system coding;
6531
6532 if (!lpxstr) abort ();
6533
6534 if (!lplogfont)
6535 return FALSE;
6536
6537 if (lplogfont->lfOutPrecision == OUT_STRING_PRECIS)
6538 fonttype = "raster";
6539 else if (lplogfont->lfOutPrecision == OUT_STROKE_PRECIS)
6540 fonttype = "outline";
6541 else
6542 fonttype = "unknown";
6543
6544 setup_coding_system (Fcheck_coding_system (Vlocale_coding_system),
6545 &coding);
6546 coding.src_multibyte = 0;
6547 coding.dst_multibyte = 1;
6548 coding.mode |= CODING_MODE_LAST_BLOCK;
6549 bufsz = decoding_buffer_size (&coding, LF_FACESIZE);
6550
6551 fontname = alloca(sizeof(*fontname) * bufsz);
6552 decode_coding (&coding, lplogfont->lfFaceName, fontname,
6553 strlen(lplogfont->lfFaceName), bufsz - 1);
6554 *(fontname + coding.produced) = '\0';
6555
6556 /* Replace dashes with underscores so the dashes are not
6557 misinterpreted. */
6558 fontname_dash = fontname;
6559 while (fontname_dash = strchr (fontname_dash, '-'))
6560 *fontname_dash = '_';
6561
6562 if (lplogfont->lfHeight)
6563 {
6564 sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
6565 sprintf (height_dpi, "%u",
6566 abs (lplogfont->lfHeight) * 720 / display_resy);
6567 }
6568 else
6569 {
6570 strcpy (height_pixels, "*");
6571 strcpy (height_dpi, "*");
6572 }
6573 if (lplogfont->lfWidth)
6574 sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
6575 else
6576 strcpy (width_pixels, "*");
6577
6578 _snprintf (lpxstr, len - 1,
6579 "-%s-%s-%s-%c-normal-normal-%s-%s-%d-%d-%c-%s-%s",
6580 fonttype, /* foundry */
6581 fontname, /* family */
6582 w32_to_x_weight (lplogfont->lfWeight), /* weight */
6583 lplogfont->lfItalic?'i':'r', /* slant */
6584 /* setwidth name */
6585 /* add style name */
6586 height_pixels, /* pixel size */
6587 height_dpi, /* point size */
6588 display_resx, /* resx */
6589 display_resy, /* resy */
6590 ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH)
6591 ? 'p' : 'c', /* spacing */
6592 width_pixels, /* avg width */
6593 specific_charset ? specific_charset
6594 : w32_to_x_charset (lplogfont->lfCharSet)
6595 /* charset registry and encoding */
6596 );
6597
6598 lpxstr[len - 1] = 0; /* just to be sure */
6599 return (TRUE);
6600 }
6601
6602 static BOOL
6603 x_to_w32_font (lpxstr, lplogfont)
6604 char * lpxstr;
6605 LOGFONT * lplogfont;
6606 {
6607 struct coding_system coding;
6608
6609 if (!lplogfont) return (FALSE);
6610
6611 memset (lplogfont, 0, sizeof (*lplogfont));
6612
6613 /* Set default value for each field. */
6614 #if 1
6615 lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
6616 lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
6617 lplogfont->lfQuality = DEFAULT_QUALITY;
6618 #else
6619 /* go for maximum quality */
6620 lplogfont->lfOutPrecision = OUT_STROKE_PRECIS;
6621 lplogfont->lfClipPrecision = CLIP_STROKE_PRECIS;
6622 lplogfont->lfQuality = PROOF_QUALITY;
6623 #endif
6624
6625 lplogfont->lfCharSet = DEFAULT_CHARSET;
6626 lplogfont->lfWeight = FW_DONTCARE;
6627 lplogfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
6628
6629 if (!lpxstr)
6630 return FALSE;
6631
6632 /* Provide a simple escape mechanism for specifying Windows font names
6633 * directly -- if font spec does not beginning with '-', assume this
6634 * format:
6635 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
6636 */
6637
6638 if (*lpxstr == '-')
6639 {
6640 int fields, tem;
6641 char name[50], weight[20], slant, pitch, pixels[10], height[10],
6642 width[10], resy[10], remainder[50];
6643 char * encoding;
6644 int dpi = one_w32_display_info.resy;
6645
6646 fields = sscanf (lpxstr,
6647 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
6648 name, weight, &slant, pixels, height, resy, &pitch, width, remainder);
6649 if (fields == EOF)
6650 return (FALSE);
6651
6652 /* In the general case when wildcards cover more than one field,
6653 we don't know which field is which, so don't fill any in.
6654 However, we need to cope with this particular form, which is
6655 generated by font_list_1 (invoked by try_font_list):
6656 "-raster-6x10-*-gb2312*-*"
6657 and make sure to correctly parse the charset field. */
6658 if (fields == 3)
6659 {
6660 fields = sscanf (lpxstr,
6661 "-%*[^-]-%49[^-]-*-%49s",
6662 name, remainder);
6663 }
6664 else if (fields < 9)
6665 {
6666 fields = 0;
6667 remainder[0] = 0;
6668 }
6669
6670 if (fields > 0 && name[0] != '*')
6671 {
6672 int bufsize;
6673 unsigned char *buf;
6674
6675 setup_coding_system
6676 (Fcheck_coding_system (Vlocale_coding_system), &coding);
6677 coding.src_multibyte = 1;
6678 coding.dst_multibyte = 1;
6679 bufsize = encoding_buffer_size (&coding, strlen (name));
6680 buf = (unsigned char *) alloca (bufsize);
6681 coding.mode |= CODING_MODE_LAST_BLOCK;
6682 encode_coding (&coding, name, buf, strlen (name), bufsize);
6683 if (coding.produced >= LF_FACESIZE)
6684 coding.produced = LF_FACESIZE - 1;
6685 buf[coding.produced] = 0;
6686 strcpy (lplogfont->lfFaceName, buf);
6687 }
6688 else
6689 {
6690 lplogfont->lfFaceName[0] = '\0';
6691 }
6692
6693 fields--;
6694
6695 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
6696
6697 fields--;
6698
6699 lplogfont->lfItalic = (fields > 0 && slant == 'i');
6700
6701 fields--;
6702
6703 if (fields > 0 && pixels[0] != '*')
6704 lplogfont->lfHeight = atoi (pixels);
6705
6706 fields--;
6707 fields--;
6708 if (fields > 0 && resy[0] != '*')
6709 {
6710 tem = atoi (resy);
6711 if (tem > 0) dpi = tem;
6712 }
6713
6714 if (fields > -1 && lplogfont->lfHeight == 0 && height[0] != '*')
6715 lplogfont->lfHeight = atoi (height) * dpi / 720;
6716
6717 if (fields > 0)
6718 lplogfont->lfPitchAndFamily =
6719 (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
6720
6721 fields--;
6722
6723 if (fields > 0 && width[0] != '*')
6724 lplogfont->lfWidth = atoi (width) / 10;
6725
6726 fields--;
6727
6728 /* Strip the trailing '-' if present. (it shouldn't be, as it
6729 fails the test against xlfd-tight-regexp in fontset.el). */
6730 {
6731 int len = strlen (remainder);
6732 if (len > 0 && remainder[len-1] == '-')
6733 remainder[len-1] = 0;
6734 }
6735 encoding = remainder;
6736 #if 0
6737 if (strncmp (encoding, "*-", 2) == 0)
6738 encoding += 2;
6739 #endif
6740 lplogfont->lfCharSet = x_to_w32_charset (encoding);
6741 }
6742 else
6743 {
6744 int fields;
6745 char name[100], height[10], width[10], weight[20];
6746
6747 fields = sscanf (lpxstr,
6748 "%99[^:]:%9[^:]:%9[^:]:%19s",
6749 name, height, width, weight);
6750
6751 if (fields == EOF) return (FALSE);
6752
6753 if (fields > 0)
6754 {
6755 strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
6756 lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
6757 }
6758 else
6759 {
6760 lplogfont->lfFaceName[0] = 0;
6761 }
6762
6763 fields--;
6764
6765 if (fields > 0)
6766 lplogfont->lfHeight = atoi (height);
6767
6768 fields--;
6769
6770 if (fields > 0)
6771 lplogfont->lfWidth = atoi (width);
6772
6773 fields--;
6774
6775 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
6776 }
6777
6778 /* This makes TrueType fonts work better. */
6779 lplogfont->lfHeight = - abs (lplogfont->lfHeight);
6780
6781 return (TRUE);
6782 }
6783
6784 /* Strip the pixel height and point height from the given xlfd, and
6785 return the pixel height. If no pixel height is specified, calculate
6786 one from the point height, or if that isn't defined either, return
6787 0 (which usually signifies a scalable font).
6788 */
6789 static int
6790 xlfd_strip_height (char *fontname)
6791 {
6792 int pixel_height, field_number;
6793 char *read_from, *write_to;
6794
6795 xassert (fontname);
6796
6797 pixel_height = field_number = 0;
6798 write_to = NULL;
6799
6800 /* Look for height fields. */
6801 for (read_from = fontname; *read_from; read_from++)
6802 {
6803 if (*read_from == '-')
6804 {
6805 field_number++;
6806 if (field_number == 7) /* Pixel height. */
6807 {
6808 read_from++;
6809 write_to = read_from;
6810
6811 /* Find end of field. */
6812 for (;*read_from && *read_from != '-'; read_from++)
6813 ;
6814
6815 /* Split the fontname at end of field. */
6816 if (*read_from)
6817 {
6818 *read_from = '\0';
6819 read_from++;
6820 }
6821 pixel_height = atoi (write_to);
6822 /* Blank out field. */
6823 if (read_from > write_to)
6824 {
6825 *write_to = '-';
6826 write_to++;
6827 }
6828 /* If the pixel height field is at the end (partial xlfd),
6829 return now. */
6830 else
6831 return pixel_height;
6832
6833 /* If we got a pixel height, the point height can be
6834 ignored. Just blank it out and break now. */
6835 if (pixel_height)
6836 {
6837 /* Find end of point size field. */
6838 for (; *read_from && *read_from != '-'; read_from++)
6839 ;
6840
6841 if (*read_from)
6842 read_from++;
6843
6844 /* Blank out the point size field. */
6845 if (read_from > write_to)
6846 {
6847 *write_to = '-';
6848 write_to++;
6849 }
6850 else
6851 return pixel_height;
6852
6853 break;
6854 }
6855 /* If the point height is already blank, break now. */
6856 if (*read_from == '-')
6857 {
6858 read_from++;
6859 break;
6860 }
6861 }
6862 else if (field_number == 8)
6863 {
6864 /* If we didn't get a pixel height, try to get the point
6865 height and convert that. */
6866 int point_size;
6867 char *point_size_start = read_from++;
6868
6869 /* Find end of field. */
6870 for (; *read_from && *read_from != '-'; read_from++)
6871 ;
6872
6873 if (*read_from)
6874 {
6875 *read_from = '\0';
6876 read_from++;
6877 }
6878
6879 point_size = atoi (point_size_start);
6880
6881 /* Convert to pixel height. */
6882 pixel_height = point_size
6883 * one_w32_display_info.height_in / 720;
6884
6885 /* Blank out this field and break. */
6886 *write_to = '-';
6887 write_to++;
6888 break;
6889 }
6890 }
6891 }
6892
6893 /* Shift the rest of the font spec into place. */
6894 if (write_to && read_from > write_to)
6895 {
6896 for (; *read_from; read_from++, write_to++)
6897 *write_to = *read_from;
6898 *write_to = '\0';
6899 }
6900
6901 return pixel_height;
6902 }
6903
6904 /* Assume parameter 1 is fully qualified, no wildcards. */
6905 static BOOL
6906 w32_font_match (fontname, pattern)
6907 char * fontname;
6908 char * pattern;
6909 {
6910 char *regex = alloca (strlen (pattern) * 2 + 3);
6911 char *font_name_copy = alloca (strlen (fontname) + 1);
6912 char *ptr;
6913
6914 /* Copy fontname so we can modify it during comparison. */
6915 strcpy (font_name_copy, fontname);
6916
6917 ptr = regex;
6918 *ptr++ = '^';
6919
6920 /* Turn pattern into a regexp and do a regexp match. */
6921 for (; *pattern; pattern++)
6922 {
6923 if (*pattern == '?')
6924 *ptr++ = '.';
6925 else if (*pattern == '*')
6926 {
6927 *ptr++ = '.';
6928 *ptr++ = '*';
6929 }
6930 else
6931 *ptr++ = *pattern;
6932 }
6933 *ptr = '$';
6934 *(ptr + 1) = '\0';
6935
6936 /* Strip out font heights and compare them seperately, since
6937 rounding error can cause mismatches. This also allows a
6938 comparison between a font that declares only a pixel height and a
6939 pattern that declares the point height.
6940 */
6941 {
6942 int font_height, pattern_height;
6943
6944 font_height = xlfd_strip_height (font_name_copy);
6945 pattern_height = xlfd_strip_height (regex);
6946
6947 /* Compare now, and don't bother doing expensive regexp matching
6948 if the heights differ. */
6949 if (font_height && pattern_height && (font_height != pattern_height))
6950 return FALSE;
6951 }
6952
6953 return (fast_c_string_match_ignore_case (build_string (regex),
6954 font_name_copy) >= 0);
6955 }
6956
6957 /* Callback functions, and a structure holding info they need, for
6958 listing system fonts on W32. We need one set of functions to do the
6959 job properly, but these don't work on NT 3.51 and earlier, so we
6960 have a second set which don't handle character sets properly to
6961 fall back on.
6962
6963 In both cases, there are two passes made. The first pass gets one
6964 font from each family, the second pass lists all the fonts from
6965 each family. */
6966
6967 typedef struct enumfont_t
6968 {
6969 HDC hdc;
6970 int numFonts;
6971 LOGFONT logfont;
6972 XFontStruct *size_ref;
6973 Lisp_Object *pattern;
6974 Lisp_Object list;
6975 Lisp_Object *tail;
6976 } enumfont_t;
6977
6978
6979 static void
6980 enum_font_maybe_add_to_list (enumfont_t *, LOGFONT *, char *, Lisp_Object);
6981
6982
6983 static int CALLBACK
6984 enum_font_cb2 (lplf, lptm, FontType, lpef)
6985 ENUMLOGFONT * lplf;
6986 NEWTEXTMETRIC * lptm;
6987 int FontType;
6988 enumfont_t * lpef;
6989 {
6990 /* Ignore struck out and underlined versions of fonts. */
6991 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline)
6992 return 1;
6993
6994 /* Only return fonts with names starting with @ if they were
6995 explicitly specified, since Microsoft uses an initial @ to
6996 denote fonts for vertical writing, without providing a more
6997 convenient way of identifying them. */
6998 if (lplf->elfLogFont.lfFaceName[0] == '@'
6999 && lpef->logfont.lfFaceName[0] != '@')
7000 return 1;
7001
7002 /* Check that the character set matches if it was specified */
7003 if (lpef->logfont.lfCharSet != DEFAULT_CHARSET &&
7004 lplf->elfLogFont.lfCharSet != lpef->logfont.lfCharSet)
7005 return 1;
7006
7007 {
7008 char buf[100];
7009 Lisp_Object width = Qnil;
7010 Lisp_Object charset_list = Qnil;
7011 char *charset = NULL;
7012
7013 /* Truetype fonts do not report their true metrics until loaded */
7014 if (FontType != RASTER_FONTTYPE)
7015 {
7016 if (!NILP (*(lpef->pattern)))
7017 {
7018 /* Scalable fonts are as big as you want them to be. */
7019 lplf->elfLogFont.lfHeight = lpef->logfont.lfHeight;
7020 lplf->elfLogFont.lfWidth = lpef->logfont.lfWidth;
7021 width = make_number (lpef->logfont.lfWidth);
7022 }
7023 else
7024 {
7025 lplf->elfLogFont.lfHeight = 0;
7026 lplf->elfLogFont.lfWidth = 0;
7027 }
7028 }
7029
7030 /* Make sure the height used here is the same as everywhere
7031 else (ie character height, not cell height). */
7032 if (lplf->elfLogFont.lfHeight > 0)
7033 {
7034 /* lptm can be trusted for RASTER fonts, but not scalable ones. */
7035 if (FontType == RASTER_FONTTYPE)
7036 lplf->elfLogFont.lfHeight = lptm->tmInternalLeading - lptm->tmHeight;
7037 else
7038 lplf->elfLogFont.lfHeight = -lplf->elfLogFont.lfHeight;
7039 }
7040
7041 if (!NILP (*(lpef->pattern)))
7042 {
7043 charset = xlfd_charset_of_font (XSTRING(*(lpef->pattern))->data);
7044
7045 /* We already checked charsets above, but DEFAULT_CHARSET
7046 slipped through. So only allow exact matches for DEFAULT_CHARSET. */
7047 if (charset
7048 && strncmp (charset, "*-*", 3) != 0
7049 && lpef->logfont.lfCharSet == DEFAULT_CHARSET
7050 && strcmp (charset, w32_to_x_charset (DEFAULT_CHARSET)) != 0)
7051 return 1;
7052 }
7053
7054 if (charset)
7055 charset_list = Fcons (build_string (charset), Qnil);
7056 else
7057 charset_list = w32_to_all_x_charsets (lplf->elfLogFont.lfCharSet);
7058
7059 /* Loop through the charsets. */
7060 for ( ; CONSP (charset_list); charset_list = Fcdr (charset_list))
7061 {
7062 Lisp_Object this_charset = Fcar (charset_list);
7063 charset = XSTRING (this_charset)->data;
7064
7065 /* List bold and italic variations if w32-enable-synthesized-fonts
7066 is non-nil and this is a plain font. */
7067 if (w32_enable_synthesized_fonts
7068 && lplf->elfLogFont.lfWeight == FW_NORMAL
7069 && lplf->elfLogFont.lfItalic == FALSE)
7070 {
7071 enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
7072 charset, width);
7073 /* bold. */
7074 lplf->elfLogFont.lfWeight = FW_BOLD;
7075 enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
7076 charset, width);
7077 /* bold italic. */
7078 lplf->elfLogFont.lfItalic = TRUE;
7079 enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
7080 charset, width);
7081 /* italic. */
7082 lplf->elfLogFont.lfWeight = FW_NORMAL;
7083 enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
7084 charset, width);
7085 }
7086 else
7087 enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
7088 charset, width);
7089 }
7090 }
7091
7092 return 1;
7093 }
7094
7095 static void
7096 enum_font_maybe_add_to_list (lpef, logfont, match_charset, width)
7097 enumfont_t * lpef;
7098 LOGFONT * logfont;
7099 char * match_charset;
7100 Lisp_Object width;
7101 {
7102 char buf[100];
7103
7104 if (!w32_to_x_font (logfont, buf, 100, match_charset))
7105 return;
7106
7107 if (NILP (*(lpef->pattern))
7108 || w32_font_match (buf, XSTRING (*(lpef->pattern))->data))
7109 {
7110 /* Check if we already listed this font. This may happen if
7111 w32_enable_synthesized_fonts is non-nil, and there are real
7112 bold and italic versions of the font. */
7113 Lisp_Object font_name = build_string (buf);
7114 if (NILP (Fmember (font_name, lpef->list)))
7115 {
7116 *lpef->tail = Fcons (Fcons (build_string (buf), width), Qnil);
7117 lpef->tail = &(XCDR (*lpef->tail));
7118 lpef->numFonts++;
7119 }
7120 }
7121 }
7122
7123
7124 static int CALLBACK
7125 enum_font_cb1 (lplf, lptm, FontType, lpef)
7126 ENUMLOGFONT * lplf;
7127 NEWTEXTMETRIC * lptm;
7128 int FontType;
7129 enumfont_t * lpef;
7130 {
7131 return EnumFontFamilies (lpef->hdc,
7132 lplf->elfLogFont.lfFaceName,
7133 (FONTENUMPROC) enum_font_cb2,
7134 (LPARAM) lpef);
7135 }
7136
7137
7138 static int CALLBACK
7139 enum_fontex_cb2 (lplf, lptm, font_type, lpef)
7140 ENUMLOGFONTEX * lplf;
7141 NEWTEXTMETRICEX * lptm;
7142 int font_type;
7143 enumfont_t * lpef;
7144 {
7145 /* We are not interested in the extra info we get back from the 'Ex
7146 version - only the fact that we get character set variations
7147 enumerated seperately. */
7148 return enum_font_cb2 ((ENUMLOGFONT *) lplf, (NEWTEXTMETRIC *) lptm,
7149 font_type, lpef);
7150 }
7151
7152 static int CALLBACK
7153 enum_fontex_cb1 (lplf, lptm, font_type, lpef)
7154 ENUMLOGFONTEX * lplf;
7155 NEWTEXTMETRICEX * lptm;
7156 int font_type;
7157 enumfont_t * lpef;
7158 {
7159 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
7160 FARPROC enum_font_families_ex
7161 = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
7162 /* We don't really expect EnumFontFamiliesEx to disappear once we
7163 get here, so don't bother handling it gracefully. */
7164 if (enum_font_families_ex == NULL)
7165 error ("gdi32.dll has disappeared!");
7166 return enum_font_families_ex (lpef->hdc,
7167 &lplf->elfLogFont,
7168 (FONTENUMPROC) enum_fontex_cb2,
7169 (LPARAM) lpef, 0);
7170 }
7171
7172 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
7173 and xterm.c in Emacs 20.3) */
7174
7175 static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names)
7176 {
7177 char *fontname, *ptnstr;
7178 Lisp_Object list, tem, newlist = Qnil;
7179 int n_fonts = 0;
7180
7181 list = Vw32_bdf_filename_alist;
7182 ptnstr = XSTRING (pattern)->data;
7183
7184 for ( ; CONSP (list); list = XCDR (list))
7185 {
7186 tem = XCAR (list);
7187 if (CONSP (tem))
7188 fontname = XSTRING (XCAR (tem))->data;
7189 else if (STRINGP (tem))
7190 fontname = XSTRING (tem)->data;
7191 else
7192 continue;
7193
7194 if (w32_font_match (fontname, ptnstr))
7195 {
7196 newlist = Fcons (XCAR (tem), newlist);
7197 n_fonts++;
7198 if (n_fonts >= max_names)
7199 break;
7200 }
7201 }
7202
7203 return newlist;
7204 }
7205
7206
7207 /* Return a list of names of available fonts matching PATTERN on frame
7208 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
7209 to be listed. Frame F NULL means we have not yet created any
7210 frame, which means we can't get proper size info, as we don't have
7211 a device context to use for GetTextMetrics.
7212 MAXNAMES sets a limit on how many fonts to match. */
7213
7214 Lisp_Object
7215 w32_list_fonts (f, pattern, size, maxnames)
7216 struct frame *f;
7217 Lisp_Object pattern;
7218 int size;
7219 int maxnames;
7220 {
7221 Lisp_Object patterns, key = Qnil, tem, tpat;
7222 Lisp_Object list = Qnil, newlist = Qnil, second_best = Qnil;
7223 struct w32_display_info *dpyinfo = &one_w32_display_info;
7224 int n_fonts = 0;
7225
7226 patterns = Fassoc (pattern, Valternate_fontname_alist);
7227 if (NILP (patterns))
7228 patterns = Fcons (pattern, Qnil);
7229
7230 for (; CONSP (patterns); patterns = XCDR (patterns))
7231 {
7232 enumfont_t ef;
7233 int codepage;
7234
7235 tpat = XCAR (patterns);
7236
7237 if (!STRINGP (tpat))
7238 continue;
7239
7240 /* Avoid expensive EnumFontFamilies functions if we are not
7241 going to be able to output one of these anyway. */
7242 codepage = w32_codepage_for_font (XSTRING (tpat)->data);
7243 if (codepage != CP_8BIT && codepage != CP_UNICODE
7244 && codepage != CP_DEFAULT && codepage != CP_UNKNOWN
7245 && !IsValidCodePage(codepage))
7246 continue;
7247
7248 /* See if we cached the result for this particular query.
7249 The cache is an alist of the form:
7250 ((PATTERN (FONTNAME . WIDTH) ...) ...)
7251 */
7252 if (tem = XCDR (dpyinfo->name_list_element),
7253 !NILP (list = Fassoc (tpat, tem)))
7254 {
7255 list = Fcdr_safe (list);
7256 /* We have a cached list. Don't have to get the list again. */
7257 goto label_cached;
7258 }
7259
7260 BLOCK_INPUT;
7261 /* At first, put PATTERN in the cache. */
7262 list = Qnil;
7263 ef.pattern = &tpat;
7264 ef.list = list;
7265 ef.tail = &list;
7266 ef.numFonts = 0;
7267
7268 /* Use EnumFontFamiliesEx where it is available, as it knows
7269 about character sets. Fall back to EnumFontFamilies for
7270 older versions of NT that don't support the 'Ex function. */
7271 x_to_w32_font (XSTRING (tpat)->data, &ef.logfont);
7272 {
7273 LOGFONT font_match_pattern;
7274 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
7275 FARPROC enum_font_families_ex
7276 = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
7277
7278 /* We do our own pattern matching so we can handle wildcards. */
7279 font_match_pattern.lfFaceName[0] = 0;
7280 font_match_pattern.lfPitchAndFamily = 0;
7281 /* We can use the charset, because if it is a wildcard it will
7282 be DEFAULT_CHARSET anyway. */
7283 font_match_pattern.lfCharSet = ef.logfont.lfCharSet;
7284
7285 ef.hdc = GetDC (dpyinfo->root_window);
7286
7287 if (enum_font_families_ex)
7288 enum_font_families_ex (ef.hdc,
7289 &font_match_pattern,
7290 (FONTENUMPROC) enum_fontex_cb1,
7291 (LPARAM) &ef, 0);
7292 else
7293 EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1,
7294 (LPARAM)&ef);
7295
7296 ReleaseDC (dpyinfo->root_window, ef.hdc);
7297 }
7298
7299 UNBLOCK_INPUT;
7300
7301 /* Make a list of the fonts we got back.
7302 Store that in the font cache for the display. */
7303 XSETCDR (dpyinfo->name_list_element,
7304 Fcons (Fcons (tpat, list),
7305 XCDR (dpyinfo->name_list_element)));
7306
7307 label_cached:
7308 if (NILP (list)) continue; /* Try the remaining alternatives. */
7309
7310 newlist = second_best = Qnil;
7311
7312 /* Make a list of the fonts that have the right width. */
7313 for (; CONSP (list); list = XCDR (list))
7314 {
7315 int found_size;
7316 tem = XCAR (list);
7317
7318 if (!CONSP (tem))
7319 continue;
7320 if (NILP (XCAR (tem)))
7321 continue;
7322 if (!size)
7323 {
7324 newlist = Fcons (XCAR (tem), newlist);
7325 n_fonts++;
7326 if (n_fonts >= maxnames)
7327 break;
7328 else
7329 continue;
7330 }
7331 if (!INTEGERP (XCDR (tem)))
7332 {
7333 /* Since we don't yet know the size of the font, we must
7334 load it and try GetTextMetrics. */
7335 W32FontStruct thisinfo;
7336 LOGFONT lf;
7337 HDC hdc;
7338 HANDLE oldobj;
7339
7340 if (!x_to_w32_font (XSTRING (XCAR (tem))->data, &lf))
7341 continue;
7342
7343 BLOCK_INPUT;
7344 thisinfo.bdf = NULL;
7345 thisinfo.hfont = CreateFontIndirect (&lf);
7346 if (thisinfo.hfont == NULL)
7347 continue;
7348
7349 hdc = GetDC (dpyinfo->root_window);
7350 oldobj = SelectObject (hdc, thisinfo.hfont);
7351 if (GetTextMetrics (hdc, &thisinfo.tm))
7352 XSETCDR (tem, make_number (FONT_WIDTH (&thisinfo)));
7353 else
7354 XSETCDR (tem, make_number (0));
7355 SelectObject (hdc, oldobj);
7356 ReleaseDC (dpyinfo->root_window, hdc);
7357 DeleteObject(thisinfo.hfont);
7358 UNBLOCK_INPUT;
7359 }
7360 found_size = XINT (XCDR (tem));
7361 if (found_size == size)
7362 {
7363 newlist = Fcons (XCAR (tem), newlist);
7364 n_fonts++;
7365 if (n_fonts >= maxnames)
7366 break;
7367 }
7368 /* keep track of the closest matching size in case
7369 no exact match is found. */
7370 else if (found_size > 0)
7371 {
7372 if (NILP (second_best))
7373 second_best = tem;
7374
7375 else if (found_size < size)
7376 {
7377 if (XINT (XCDR (second_best)) > size
7378 || XINT (XCDR (second_best)) < found_size)
7379 second_best = tem;
7380 }
7381 else
7382 {
7383 if (XINT (XCDR (second_best)) > size
7384 && XINT (XCDR (second_best)) >
7385 found_size)
7386 second_best = tem;
7387 }
7388 }
7389 }
7390
7391 if (!NILP (newlist))
7392 break;
7393 else if (!NILP (second_best))
7394 {
7395 newlist = Fcons (XCAR (second_best), Qnil);
7396 break;
7397 }
7398 }
7399
7400 /* Include any bdf fonts. */
7401 if (n_fonts < maxnames)
7402 {
7403 Lisp_Object combined[2];
7404 combined[0] = w32_list_bdf_fonts (pattern, maxnames - n_fonts);
7405 combined[1] = newlist;
7406 newlist = Fnconc(2, combined);
7407 }
7408
7409 return newlist;
7410 }
7411
7412
7413 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7414 struct font_info *
7415 w32_get_font_info (f, font_idx)
7416 FRAME_PTR f;
7417 int font_idx;
7418 {
7419 return (FRAME_W32_FONT_TABLE (f) + font_idx);
7420 }
7421
7422
7423 struct font_info*
7424 w32_query_font (struct frame *f, char *fontname)
7425 {
7426 int i;
7427 struct font_info *pfi;
7428
7429 pfi = FRAME_W32_FONT_TABLE (f);
7430
7431 for (i = 0; i < one_w32_display_info.n_fonts ;i++, pfi++)
7432 {
7433 if (strcmp(pfi->name, fontname) == 0) return pfi;
7434 }
7435
7436 return NULL;
7437 }
7438
7439 /* Find a CCL program for a font specified by FONTP, and set the member
7440 `encoder' of the structure. */
7441
7442 void
7443 w32_find_ccl_program (fontp)
7444 struct font_info *fontp;
7445 {
7446 Lisp_Object list, elt;
7447
7448 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7449 {
7450 elt = XCAR (list);
7451 if (CONSP (elt)
7452 && STRINGP (XCAR (elt))
7453 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7454 >= 0))
7455 break;
7456 }
7457 if (! NILP (list))
7458 {
7459 struct ccl_program *ccl
7460 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7461
7462 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7463 xfree (ccl);
7464 else
7465 fontp->font_encoder = ccl;
7466 }
7467 }
7468
7469 \f
7470 /* Find BDF files in a specified directory. (use GCPRO when calling,
7471 as this calls lisp to get a directory listing). */
7472 static Lisp_Object
7473 w32_find_bdf_fonts_in_dir (Lisp_Object directory)
7474 {
7475 Lisp_Object filelist, list = Qnil;
7476 char fontname[100];
7477
7478 if (!STRINGP(directory))
7479 return Qnil;
7480
7481 filelist = Fdirectory_files (directory, Qt,
7482 build_string (".*\\.[bB][dD][fF]"), Qt);
7483
7484 for ( ; CONSP(filelist); filelist = XCDR (filelist))
7485 {
7486 Lisp_Object filename = XCAR (filelist);
7487 if (w32_BDF_to_x_font (XSTRING (filename)->data, fontname, 100))
7488 store_in_alist (&list, build_string (fontname), filename);
7489 }
7490 return list;
7491 }
7492
7493 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts, Sw32_find_bdf_fonts,
7494 1, 1, 0,
7495 doc: /* Return a list of BDF fonts in DIR.
7496 The list is suitable for appending to w32-bdf-filename-alist. Fonts
7497 which do not contain an xlfd description will not be included in the
7498 list. DIR may be a list of directories. */)
7499 (directory)
7500 Lisp_Object directory;
7501 {
7502 Lisp_Object list = Qnil;
7503 struct gcpro gcpro1, gcpro2;
7504
7505 if (!CONSP (directory))
7506 return w32_find_bdf_fonts_in_dir (directory);
7507
7508 for ( ; CONSP (directory); directory = XCDR (directory))
7509 {
7510 Lisp_Object pair[2];
7511 pair[0] = list;
7512 pair[1] = Qnil;
7513 GCPRO2 (directory, list);
7514 pair[1] = w32_find_bdf_fonts_in_dir( XCAR (directory) );
7515 list = Fnconc( 2, pair );
7516 UNGCPRO;
7517 }
7518 return list;
7519 }
7520
7521 \f
7522 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
7523 doc: /* Internal function called by `color-defined-p', which see. */)
7524 (color, frame)
7525 Lisp_Object color, frame;
7526 {
7527 XColor foo;
7528 FRAME_PTR f = check_x_frame (frame);
7529
7530 CHECK_STRING (color);
7531
7532 if (w32_defined_color (f, XSTRING (color)->data, &foo, 0))
7533 return Qt;
7534 else
7535 return Qnil;
7536 }
7537
7538 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
7539 doc: /* Internal function called by `color-values', which see. */)
7540 (color, frame)
7541 Lisp_Object color, frame;
7542 {
7543 XColor foo;
7544 FRAME_PTR f = check_x_frame (frame);
7545
7546 CHECK_STRING (color);
7547
7548 if (w32_defined_color (f, XSTRING (color)->data, &foo, 0))
7549 {
7550 Lisp_Object rgb[3];
7551
7552 rgb[0] = make_number ((GetRValue (foo.pixel) << 8)
7553 | GetRValue (foo.pixel));
7554 rgb[1] = make_number ((GetGValue (foo.pixel) << 8)
7555 | GetGValue (foo.pixel));
7556 rgb[2] = make_number ((GetBValue (foo.pixel) << 8)
7557 | GetBValue (foo.pixel));
7558 return Flist (3, rgb);
7559 }
7560 else
7561 return Qnil;
7562 }
7563
7564 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
7565 doc: /* Internal function called by `display-color-p', which see. */)
7566 (display)
7567 Lisp_Object display;
7568 {
7569 struct w32_display_info *dpyinfo = check_x_display_info (display);
7570
7571 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
7572 return Qnil;
7573
7574 return Qt;
7575 }
7576
7577 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
7578 Sx_display_grayscale_p, 0, 1, 0,
7579 doc: /* Return t if the X display supports shades of gray.
7580 Note that color displays do support shades of gray.
7581 The optional argument DISPLAY specifies which display to ask about.
7582 DISPLAY should be either a frame or a display name (a string).
7583 If omitted or nil, that stands for the selected frame's display. */)
7584 (display)
7585 Lisp_Object display;
7586 {
7587 struct w32_display_info *dpyinfo = check_x_display_info (display);
7588
7589 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
7590 return Qnil;
7591
7592 return Qt;
7593 }
7594
7595 DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
7596 Sx_display_pixel_width, 0, 1, 0,
7597 doc: /* Returns the width in pixels of DISPLAY.
7598 The optional argument DISPLAY specifies which display to ask about.
7599 DISPLAY should be either a frame or a display name (a string).
7600 If omitted or nil, that stands for the selected frame's display. */)
7601 (display)
7602 Lisp_Object display;
7603 {
7604 struct w32_display_info *dpyinfo = check_x_display_info (display);
7605
7606 return make_number (dpyinfo->width);
7607 }
7608
7609 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
7610 Sx_display_pixel_height, 0, 1, 0,
7611 doc: /* Returns the height in pixels of DISPLAY.
7612 The optional argument DISPLAY specifies which display to ask about.
7613 DISPLAY should be either a frame or a display name (a string).
7614 If omitted or nil, that stands for the selected frame's display. */)
7615 (display)
7616 Lisp_Object display;
7617 {
7618 struct w32_display_info *dpyinfo = check_x_display_info (display);
7619
7620 return make_number (dpyinfo->height);
7621 }
7622
7623 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
7624 0, 1, 0,
7625 doc: /* Returns the number of bitplanes of DISPLAY.
7626 The optional argument DISPLAY specifies which display to ask about.
7627 DISPLAY should be either a frame or a display name (a string).
7628 If omitted or nil, that stands for the selected frame's display. */)
7629 (display)
7630 Lisp_Object display;
7631 {
7632 struct w32_display_info *dpyinfo = check_x_display_info (display);
7633
7634 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
7635 }
7636
7637 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
7638 0, 1, 0,
7639 doc: /* Returns the number of color cells of DISPLAY.
7640 The optional argument DISPLAY specifies which display to ask about.
7641 DISPLAY should be either a frame or a display name (a string).
7642 If omitted or nil, that stands for the selected frame's display. */)
7643 (display)
7644 Lisp_Object display;
7645 {
7646 struct w32_display_info *dpyinfo = check_x_display_info (display);
7647 HDC hdc;
7648 int cap;
7649
7650 hdc = GetDC (dpyinfo->root_window);
7651 if (dpyinfo->has_palette)
7652 cap = GetDeviceCaps (hdc,SIZEPALETTE);
7653 else
7654 cap = GetDeviceCaps (hdc,NUMCOLORS);
7655
7656 if (cap < 0)
7657 cap = 1 << (dpyinfo->n_planes * dpyinfo->n_cbits);
7658
7659 ReleaseDC (dpyinfo->root_window, hdc);
7660
7661 return make_number (cap);
7662 }
7663
7664 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
7665 Sx_server_max_request_size,
7666 0, 1, 0,
7667 doc: /* Returns the maximum request size of the server of DISPLAY.
7668 The optional argument DISPLAY specifies which display to ask about.
7669 DISPLAY should be either a frame or a display name (a string).
7670 If omitted or nil, that stands for the selected frame's display. */)
7671 (display)
7672 Lisp_Object display;
7673 {
7674 struct w32_display_info *dpyinfo = check_x_display_info (display);
7675
7676 return make_number (1);
7677 }
7678
7679 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
7680 doc: /* Returns the vendor ID string of the W32 system (Microsoft).
7681 The optional argument DISPLAY specifies which display to ask about.
7682 DISPLAY should be either a frame or a display name (a string).
7683 If omitted or nil, that stands for the selected frame's display. */)
7684 (display)
7685 Lisp_Object display;
7686 {
7687 return build_string ("Microsoft Corp.");
7688 }
7689
7690 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
7691 doc: /* Returns the version numbers of the server of DISPLAY.
7692 The value is a list of three integers: the major and minor
7693 version numbers, and the vendor-specific release
7694 number. See also the function `x-server-vendor'.
7695
7696 The optional argument DISPLAY specifies which display to ask about.
7697 DISPLAY should be either a frame or a display name (a string).
7698 If omitted or nil, that stands for the selected frame's display. */)
7699 (display)
7700 Lisp_Object display;
7701 {
7702 return Fcons (make_number (w32_major_version),
7703 Fcons (make_number (w32_minor_version),
7704 Fcons (make_number (w32_build_number), Qnil)));
7705 }
7706
7707 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
7708 doc: /* Returns the number of screens on the server of DISPLAY.
7709 The optional argument DISPLAY specifies which display to ask about.
7710 DISPLAY should be either a frame or a display name (a string).
7711 If omitted or nil, that stands for the selected frame's display. */)
7712 (display)
7713 Lisp_Object display;
7714 {
7715 return make_number (1);
7716 }
7717
7718 DEFUN ("x-display-mm-height", Fx_display_mm_height,
7719 Sx_display_mm_height, 0, 1, 0,
7720 doc: /* Returns the height in millimeters of DISPLAY.
7721 The optional argument DISPLAY specifies which display to ask about.
7722 DISPLAY should be either a frame or a display name (a string).
7723 If omitted or nil, that stands for the selected frame's display. */)
7724 (display)
7725 Lisp_Object display;
7726 {
7727 struct w32_display_info *dpyinfo = check_x_display_info (display);
7728 HDC hdc;
7729 int cap;
7730
7731 hdc = GetDC (dpyinfo->root_window);
7732
7733 cap = GetDeviceCaps (hdc, VERTSIZE);
7734
7735 ReleaseDC (dpyinfo->root_window, hdc);
7736
7737 return make_number (cap);
7738 }
7739
7740 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
7741 doc: /* Returns the width in millimeters of DISPLAY.
7742 The optional argument DISPLAY specifies which display to ask about.
7743 DISPLAY should be either a frame or a display name (a string).
7744 If omitted or nil, that stands for the selected frame's display. */)
7745 (display)
7746 Lisp_Object display;
7747 {
7748 struct w32_display_info *dpyinfo = check_x_display_info (display);
7749
7750 HDC hdc;
7751 int cap;
7752
7753 hdc = GetDC (dpyinfo->root_window);
7754
7755 cap = GetDeviceCaps (hdc, HORZSIZE);
7756
7757 ReleaseDC (dpyinfo->root_window, hdc);
7758
7759 return make_number (cap);
7760 }
7761
7762 DEFUN ("x-display-backing-store", Fx_display_backing_store,
7763 Sx_display_backing_store, 0, 1, 0,
7764 doc: /* Returns an indication of whether DISPLAY does backing store.
7765 The value may be `always', `when-mapped', or `not-useful'.
7766 The optional argument DISPLAY specifies which display to ask about.
7767 DISPLAY should be either a frame or a display name (a string).
7768 If omitted or nil, that stands for the selected frame's display. */)
7769 (display)
7770 Lisp_Object display;
7771 {
7772 return intern ("not-useful");
7773 }
7774
7775 DEFUN ("x-display-visual-class", Fx_display_visual_class,
7776 Sx_display_visual_class, 0, 1, 0,
7777 doc: /* Returns the visual class of DISPLAY.
7778 The value is one of the symbols `static-gray', `gray-scale',
7779 `static-color', `pseudo-color', `true-color', or `direct-color'.
7780
7781 The optional argument DISPLAY specifies which display to ask about.
7782 DISPLAY should be either a frame or a display name (a string).
7783 If omitted or nil, that stands for the selected frame's display. */)
7784 (display)
7785 Lisp_Object display;
7786 {
7787 struct w32_display_info *dpyinfo = check_x_display_info (display);
7788 Lisp_Object result = Qnil;
7789
7790 if (dpyinfo->has_palette)
7791 result = intern ("pseudo-color");
7792 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 1)
7793 result = intern ("static-grey");
7794 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 4)
7795 result = intern ("static-color");
7796 else if (dpyinfo->n_planes * dpyinfo->n_cbits > 8)
7797 result = intern ("true-color");
7798
7799 return result;
7800 }
7801
7802 DEFUN ("x-display-save-under", Fx_display_save_under,
7803 Sx_display_save_under, 0, 1, 0,
7804 doc: /* Returns t if DISPLAY supports the save-under feature.
7805 The optional argument DISPLAY specifies which display to ask about.
7806 DISPLAY should be either a frame or a display name (a string).
7807 If omitted or nil, that stands for the selected frame's display. */)
7808 (display)
7809 Lisp_Object display;
7810 {
7811 return Qnil;
7812 }
7813 \f
7814 int
7815 x_pixel_width (f)
7816 register struct frame *f;
7817 {
7818 return PIXEL_WIDTH (f);
7819 }
7820
7821 int
7822 x_pixel_height (f)
7823 register struct frame *f;
7824 {
7825 return PIXEL_HEIGHT (f);
7826 }
7827
7828 int
7829 x_char_width (f)
7830 register struct frame *f;
7831 {
7832 return FONT_WIDTH (f->output_data.w32->font);
7833 }
7834
7835 int
7836 x_char_height (f)
7837 register struct frame *f;
7838 {
7839 return f->output_data.w32->line_height;
7840 }
7841
7842 int
7843 x_screen_planes (f)
7844 register struct frame *f;
7845 {
7846 return FRAME_W32_DISPLAY_INFO (f)->n_planes;
7847 }
7848 \f
7849 /* Return the display structure for the display named NAME.
7850 Open a new connection if necessary. */
7851
7852 struct w32_display_info *
7853 x_display_info_for_name (name)
7854 Lisp_Object name;
7855 {
7856 Lisp_Object names;
7857 struct w32_display_info *dpyinfo;
7858
7859 CHECK_STRING (name);
7860
7861 for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
7862 dpyinfo;
7863 dpyinfo = dpyinfo->next, names = XCDR (names))
7864 {
7865 Lisp_Object tem;
7866 tem = Fstring_equal (XCAR (XCAR (names)), name);
7867 if (!NILP (tem))
7868 return dpyinfo;
7869 }
7870
7871 /* Use this general default value to start with. */
7872 Vx_resource_name = Vinvocation_name;
7873
7874 validate_x_resource_name ();
7875
7876 dpyinfo = w32_term_init (name, (unsigned char *)0,
7877 (char *) XSTRING (Vx_resource_name)->data);
7878
7879 if (dpyinfo == 0)
7880 error ("Cannot connect to server %s", XSTRING (name)->data);
7881
7882 w32_in_use = 1;
7883 XSETFASTINT (Vwindow_system_version, 3);
7884
7885 return dpyinfo;
7886 }
7887
7888 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
7889 1, 3, 0, doc: /* Open a connection to a server.
7890 DISPLAY is the name of the display to connect to.
7891 Optional second arg XRM-STRING is a string of resources in xrdb format.
7892 If the optional third arg MUST-SUCCEED is non-nil,
7893 terminate Emacs if we can't open the connection. */)
7894 (display, xrm_string, must_succeed)
7895 Lisp_Object display, xrm_string, must_succeed;
7896 {
7897 unsigned char *xrm_option;
7898 struct w32_display_info *dpyinfo;
7899
7900 /* If initialization has already been done, return now to avoid
7901 overwriting critical parts of one_w32_display_info. */
7902 if (w32_in_use)
7903 return Qnil;
7904
7905 CHECK_STRING (display);
7906 if (! NILP (xrm_string))
7907 CHECK_STRING (xrm_string);
7908
7909 if (! EQ (Vwindow_system, intern ("w32")))
7910 error ("Not using Microsoft Windows");
7911
7912 /* Allow color mapping to be defined externally; first look in user's
7913 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
7914 {
7915 Lisp_Object color_file;
7916 struct gcpro gcpro1;
7917
7918 color_file = build_string("~/rgb.txt");
7919
7920 GCPRO1 (color_file);
7921
7922 if (NILP (Ffile_readable_p (color_file)))
7923 color_file =
7924 Fexpand_file_name (build_string ("rgb.txt"),
7925 Fsymbol_value (intern ("data-directory")));
7926
7927 Vw32_color_map = Fw32_load_color_file (color_file);
7928
7929 UNGCPRO;
7930 }
7931 if (NILP (Vw32_color_map))
7932 Vw32_color_map = Fw32_default_color_map ();
7933
7934 if (! NILP (xrm_string))
7935 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
7936 else
7937 xrm_option = (unsigned char *) 0;
7938
7939 /* Use this general default value to start with. */
7940 /* First remove .exe suffix from invocation-name - it looks ugly. */
7941 {
7942 char basename[ MAX_PATH ], *str;
7943
7944 strcpy (basename, XSTRING (Vinvocation_name)->data);
7945 str = strrchr (basename, '.');
7946 if (str) *str = 0;
7947 Vinvocation_name = build_string (basename);
7948 }
7949 Vx_resource_name = Vinvocation_name;
7950
7951 validate_x_resource_name ();
7952
7953 /* This is what opens the connection and sets x_current_display.
7954 This also initializes many symbols, such as those used for input. */
7955 dpyinfo = w32_term_init (display, xrm_option,
7956 (char *) XSTRING (Vx_resource_name)->data);
7957
7958 if (dpyinfo == 0)
7959 {
7960 if (!NILP (must_succeed))
7961 fatal ("Cannot connect to server %s.\n",
7962 XSTRING (display)->data);
7963 else
7964 error ("Cannot connect to server %s", XSTRING (display)->data);
7965 }
7966
7967 w32_in_use = 1;
7968
7969 XSETFASTINT (Vwindow_system_version, 3);
7970 return Qnil;
7971 }
7972
7973 DEFUN ("x-close-connection", Fx_close_connection,
7974 Sx_close_connection, 1, 1, 0,
7975 doc: /* Close the connection to DISPLAY's server.
7976 For DISPLAY, specify either a frame or a display name (a string).
7977 If DISPLAY is nil, that stands for the selected frame's display. */)
7978 (display)
7979 Lisp_Object display;
7980 {
7981 struct w32_display_info *dpyinfo = check_x_display_info (display);
7982 int i;
7983
7984 if (dpyinfo->reference_count > 0)
7985 error ("Display still has frames on it");
7986
7987 BLOCK_INPUT;
7988 /* Free the fonts in the font table. */
7989 for (i = 0; i < dpyinfo->n_fonts; i++)
7990 if (dpyinfo->font_table[i].name)
7991 {
7992 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
7993 xfree (dpyinfo->font_table[i].full_name);
7994 xfree (dpyinfo->font_table[i].name);
7995 w32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
7996 }
7997 x_destroy_all_bitmaps (dpyinfo);
7998
7999 x_delete_display (dpyinfo);
8000 UNBLOCK_INPUT;
8001
8002 return Qnil;
8003 }
8004
8005 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
8006 doc: /* Return the list of display names that Emacs has connections to. */)
8007 ()
8008 {
8009 Lisp_Object tail, result;
8010
8011 result = Qnil;
8012 for (tail = w32_display_name_list; ! NILP (tail); tail = XCDR (tail))
8013 result = Fcons (XCAR (XCAR (tail)), result);
8014
8015 return result;
8016 }
8017
8018 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
8019 doc: /* This is a noop on W32 systems. */)
8020 (on, display)
8021 Lisp_Object display, on;
8022 {
8023 return Qnil;
8024 }
8025
8026 \f
8027 \f
8028 /***********************************************************************
8029 Image types
8030 ***********************************************************************/
8031
8032 /* Value is the number of elements of vector VECTOR. */
8033
8034 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
8035
8036 /* List of supported image types. Use define_image_type to add new
8037 types. Use lookup_image_type to find a type for a given symbol. */
8038
8039 static struct image_type *image_types;
8040
8041 /* The symbol `image' which is the car of the lists used to represent
8042 images in Lisp. */
8043
8044 extern Lisp_Object Qimage;
8045
8046 /* The symbol `xbm' which is used as the type symbol for XBM images. */
8047
8048 Lisp_Object Qxbm;
8049
8050 /* Keywords. */
8051
8052 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
8053 extern Lisp_Object QCdata;
8054 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
8055 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
8056 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
8057
8058 /* Other symbols. */
8059
8060 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
8061
8062 /* Time in seconds after which images should be removed from the cache
8063 if not displayed. */
8064
8065 Lisp_Object Vimage_cache_eviction_delay;
8066
8067 /* Function prototypes. */
8068
8069 static void define_image_type P_ ((struct image_type *type));
8070 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
8071 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
8072 static void x_laplace P_ ((struct frame *, struct image *));
8073 static void x_emboss P_ ((struct frame *, struct image *));
8074 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
8075 Lisp_Object));
8076
8077
8078 /* Define a new image type from TYPE. This adds a copy of TYPE to
8079 image_types and adds the symbol *TYPE->type to Vimage_types. */
8080
8081 static void
8082 define_image_type (type)
8083 struct image_type *type;
8084 {
8085 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
8086 The initialized data segment is read-only. */
8087 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
8088 bcopy (type, p, sizeof *p);
8089 p->next = image_types;
8090 image_types = p;
8091 Vimage_types = Fcons (*p->type, Vimage_types);
8092 }
8093
8094
8095 /* Look up image type SYMBOL, and return a pointer to its image_type
8096 structure. Value is null if SYMBOL is not a known image type. */
8097
8098 static INLINE struct image_type *
8099 lookup_image_type (symbol)
8100 Lisp_Object symbol;
8101 {
8102 struct image_type *type;
8103
8104 for (type = image_types; type; type = type->next)
8105 if (EQ (symbol, *type->type))
8106 break;
8107
8108 return type;
8109 }
8110
8111
8112 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
8113 valid image specification is a list whose car is the symbol
8114 `image', and whose rest is a property list. The property list must
8115 contain a value for key `:type'. That value must be the name of a
8116 supported image type. The rest of the property list depends on the
8117 image type. */
8118
8119 int
8120 valid_image_p (object)
8121 Lisp_Object object;
8122 {
8123 int valid_p = 0;
8124
8125 if (CONSP (object) && EQ (XCAR (object), Qimage))
8126 {
8127 Lisp_Object tem;
8128
8129 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
8130 if (EQ (XCAR (tem), QCtype))
8131 {
8132 tem = XCDR (tem);
8133 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
8134 {
8135 struct image_type *type;
8136 type = lookup_image_type (XCAR (tem));
8137 if (type)
8138 valid_p = type->valid_p (object);
8139 }
8140
8141 break;
8142 }
8143 }
8144
8145 return valid_p;
8146 }
8147
8148
8149 /* Log error message with format string FORMAT and argument ARG.
8150 Signaling an error, e.g. when an image cannot be loaded, is not a
8151 good idea because this would interrupt redisplay, and the error
8152 message display would lead to another redisplay. This function
8153 therefore simply displays a message. */
8154
8155 static void
8156 image_error (format, arg1, arg2)
8157 char *format;
8158 Lisp_Object arg1, arg2;
8159 {
8160 add_to_log (format, arg1, arg2);
8161 }
8162
8163
8164 \f
8165 /***********************************************************************
8166 Image specifications
8167 ***********************************************************************/
8168
8169 enum image_value_type
8170 {
8171 IMAGE_DONT_CHECK_VALUE_TYPE,
8172 IMAGE_STRING_VALUE,
8173 IMAGE_STRING_OR_NIL_VALUE,
8174 IMAGE_SYMBOL_VALUE,
8175 IMAGE_POSITIVE_INTEGER_VALUE,
8176 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
8177 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
8178 IMAGE_ASCENT_VALUE,
8179 IMAGE_INTEGER_VALUE,
8180 IMAGE_FUNCTION_VALUE,
8181 IMAGE_NUMBER_VALUE,
8182 IMAGE_BOOL_VALUE
8183 };
8184
8185 /* Structure used when parsing image specifications. */
8186
8187 struct image_keyword
8188 {
8189 /* Name of keyword. */
8190 char *name;
8191
8192 /* The type of value allowed. */
8193 enum image_value_type type;
8194
8195 /* Non-zero means key must be present. */
8196 int mandatory_p;
8197
8198 /* Used to recognize duplicate keywords in a property list. */
8199 int count;
8200
8201 /* The value that was found. */
8202 Lisp_Object value;
8203 };
8204
8205
8206 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
8207 int, Lisp_Object));
8208 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
8209
8210
8211 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
8212 has the format (image KEYWORD VALUE ...). One of the keyword/
8213 value pairs must be `:type TYPE'. KEYWORDS is a vector of
8214 image_keywords structures of size NKEYWORDS describing other
8215 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
8216
8217 static int
8218 parse_image_spec (spec, keywords, nkeywords, type)
8219 Lisp_Object spec;
8220 struct image_keyword *keywords;
8221 int nkeywords;
8222 Lisp_Object type;
8223 {
8224 int i;
8225 Lisp_Object plist;
8226
8227 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
8228 return 0;
8229
8230 plist = XCDR (spec);
8231 while (CONSP (plist))
8232 {
8233 Lisp_Object key, value;
8234
8235 /* First element of a pair must be a symbol. */
8236 key = XCAR (plist);
8237 plist = XCDR (plist);
8238 if (!SYMBOLP (key))
8239 return 0;
8240
8241 /* There must follow a value. */
8242 if (!CONSP (plist))
8243 return 0;
8244 value = XCAR (plist);
8245 plist = XCDR (plist);
8246
8247 /* Find key in KEYWORDS. Error if not found. */
8248 for (i = 0; i < nkeywords; ++i)
8249 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
8250 break;
8251
8252 if (i == nkeywords)
8253 continue;
8254
8255 /* Record that we recognized the keyword. If a keywords
8256 was found more than once, it's an error. */
8257 keywords[i].value = value;
8258 ++keywords[i].count;
8259
8260 if (keywords[i].count > 1)
8261 return 0;
8262
8263 /* Check type of value against allowed type. */
8264 switch (keywords[i].type)
8265 {
8266 case IMAGE_STRING_VALUE:
8267 if (!STRINGP (value))
8268 return 0;
8269 break;
8270
8271 case IMAGE_STRING_OR_NIL_VALUE:
8272 if (!STRINGP (value) && !NILP (value))
8273 return 0;
8274 break;
8275
8276 case IMAGE_SYMBOL_VALUE:
8277 if (!SYMBOLP (value))
8278 return 0;
8279 break;
8280
8281 case IMAGE_POSITIVE_INTEGER_VALUE:
8282 if (!INTEGERP (value) || XINT (value) <= 0)
8283 return 0;
8284 break;
8285
8286 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
8287 if (INTEGERP (value) && XINT (value) >= 0)
8288 break;
8289 if (CONSP (value)
8290 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
8291 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
8292 break;
8293 return 0;
8294
8295 case IMAGE_ASCENT_VALUE:
8296 if (SYMBOLP (value) && EQ (value, Qcenter))
8297 break;
8298 else if (INTEGERP (value)
8299 && XINT (value) >= 0
8300 && XINT (value) <= 100)
8301 break;
8302 return 0;
8303
8304 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
8305 if (!INTEGERP (value) || XINT (value) < 0)
8306 return 0;
8307 break;
8308
8309 case IMAGE_DONT_CHECK_VALUE_TYPE:
8310 break;
8311
8312 case IMAGE_FUNCTION_VALUE:
8313 value = indirect_function (value);
8314 if (SUBRP (value)
8315 || COMPILEDP (value)
8316 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
8317 break;
8318 return 0;
8319
8320 case IMAGE_NUMBER_VALUE:
8321 if (!INTEGERP (value) && !FLOATP (value))
8322 return 0;
8323 break;
8324
8325 case IMAGE_INTEGER_VALUE:
8326 if (!INTEGERP (value))
8327 return 0;
8328 break;
8329
8330 case IMAGE_BOOL_VALUE:
8331 if (!NILP (value) && !EQ (value, Qt))
8332 return 0;
8333 break;
8334
8335 default:
8336 abort ();
8337 break;
8338 }
8339
8340 if (EQ (key, QCtype) && !EQ (type, value))
8341 return 0;
8342 }
8343
8344 /* Check that all mandatory fields are present. */
8345 for (i = 0; i < nkeywords; ++i)
8346 if (keywords[i].mandatory_p && keywords[i].count == 0)
8347 return 0;
8348
8349 return NILP (plist);
8350 }
8351
8352
8353 /* Return the value of KEY in image specification SPEC. Value is nil
8354 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
8355 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
8356
8357 static Lisp_Object
8358 image_spec_value (spec, key, found)
8359 Lisp_Object spec, key;
8360 int *found;
8361 {
8362 Lisp_Object tail;
8363
8364 xassert (valid_image_p (spec));
8365
8366 for (tail = XCDR (spec);
8367 CONSP (tail) && CONSP (XCDR (tail));
8368 tail = XCDR (XCDR (tail)))
8369 {
8370 if (EQ (XCAR (tail), key))
8371 {
8372 if (found)
8373 *found = 1;
8374 return XCAR (XCDR (tail));
8375 }
8376 }
8377
8378 if (found)
8379 *found = 0;
8380 return Qnil;
8381 }
8382
8383
8384
8385 \f
8386 /***********************************************************************
8387 Image type independent image structures
8388 ***********************************************************************/
8389
8390 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
8391 static void free_image P_ ((struct frame *f, struct image *img));
8392
8393
8394 /* Allocate and return a new image structure for image specification
8395 SPEC. SPEC has a hash value of HASH. */
8396
8397 static struct image *
8398 make_image (spec, hash)
8399 Lisp_Object spec;
8400 unsigned hash;
8401 {
8402 struct image *img = (struct image *) xmalloc (sizeof *img);
8403
8404 xassert (valid_image_p (spec));
8405 bzero (img, sizeof *img);
8406 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
8407 xassert (img->type != NULL);
8408 img->spec = spec;
8409 img->data.lisp_val = Qnil;
8410 img->ascent = DEFAULT_IMAGE_ASCENT;
8411 img->hash = hash;
8412 return img;
8413 }
8414
8415
8416 /* Free image IMG which was used on frame F, including its resources. */
8417
8418 static void
8419 free_image (f, img)
8420 struct frame *f;
8421 struct image *img;
8422 {
8423 if (img)
8424 {
8425 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8426
8427 /* Remove IMG from the hash table of its cache. */
8428 if (img->prev)
8429 img->prev->next = img->next;
8430 else
8431 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
8432
8433 if (img->next)
8434 img->next->prev = img->prev;
8435
8436 c->images[img->id] = NULL;
8437
8438 /* Free resources, then free IMG. */
8439 img->type->free (f, img);
8440 xfree (img);
8441 }
8442 }
8443
8444
8445 /* Prepare image IMG for display on frame F. Must be called before
8446 drawing an image. */
8447
8448 void
8449 prepare_image_for_display (f, img)
8450 struct frame *f;
8451 struct image *img;
8452 {
8453 EMACS_TIME t;
8454
8455 /* We're about to display IMG, so set its timestamp to `now'. */
8456 EMACS_GET_TIME (t);
8457 img->timestamp = EMACS_SECS (t);
8458
8459 /* If IMG doesn't have a pixmap yet, load it now, using the image
8460 type dependent loader function. */
8461 if (img->pixmap == 0 && !img->load_failed_p)
8462 img->load_failed_p = img->type->load (f, img) == 0;
8463 }
8464
8465
8466 /* Value is the number of pixels for the ascent of image IMG when
8467 drawn in face FACE. */
8468
8469 int
8470 image_ascent (img, face)
8471 struct image *img;
8472 struct face *face;
8473 {
8474 int height = img->height + img->vmargin;
8475 int ascent;
8476
8477 if (img->ascent == CENTERED_IMAGE_ASCENT)
8478 {
8479 if (face->font)
8480 ascent = height / 2 - (FONT_DESCENT(face->font)
8481 - FONT_BASE(face->font)) / 2;
8482 else
8483 ascent = height / 2;
8484 }
8485 else
8486 ascent = height * img->ascent / 100.0;
8487
8488 return ascent;
8489 }
8490
8491
8492 \f
8493 /* Image background colors. */
8494
8495 static unsigned long
8496 four_corners_best (ximg, width, height)
8497 XImage *ximg;
8498 unsigned long width, height;
8499 {
8500 #if 0 /* TODO: Image support. */
8501 unsigned long corners[4], best;
8502 int i, best_count;
8503
8504 /* Get the colors at the corners of ximg. */
8505 corners[0] = XGetPixel (ximg, 0, 0);
8506 corners[1] = XGetPixel (ximg, width - 1, 0);
8507 corners[2] = XGetPixel (ximg, width - 1, height - 1);
8508 corners[3] = XGetPixel (ximg, 0, height - 1);
8509
8510 /* Choose the most frequently found color as background. */
8511 for (i = best_count = 0; i < 4; ++i)
8512 {
8513 int j, n;
8514
8515 for (j = n = 0; j < 4; ++j)
8516 if (corners[i] == corners[j])
8517 ++n;
8518
8519 if (n > best_count)
8520 best = corners[i], best_count = n;
8521 }
8522
8523 return best;
8524 #else
8525 return 0;
8526 #endif
8527 }
8528
8529 /* Return the `background' field of IMG. If IMG doesn't have one yet,
8530 it is guessed heuristically. If non-zero, XIMG is an existing XImage
8531 object to use for the heuristic. */
8532
8533 unsigned long
8534 image_background (img, f, ximg)
8535 struct image *img;
8536 struct frame *f;
8537 XImage *ximg;
8538 {
8539 if (! img->background_valid)
8540 /* IMG doesn't have a background yet, try to guess a reasonable value. */
8541 {
8542 #if 0 /* TODO: Image support. */
8543 int free_ximg = !ximg;
8544
8545 if (! ximg)
8546 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8547 0, 0, img->width, img->height, ~0, ZPixmap);
8548
8549 img->background = four_corners_best (ximg, img->width, img->height);
8550
8551 if (free_ximg)
8552 XDestroyImage (ximg);
8553
8554 img->background_valid = 1;
8555 #endif
8556 }
8557
8558 return img->background;
8559 }
8560
8561 /* Return the `background_transparent' field of IMG. If IMG doesn't
8562 have one yet, it is guessed heuristically. If non-zero, MASK is an
8563 existing XImage object to use for the heuristic. */
8564
8565 int
8566 image_background_transparent (img, f, mask)
8567 struct image *img;
8568 struct frame *f;
8569 XImage *mask;
8570 {
8571 if (! img->background_transparent_valid)
8572 /* IMG doesn't have a background yet, try to guess a reasonable value. */
8573 {
8574 #if 0 /* TODO: Image support. */
8575 if (img->mask)
8576 {
8577 int free_mask = !mask;
8578
8579 if (! mask)
8580 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
8581 0, 0, img->width, img->height, ~0, ZPixmap);
8582
8583 img->background_transparent
8584 = !four_corners_best (mask, img->width, img->height);
8585
8586 if (free_mask)
8587 XDestroyImage (mask);
8588 }
8589 else
8590 #endif
8591 img->background_transparent = 0;
8592
8593 img->background_transparent_valid = 1;
8594 }
8595
8596 return img->background_transparent;
8597 }
8598
8599 \f
8600 /***********************************************************************
8601 Helper functions for X image types
8602 ***********************************************************************/
8603
8604 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
8605 int, int));
8606 static void x_clear_image P_ ((struct frame *f, struct image *img));
8607 static unsigned long x_alloc_image_color P_ ((struct frame *f,
8608 struct image *img,
8609 Lisp_Object color_name,
8610 unsigned long dflt));
8611
8612
8613 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
8614 free the pixmap if any. MASK_P non-zero means clear the mask
8615 pixmap if any. COLORS_P non-zero means free colors allocated for
8616 the image, if any. */
8617
8618 static void
8619 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
8620 struct frame *f;
8621 struct image *img;
8622 int pixmap_p, mask_p, colors_p;
8623 {
8624 #if 0 /* TODO: W32 image support */
8625 if (pixmap_p && img->pixmap)
8626 {
8627 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8628 img->pixmap = None;
8629 img->background_valid = 0;
8630 }
8631
8632 if (mask_p && img->mask)
8633 {
8634 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8635 img->mask = None;
8636 img->background_transparent_valid = 0;
8637 }
8638
8639 if (colors_p && img->ncolors)
8640 {
8641 x_free_colors (f, img->colors, img->ncolors);
8642 xfree (img->colors);
8643 img->colors = NULL;
8644 img->ncolors = 0;
8645 }
8646 #endif
8647 }
8648
8649 /* Free X resources of image IMG which is used on frame F. */
8650
8651 static void
8652 x_clear_image (f, img)
8653 struct frame *f;
8654 struct image *img;
8655 {
8656 #if 0 /* TODO: W32 image support */
8657
8658 if (img->pixmap)
8659 {
8660 BLOCK_INPUT;
8661 XFreePixmap (NULL, img->pixmap);
8662 img->pixmap = 0;
8663 UNBLOCK_INPUT;
8664 }
8665
8666 if (img->ncolors)
8667 {
8668 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
8669
8670 /* If display has an immutable color map, freeing colors is not
8671 necessary and some servers don't allow it. So don't do it. */
8672 if (class != StaticColor
8673 && class != StaticGray
8674 && class != TrueColor)
8675 {
8676 Colormap cmap;
8677 BLOCK_INPUT;
8678 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
8679 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
8680 img->ncolors, 0);
8681 UNBLOCK_INPUT;
8682 }
8683
8684 xfree (img->colors);
8685 img->colors = NULL;
8686 img->ncolors = 0;
8687 }
8688 #endif
8689 }
8690
8691
8692 /* Allocate color COLOR_NAME for image IMG on frame F. If color
8693 cannot be allocated, use DFLT. Add a newly allocated color to
8694 IMG->colors, so that it can be freed again. Value is the pixel
8695 color. */
8696
8697 static unsigned long
8698 x_alloc_image_color (f, img, color_name, dflt)
8699 struct frame *f;
8700 struct image *img;
8701 Lisp_Object color_name;
8702 unsigned long dflt;
8703 {
8704 #if 0 /* TODO: allocing colors. */
8705 XColor color;
8706 unsigned long result;
8707
8708 xassert (STRINGP (color_name));
8709
8710 if (w32_defined_color (f, XSTRING (color_name)->data, &color, 1))
8711 {
8712 /* This isn't called frequently so we get away with simply
8713 reallocating the color vector to the needed size, here. */
8714 ++img->ncolors;
8715 img->colors =
8716 (unsigned long *) xrealloc (img->colors,
8717 img->ncolors * sizeof *img->colors);
8718 img->colors[img->ncolors - 1] = color.pixel;
8719 result = color.pixel;
8720 }
8721 else
8722 result = dflt;
8723 return result;
8724 #endif
8725 return 0;
8726 }
8727
8728
8729 \f
8730 /***********************************************************************
8731 Image Cache
8732 ***********************************************************************/
8733
8734 static void cache_image P_ ((struct frame *f, struct image *img));
8735 static void postprocess_image P_ ((struct frame *, struct image *));
8736
8737
8738 /* Return a new, initialized image cache that is allocated from the
8739 heap. Call free_image_cache to free an image cache. */
8740
8741 struct image_cache *
8742 make_image_cache ()
8743 {
8744 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
8745 int size;
8746
8747 bzero (c, sizeof *c);
8748 c->size = 50;
8749 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
8750 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
8751 c->buckets = (struct image **) xmalloc (size);
8752 bzero (c->buckets, size);
8753 return c;
8754 }
8755
8756
8757 /* Free image cache of frame F. Be aware that X frames share images
8758 caches. */
8759
8760 void
8761 free_image_cache (f)
8762 struct frame *f;
8763 {
8764 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8765 if (c)
8766 {
8767 int i;
8768
8769 /* Cache should not be referenced by any frame when freed. */
8770 xassert (c->refcount == 0);
8771
8772 for (i = 0; i < c->used; ++i)
8773 free_image (f, c->images[i]);
8774 xfree (c->images);
8775 xfree (c);
8776 xfree (c->buckets);
8777 FRAME_X_IMAGE_CACHE (f) = NULL;
8778 }
8779 }
8780
8781
8782 /* Clear image cache of frame F. FORCE_P non-zero means free all
8783 images. FORCE_P zero means clear only images that haven't been
8784 displayed for some time. Should be called from time to time to
8785 reduce the number of loaded images. If image-eviction-seconds is
8786 non-nil, this frees images in the cache which weren't displayed for
8787 at least that many seconds. */
8788
8789 void
8790 clear_image_cache (f, force_p)
8791 struct frame *f;
8792 int force_p;
8793 {
8794 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8795
8796 if (c && INTEGERP (Vimage_cache_eviction_delay))
8797 {
8798 EMACS_TIME t;
8799 unsigned long old;
8800 int i, any_freed_p = 0;
8801
8802 EMACS_GET_TIME (t);
8803 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
8804
8805 for (i = 0; i < c->used; ++i)
8806 {
8807 struct image *img = c->images[i];
8808 if (img != NULL
8809 && (force_p
8810 || (img->timestamp > old)))
8811 {
8812 free_image (f, img);
8813 any_freed_p = 1;
8814 }
8815 }
8816
8817 /* We may be clearing the image cache because, for example,
8818 Emacs was iconified for a longer period of time. In that
8819 case, current matrices may still contain references to
8820 images freed above. So, clear these matrices. */
8821 if (any_freed_p)
8822 {
8823 clear_current_matrices (f);
8824 ++windows_or_buffers_changed;
8825 }
8826 }
8827 }
8828
8829
8830 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
8831 0, 1, 0,
8832 doc: /* Clear the image cache of FRAME.
8833 FRAME nil or omitted means use the selected frame.
8834 FRAME t means clear the image caches of all frames. */)
8835 (frame)
8836 Lisp_Object frame;
8837 {
8838 if (EQ (frame, Qt))
8839 {
8840 Lisp_Object tail;
8841
8842 FOR_EACH_FRAME (tail, frame)
8843 if (FRAME_W32_P (XFRAME (frame)))
8844 clear_image_cache (XFRAME (frame), 1);
8845 }
8846 else
8847 clear_image_cache (check_x_frame (frame), 1);
8848
8849 return Qnil;
8850 }
8851
8852
8853 /* Compute masks and transform image IMG on frame F, as specified
8854 by the image's specification, */
8855
8856 static void
8857 postprocess_image (f, img)
8858 struct frame *f;
8859 struct image *img;
8860 {
8861 #if 0 /* TODO: image support. */
8862 /* Manipulation of the image's mask. */
8863 if (img->pixmap)
8864 {
8865 Lisp_Object conversion, spec;
8866 Lisp_Object mask;
8867
8868 spec = img->spec;
8869
8870 /* `:heuristic-mask t'
8871 `:mask heuristic'
8872 means build a mask heuristically.
8873 `:heuristic-mask (R G B)'
8874 `:mask (heuristic (R G B))'
8875 means build a mask from color (R G B) in the
8876 image.
8877 `:mask nil'
8878 means remove a mask, if any. */
8879
8880 mask = image_spec_value (spec, QCheuristic_mask, NULL);
8881 if (!NILP (mask))
8882 x_build_heuristic_mask (f, img, mask);
8883 else
8884 {
8885 int found_p;
8886
8887 mask = image_spec_value (spec, QCmask, &found_p);
8888
8889 if (EQ (mask, Qheuristic))
8890 x_build_heuristic_mask (f, img, Qt);
8891 else if (CONSP (mask)
8892 && EQ (XCAR (mask), Qheuristic))
8893 {
8894 if (CONSP (XCDR (mask)))
8895 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
8896 else
8897 x_build_heuristic_mask (f, img, XCDR (mask));
8898 }
8899 else if (NILP (mask) && found_p && img->mask)
8900 {
8901 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8902 img->mask = NULL;
8903 }
8904 }
8905
8906
8907 /* Should we apply an image transformation algorithm? */
8908 conversion = image_spec_value (spec, QCconversion, NULL);
8909 if (EQ (conversion, Qdisabled))
8910 x_disable_image (f, img);
8911 else if (EQ (conversion, Qlaplace))
8912 x_laplace (f, img);
8913 else if (EQ (conversion, Qemboss))
8914 x_emboss (f, img);
8915 else if (CONSP (conversion)
8916 && EQ (XCAR (conversion), Qedge_detection))
8917 {
8918 Lisp_Object tem;
8919 tem = XCDR (conversion);
8920 if (CONSP (tem))
8921 x_edge_detection (f, img,
8922 Fplist_get (tem, QCmatrix),
8923 Fplist_get (tem, QCcolor_adjustment));
8924 }
8925 }
8926 #endif
8927 }
8928
8929
8930 /* Return the id of image with Lisp specification SPEC on frame F.
8931 SPEC must be a valid Lisp image specification (see valid_image_p). */
8932
8933 int
8934 lookup_image (f, spec)
8935 struct frame *f;
8936 Lisp_Object spec;
8937 {
8938 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8939 struct image *img;
8940 int i;
8941 unsigned hash;
8942 struct gcpro gcpro1;
8943 EMACS_TIME now;
8944
8945 /* F must be a window-system frame, and SPEC must be a valid image
8946 specification. */
8947 xassert (FRAME_WINDOW_P (f));
8948 xassert (valid_image_p (spec));
8949
8950 GCPRO1 (spec);
8951
8952 /* Look up SPEC in the hash table of the image cache. */
8953 hash = sxhash (spec, 0);
8954 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
8955
8956 for (img = c->buckets[i]; img; img = img->next)
8957 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
8958 break;
8959
8960 /* If not found, create a new image and cache it. */
8961 if (img == NULL)
8962 {
8963 extern Lisp_Object Qpostscript;
8964
8965 BLOCK_INPUT;
8966 img = make_image (spec, hash);
8967 cache_image (f, img);
8968 img->load_failed_p = img->type->load (f, img) == 0;
8969
8970 /* If we can't load the image, and we don't have a width and
8971 height, use some arbitrary width and height so that we can
8972 draw a rectangle for it. */
8973 if (img->load_failed_p)
8974 {
8975 Lisp_Object value;
8976
8977 value = image_spec_value (spec, QCwidth, NULL);
8978 img->width = (INTEGERP (value)
8979 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
8980 value = image_spec_value (spec, QCheight, NULL);
8981 img->height = (INTEGERP (value)
8982 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
8983 }
8984 else
8985 {
8986 /* Handle image type independent image attributes
8987 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF',
8988 `:background COLOR'. */
8989 Lisp_Object ascent, margin, relief, bg;
8990
8991 ascent = image_spec_value (spec, QCascent, NULL);
8992 if (INTEGERP (ascent))
8993 img->ascent = XFASTINT (ascent);
8994 else if (EQ (ascent, Qcenter))
8995 img->ascent = CENTERED_IMAGE_ASCENT;
8996
8997 margin = image_spec_value (spec, QCmargin, NULL);
8998 if (INTEGERP (margin) && XINT (margin) >= 0)
8999 img->vmargin = img->hmargin = XFASTINT (margin);
9000 else if (CONSP (margin) && INTEGERP (XCAR (margin))
9001 && INTEGERP (XCDR (margin)))
9002 {
9003 if (XINT (XCAR (margin)) > 0)
9004 img->hmargin = XFASTINT (XCAR (margin));
9005 if (XINT (XCDR (margin)) > 0)
9006 img->vmargin = XFASTINT (XCDR (margin));
9007 }
9008
9009 relief = image_spec_value (spec, QCrelief, NULL);
9010 if (INTEGERP (relief))
9011 {
9012 img->relief = XINT (relief);
9013 img->hmargin += abs (img->relief);
9014 img->vmargin += abs (img->relief);
9015 }
9016
9017 if (! img->background_valid)
9018 {
9019 bg = image_spec_value (img->spec, QCbackground, NULL);
9020 if (!NILP (bg))
9021 {
9022 img->background
9023 = x_alloc_image_color (f, img, bg,
9024 FRAME_BACKGROUND_PIXEL (f));
9025 img->background_valid = 1;
9026 }
9027 }
9028
9029 /* Do image transformations and compute masks, unless we
9030 don't have the image yet. */
9031 if (!EQ (*img->type->type, Qpostscript))
9032 postprocess_image (f, img);
9033 }
9034
9035 UNBLOCK_INPUT;
9036 xassert (!interrupt_input_blocked);
9037 }
9038
9039 /* We're using IMG, so set its timestamp to `now'. */
9040 EMACS_GET_TIME (now);
9041 img->timestamp = EMACS_SECS (now);
9042
9043 UNGCPRO;
9044
9045 /* Value is the image id. */
9046 return img->id;
9047 }
9048
9049
9050 /* Cache image IMG in the image cache of frame F. */
9051
9052 static void
9053 cache_image (f, img)
9054 struct frame *f;
9055 struct image *img;
9056 {
9057 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9058 int i;
9059
9060 /* Find a free slot in c->images. */
9061 for (i = 0; i < c->used; ++i)
9062 if (c->images[i] == NULL)
9063 break;
9064
9065 /* If no free slot found, maybe enlarge c->images. */
9066 if (i == c->used && c->used == c->size)
9067 {
9068 c->size *= 2;
9069 c->images = (struct image **) xrealloc (c->images,
9070 c->size * sizeof *c->images);
9071 }
9072
9073 /* Add IMG to c->images, and assign IMG an id. */
9074 c->images[i] = img;
9075 img->id = i;
9076 if (i == c->used)
9077 ++c->used;
9078
9079 /* Add IMG to the cache's hash table. */
9080 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
9081 img->next = c->buckets[i];
9082 if (img->next)
9083 img->next->prev = img;
9084 img->prev = NULL;
9085 c->buckets[i] = img;
9086 }
9087
9088
9089 /* Call FN on every image in the image cache of frame F. Used to mark
9090 Lisp Objects in the image cache. */
9091
9092 void
9093 forall_images_in_image_cache (f, fn)
9094 struct frame *f;
9095 void (*fn) P_ ((struct image *img));
9096 {
9097 if (FRAME_LIVE_P (f) && FRAME_W32_P (f))
9098 {
9099 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9100 if (c)
9101 {
9102 int i;
9103 for (i = 0; i < c->used; ++i)
9104 if (c->images[i])
9105 fn (c->images[i]);
9106 }
9107 }
9108 }
9109
9110
9111 \f
9112 /***********************************************************************
9113 W32 support code
9114 ***********************************************************************/
9115
9116 #if 0 /* TODO: W32 specific image code. */
9117
9118 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
9119 XImage **, Pixmap *));
9120 static void x_destroy_x_image P_ ((XImage *));
9121 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
9122
9123
9124 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
9125 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
9126 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
9127 via xmalloc. Print error messages via image_error if an error
9128 occurs. Value is non-zero if successful. */
9129
9130 static int
9131 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
9132 struct frame *f;
9133 int width, height, depth;
9134 XImage **ximg;
9135 Pixmap *pixmap;
9136 {
9137 #if 0 /* TODO: Image support for W32 */
9138 Display *display = FRAME_W32_DISPLAY (f);
9139 Screen *screen = FRAME_X_SCREEN (f);
9140 Window window = FRAME_W32_WINDOW (f);
9141
9142 xassert (interrupt_input_blocked);
9143
9144 if (depth <= 0)
9145 depth = one_w32_display_info.n_cbits;
9146 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
9147 depth, ZPixmap, 0, NULL, width, height,
9148 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
9149 if (*ximg == NULL)
9150 {
9151 image_error ("Unable to allocate X image", Qnil, Qnil);
9152 return 0;
9153 }
9154
9155 /* Allocate image raster. */
9156 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
9157
9158 /* Allocate a pixmap of the same size. */
9159 *pixmap = XCreatePixmap (display, window, width, height, depth);
9160 if (*pixmap == 0)
9161 {
9162 x_destroy_x_image (*ximg);
9163 *ximg = NULL;
9164 image_error ("Unable to create X pixmap", Qnil, Qnil);
9165 return 0;
9166 }
9167 #endif
9168 return 1;
9169 }
9170
9171
9172 /* Destroy XImage XIMG. Free XIMG->data. */
9173
9174 static void
9175 x_destroy_x_image (ximg)
9176 XImage *ximg;
9177 {
9178 xassert (interrupt_input_blocked);
9179 if (ximg)
9180 {
9181 xfree (ximg->data);
9182 ximg->data = NULL;
9183 XDestroyImage (ximg);
9184 }
9185 }
9186
9187
9188 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
9189 are width and height of both the image and pixmap. */
9190
9191 static void
9192 x_put_x_image (f, ximg, pixmap, width, height)
9193 struct frame *f;
9194 XImage *ximg;
9195 Pixmap pixmap;
9196 {
9197 GC gc;
9198
9199 xassert (interrupt_input_blocked);
9200 gc = XCreateGC (NULL, pixmap, 0, NULL);
9201 XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
9202 XFreeGC (NULL, gc);
9203 }
9204
9205 #endif
9206
9207 \f
9208 /***********************************************************************
9209 File Handling
9210 ***********************************************************************/
9211
9212 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
9213 static char *slurp_file P_ ((char *, int *));
9214
9215
9216 /* Find image file FILE. Look in data-directory, then
9217 x-bitmap-file-path. Value is the full name of the file found, or
9218 nil if not found. */
9219
9220 static Lisp_Object
9221 x_find_image_file (file)
9222 Lisp_Object file;
9223 {
9224 Lisp_Object file_found, search_path;
9225 struct gcpro gcpro1, gcpro2;
9226 int fd;
9227
9228 file_found = Qnil;
9229 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
9230 GCPRO2 (file_found, search_path);
9231
9232 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
9233 fd = openp (search_path, file, Qnil, &file_found, 0);
9234
9235 if (fd == -1)
9236 file_found = Qnil;
9237 else
9238 close (fd);
9239
9240 UNGCPRO;
9241 return file_found;
9242 }
9243
9244
9245 /* Read FILE into memory. Value is a pointer to a buffer allocated
9246 with xmalloc holding FILE's contents. Value is null if an error
9247 occurred. *SIZE is set to the size of the file. */
9248
9249 static char *
9250 slurp_file (file, size)
9251 char *file;
9252 int *size;
9253 {
9254 FILE *fp = NULL;
9255 char *buf = NULL;
9256 struct stat st;
9257
9258 if (stat (file, &st) == 0
9259 && (fp = fopen (file, "r")) != NULL
9260 && (buf = (char *) xmalloc (st.st_size),
9261 fread (buf, 1, st.st_size, fp) == st.st_size))
9262 {
9263 *size = st.st_size;
9264 fclose (fp);
9265 }
9266 else
9267 {
9268 if (fp)
9269 fclose (fp);
9270 if (buf)
9271 {
9272 xfree (buf);
9273 buf = NULL;
9274 }
9275 }
9276
9277 return buf;
9278 }
9279
9280
9281 \f
9282 /***********************************************************************
9283 XBM images
9284 ***********************************************************************/
9285
9286 static int xbm_load P_ ((struct frame *f, struct image *img));
9287 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
9288 Lisp_Object file));
9289 static int xbm_image_p P_ ((Lisp_Object object));
9290 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
9291 unsigned char **));
9292
9293
9294 /* Indices of image specification fields in xbm_format, below. */
9295
9296 enum xbm_keyword_index
9297 {
9298 XBM_TYPE,
9299 XBM_FILE,
9300 XBM_WIDTH,
9301 XBM_HEIGHT,
9302 XBM_DATA,
9303 XBM_FOREGROUND,
9304 XBM_BACKGROUND,
9305 XBM_ASCENT,
9306 XBM_MARGIN,
9307 XBM_RELIEF,
9308 XBM_ALGORITHM,
9309 XBM_HEURISTIC_MASK,
9310 XBM_MASK,
9311 XBM_LAST
9312 };
9313
9314 /* Vector of image_keyword structures describing the format
9315 of valid XBM image specifications. */
9316
9317 static struct image_keyword xbm_format[XBM_LAST] =
9318 {
9319 {":type", IMAGE_SYMBOL_VALUE, 1},
9320 {":file", IMAGE_STRING_VALUE, 0},
9321 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9322 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9323 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9324 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
9325 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
9326 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9327 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9328 {":relief", IMAGE_INTEGER_VALUE, 0},
9329 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9330 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9331 };
9332
9333 /* Structure describing the image type XBM. */
9334
9335 static struct image_type xbm_type =
9336 {
9337 &Qxbm,
9338 xbm_image_p,
9339 xbm_load,
9340 x_clear_image,
9341 NULL
9342 };
9343
9344 /* Tokens returned from xbm_scan. */
9345
9346 enum xbm_token
9347 {
9348 XBM_TK_IDENT = 256,
9349 XBM_TK_NUMBER
9350 };
9351
9352
9353 /* Return non-zero if OBJECT is a valid XBM-type image specification.
9354 A valid specification is a list starting with the symbol `image'
9355 The rest of the list is a property list which must contain an
9356 entry `:type xbm..
9357
9358 If the specification specifies a file to load, it must contain
9359 an entry `:file FILENAME' where FILENAME is a string.
9360
9361 If the specification is for a bitmap loaded from memory it must
9362 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
9363 WIDTH and HEIGHT are integers > 0. DATA may be:
9364
9365 1. a string large enough to hold the bitmap data, i.e. it must
9366 have a size >= (WIDTH + 7) / 8 * HEIGHT
9367
9368 2. a bool-vector of size >= WIDTH * HEIGHT
9369
9370 3. a vector of strings or bool-vectors, one for each line of the
9371 bitmap.
9372
9373 Both the file and data forms may contain the additional entries
9374 `:background COLOR' and `:foreground COLOR'. If not present,
9375 foreground and background of the frame on which the image is
9376 displayed, is used. */
9377
9378 static int
9379 xbm_image_p (object)
9380 Lisp_Object object;
9381 {
9382 struct image_keyword kw[XBM_LAST];
9383
9384 bcopy (xbm_format, kw, sizeof kw);
9385 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
9386 return 0;
9387
9388 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
9389
9390 if (kw[XBM_FILE].count)
9391 {
9392 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
9393 return 0;
9394 }
9395 else
9396 {
9397 Lisp_Object data;
9398 int width, height;
9399
9400 /* Entries for `:width', `:height' and `:data' must be present. */
9401 if (!kw[XBM_WIDTH].count
9402 || !kw[XBM_HEIGHT].count
9403 || !kw[XBM_DATA].count)
9404 return 0;
9405
9406 data = kw[XBM_DATA].value;
9407 width = XFASTINT (kw[XBM_WIDTH].value);
9408 height = XFASTINT (kw[XBM_HEIGHT].value);
9409
9410 /* Check type of data, and width and height against contents of
9411 data. */
9412 if (VECTORP (data))
9413 {
9414 int i;
9415
9416 /* Number of elements of the vector must be >= height. */
9417 if (XVECTOR (data)->size < height)
9418 return 0;
9419
9420 /* Each string or bool-vector in data must be large enough
9421 for one line of the image. */
9422 for (i = 0; i < height; ++i)
9423 {
9424 Lisp_Object elt = XVECTOR (data)->contents[i];
9425
9426 if (STRINGP (elt))
9427 {
9428 if (XSTRING (elt)->size
9429 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
9430 return 0;
9431 }
9432 else if (BOOL_VECTOR_P (elt))
9433 {
9434 if (XBOOL_VECTOR (elt)->size < width)
9435 return 0;
9436 }
9437 else
9438 return 0;
9439 }
9440 }
9441 else if (STRINGP (data))
9442 {
9443 if (XSTRING (data)->size
9444 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
9445 return 0;
9446 }
9447 else if (BOOL_VECTOR_P (data))
9448 {
9449 if (XBOOL_VECTOR (data)->size < width * height)
9450 return 0;
9451 }
9452 else
9453 return 0;
9454 }
9455
9456 /* Baseline must be a value between 0 and 100 (a percentage). */
9457 if (kw[XBM_ASCENT].count
9458 && XFASTINT (kw[XBM_ASCENT].value) > 100)
9459 return 0;
9460
9461 return 1;
9462 }
9463
9464
9465 /* Scan a bitmap file. FP is the stream to read from. Value is
9466 either an enumerator from enum xbm_token, or a character for a
9467 single-character token, or 0 at end of file. If scanning an
9468 identifier, store the lexeme of the identifier in SVAL. If
9469 scanning a number, store its value in *IVAL. */
9470
9471 static int
9472 xbm_scan (s, end, sval, ival)
9473 char **s, *end;
9474 char *sval;
9475 int *ival;
9476 {
9477 int c;
9478
9479 loop:
9480
9481 /* Skip white space. */
9482 while (*s < end &&(c = *(*s)++, isspace (c)))
9483 ;
9484
9485 if (*s >= end)
9486 c = 0;
9487 else if (isdigit (c))
9488 {
9489 int value = 0, digit;
9490
9491 if (c == '0' && *s < end)
9492 {
9493 c = *(*s)++;
9494 if (c == 'x' || c == 'X')
9495 {
9496 while (*s < end)
9497 {
9498 c = *(*s)++;
9499 if (isdigit (c))
9500 digit = c - '0';
9501 else if (c >= 'a' && c <= 'f')
9502 digit = c - 'a' + 10;
9503 else if (c >= 'A' && c <= 'F')
9504 digit = c - 'A' + 10;
9505 else
9506 break;
9507 value = 16 * value + digit;
9508 }
9509 }
9510 else if (isdigit (c))
9511 {
9512 value = c - '0';
9513 while (*s < end
9514 && (c = *(*s)++, isdigit (c)))
9515 value = 8 * value + c - '0';
9516 }
9517 }
9518 else
9519 {
9520 value = c - '0';
9521 while (*s < end
9522 && (c = *(*s)++, isdigit (c)))
9523 value = 10 * value + c - '0';
9524 }
9525
9526 if (*s < end)
9527 *s = *s - 1;
9528 *ival = value;
9529 c = XBM_TK_NUMBER;
9530 }
9531 else if (isalpha (c) || c == '_')
9532 {
9533 *sval++ = c;
9534 while (*s < end
9535 && (c = *(*s)++, (isalnum (c) || c == '_')))
9536 *sval++ = c;
9537 *sval = 0;
9538 if (*s < end)
9539 *s = *s - 1;
9540 c = XBM_TK_IDENT;
9541 }
9542 else if (c == '/' && **s == '*')
9543 {
9544 /* C-style comment. */
9545 ++*s;
9546 while (**s && (**s != '*' || *(*s + 1) != '/'))
9547 ++*s;
9548 if (**s)
9549 {
9550 *s += 2;
9551 goto loop;
9552 }
9553 }
9554
9555 return c;
9556 }
9557
9558
9559 /* Replacement for XReadBitmapFileData which isn't available under old
9560 X versions. CONTENTS is a pointer to a buffer to parse; END is the
9561 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
9562 the image. Return in *DATA the bitmap data allocated with xmalloc.
9563 Value is non-zero if successful. DATA null means just test if
9564 CONTENTS looks like an in-memory XBM file. */
9565
9566 static int
9567 xbm_read_bitmap_data (contents, end, width, height, data)
9568 char *contents, *end;
9569 int *width, *height;
9570 unsigned char **data;
9571 {
9572 char *s = contents;
9573 char buffer[BUFSIZ];
9574 int padding_p = 0;
9575 int v10 = 0;
9576 int bytes_per_line, i, nbytes;
9577 unsigned char *p;
9578 int value;
9579 int LA1;
9580
9581 #define match() \
9582 LA1 = xbm_scan (contents, end, buffer, &value)
9583
9584 #define expect(TOKEN) \
9585 if (LA1 != (TOKEN)) \
9586 goto failure; \
9587 else \
9588 match ()
9589
9590 #define expect_ident(IDENT) \
9591 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
9592 match (); \
9593 else \
9594 goto failure
9595
9596 *width = *height = -1;
9597 if (data)
9598 *data = NULL;
9599 LA1 = xbm_scan (&s, end, buffer, &value);
9600
9601 /* Parse defines for width, height and hot-spots. */
9602 while (LA1 == '#')
9603 {
9604 match ();
9605 expect_ident ("define");
9606 expect (XBM_TK_IDENT);
9607
9608 if (LA1 == XBM_TK_NUMBER);
9609 {
9610 char *p = strrchr (buffer, '_');
9611 p = p ? p + 1 : buffer;
9612 if (strcmp (p, "width") == 0)
9613 *width = value;
9614 else if (strcmp (p, "height") == 0)
9615 *height = value;
9616 }
9617 expect (XBM_TK_NUMBER);
9618 }
9619
9620 if (*width < 0 || *height < 0)
9621 goto failure;
9622 else if (data == NULL)
9623 goto success;
9624
9625 /* Parse bits. Must start with `static'. */
9626 expect_ident ("static");
9627 if (LA1 == XBM_TK_IDENT)
9628 {
9629 if (strcmp (buffer, "unsigned") == 0)
9630 {
9631 match ();
9632 expect_ident ("char");
9633 }
9634 else if (strcmp (buffer, "short") == 0)
9635 {
9636 match ();
9637 v10 = 1;
9638 if (*width % 16 && *width % 16 < 9)
9639 padding_p = 1;
9640 }
9641 else if (strcmp (buffer, "char") == 0)
9642 match ();
9643 else
9644 goto failure;
9645 }
9646 else
9647 goto failure;
9648
9649 expect (XBM_TK_IDENT);
9650 expect ('[');
9651 expect (']');
9652 expect ('=');
9653 expect ('{');
9654
9655 bytes_per_line = (*width + 7) / 8 + padding_p;
9656 nbytes = bytes_per_line * *height;
9657 p = *data = (char *) xmalloc (nbytes);
9658
9659 if (v10)
9660 {
9661
9662 for (i = 0; i < nbytes; i += 2)
9663 {
9664 int val = value;
9665 expect (XBM_TK_NUMBER);
9666
9667 *p++ = val;
9668 if (!padding_p || ((i + 2) % bytes_per_line))
9669 *p++ = value >> 8;
9670
9671 if (LA1 == ',' || LA1 == '}')
9672 match ();
9673 else
9674 goto failure;
9675 }
9676 }
9677 else
9678 {
9679 for (i = 0; i < nbytes; ++i)
9680 {
9681 int val = value;
9682 expect (XBM_TK_NUMBER);
9683
9684 *p++ = val;
9685
9686 if (LA1 == ',' || LA1 == '}')
9687 match ();
9688 else
9689 goto failure;
9690 }
9691 }
9692
9693 success:
9694 return 1;
9695
9696 failure:
9697
9698 if (data && *data)
9699 {
9700 xfree (*data);
9701 *data = NULL;
9702 }
9703 return 0;
9704
9705 #undef match
9706 #undef expect
9707 #undef expect_ident
9708 }
9709
9710
9711 /* Load XBM image IMG which will be displayed on frame F from buffer
9712 CONTENTS. END is the end of the buffer. Value is non-zero if
9713 successful. */
9714
9715 static int
9716 xbm_load_image (f, img, contents, end)
9717 struct frame *f;
9718 struct image *img;
9719 char *contents, *end;
9720 {
9721 int rc;
9722 unsigned char *data;
9723 int success_p = 0;
9724
9725 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
9726 if (rc)
9727 {
9728 int depth = one_w32_display_info.n_cbits;
9729 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
9730 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9731 Lisp_Object value;
9732
9733 xassert (img->width > 0 && img->height > 0);
9734
9735 /* Get foreground and background colors, maybe allocate colors. */
9736 value = image_spec_value (img->spec, QCforeground, NULL);
9737 if (!NILP (value))
9738 foreground = x_alloc_image_color (f, img, value, foreground);
9739 value = image_spec_value (img->spec, QCbackground, NULL);
9740 if (!NILP (value))
9741 {
9742 background = x_alloc_image_color (f, img, value, background);
9743 img->background = background;
9744 img->background_valid = 1;
9745 }
9746
9747 #if 0 /* TODO : Port image display to W32 */
9748 img->pixmap
9749 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
9750 FRAME_W32_WINDOW (f),
9751 data,
9752 img->width, img->height,
9753 foreground, background,
9754 depth);
9755 #endif
9756 xfree (data);
9757
9758 if (img->pixmap == 0)
9759 {
9760 x_clear_image (f, img);
9761 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
9762 }
9763 else
9764 success_p = 1;
9765 }
9766 else
9767 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
9768
9769 return success_p;
9770 }
9771
9772
9773 /* Value is non-zero if DATA looks like an in-memory XBM file. */
9774
9775 static int
9776 xbm_file_p (data)
9777 Lisp_Object data;
9778 {
9779 int w, h;
9780 return (STRINGP (data)
9781 && xbm_read_bitmap_data (XSTRING (data)->data,
9782 (XSTRING (data)->data
9783 + STRING_BYTES (XSTRING (data))),
9784 &w, &h, NULL));
9785 }
9786
9787
9788 /* Fill image IMG which is used on frame F with pixmap data. Value is
9789 non-zero if successful. */
9790
9791 static int
9792 xbm_load (f, img)
9793 struct frame *f;
9794 struct image *img;
9795 {
9796 int success_p = 0;
9797 Lisp_Object file_name;
9798
9799 xassert (xbm_image_p (img->spec));
9800
9801 /* If IMG->spec specifies a file name, create a non-file spec from it. */
9802 file_name = image_spec_value (img->spec, QCfile, NULL);
9803 if (STRINGP (file_name))
9804 {
9805 Lisp_Object file;
9806 char *contents;
9807 int size;
9808 struct gcpro gcpro1;
9809
9810 file = x_find_image_file (file_name);
9811 GCPRO1 (file);
9812 if (!STRINGP (file))
9813 {
9814 image_error ("Cannot find image file `%s'", file_name, Qnil);
9815 UNGCPRO;
9816 return 0;
9817 }
9818
9819 contents = slurp_file (XSTRING (file)->data, &size);
9820 if (contents == NULL)
9821 {
9822 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
9823 UNGCPRO;
9824 return 0;
9825 }
9826
9827 success_p = xbm_load_image (f, img, contents, contents + size);
9828 UNGCPRO;
9829 }
9830 else
9831 {
9832 struct image_keyword fmt[XBM_LAST];
9833 Lisp_Object data;
9834 int depth;
9835 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
9836 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9837 char *bits;
9838 int parsed_p;
9839 int in_memory_file_p = 0;
9840
9841 /* See if data looks like an in-memory XBM file. */
9842 data = image_spec_value (img->spec, QCdata, NULL);
9843 in_memory_file_p = xbm_file_p (data);
9844
9845 /* Parse the list specification. */
9846 bcopy (xbm_format, fmt, sizeof fmt);
9847 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
9848 xassert (parsed_p);
9849
9850 /* Get specified width, and height. */
9851 if (!in_memory_file_p)
9852 {
9853 img->width = XFASTINT (fmt[XBM_WIDTH].value);
9854 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
9855 xassert (img->width > 0 && img->height > 0);
9856 }
9857 /* Get foreground and background colors, maybe allocate colors. */
9858 if (fmt[XBM_FOREGROUND].count
9859 && STRINGP (fmt[XBM_FOREGROUND].value))
9860 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
9861 foreground);
9862 if (fmt[XBM_BACKGROUND].count
9863 && STRINGP (fmt[XBM_BACKGROUND].value))
9864 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
9865 background);
9866
9867 if (in_memory_file_p)
9868 success_p = xbm_load_image (f, img, XSTRING (data)->data,
9869 (XSTRING (data)->data
9870 + STRING_BYTES (XSTRING (data))));
9871 else
9872 {
9873 if (VECTORP (data))
9874 {
9875 int i;
9876 char *p;
9877 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
9878
9879 p = bits = (char *) alloca (nbytes * img->height);
9880 for (i = 0; i < img->height; ++i, p += nbytes)
9881 {
9882 Lisp_Object line = XVECTOR (data)->contents[i];
9883 if (STRINGP (line))
9884 bcopy (XSTRING (line)->data, p, nbytes);
9885 else
9886 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
9887 }
9888 }
9889 else if (STRINGP (data))
9890 bits = XSTRING (data)->data;
9891 else
9892 bits = XBOOL_VECTOR (data)->data;
9893 #ifdef TODO /* image support. */
9894 /* Create the pixmap. */
9895 depth = one_w32_display_info.n_cbits;
9896 img->pixmap
9897 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
9898 FRAME_X_WINDOW (f),
9899 bits,
9900 img->width, img->height,
9901 foreground, background,
9902 depth);
9903 #endif
9904 if (img->pixmap)
9905 success_p = 1;
9906 else
9907 {
9908 image_error ("Unable to create pixmap for XBM image `%s'",
9909 img->spec, Qnil);
9910 x_clear_image (f, img);
9911 }
9912 }
9913 }
9914
9915 return success_p;
9916 }
9917
9918
9919 \f
9920 /***********************************************************************
9921 XPM images
9922 ***********************************************************************/
9923
9924 #if HAVE_XPM
9925
9926 static int xpm_image_p P_ ((Lisp_Object object));
9927 static int xpm_load P_ ((struct frame *f, struct image *img));
9928 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
9929
9930 #include "X11/xpm.h"
9931
9932 /* The symbol `xpm' identifying XPM-format images. */
9933
9934 Lisp_Object Qxpm;
9935
9936 /* Indices of image specification fields in xpm_format, below. */
9937
9938 enum xpm_keyword_index
9939 {
9940 XPM_TYPE,
9941 XPM_FILE,
9942 XPM_DATA,
9943 XPM_ASCENT,
9944 XPM_MARGIN,
9945 XPM_RELIEF,
9946 XPM_ALGORITHM,
9947 XPM_HEURISTIC_MASK,
9948 XPM_MASK,
9949 XPM_COLOR_SYMBOLS,
9950 XPM_BACKGROUND,
9951 XPM_LAST
9952 };
9953
9954 /* Vector of image_keyword structures describing the format
9955 of valid XPM image specifications. */
9956
9957 static struct image_keyword xpm_format[XPM_LAST] =
9958 {
9959 {":type", IMAGE_SYMBOL_VALUE, 1},
9960 {":file", IMAGE_STRING_VALUE, 0},
9961 {":data", IMAGE_STRING_VALUE, 0},
9962 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9963 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9964 {":relief", IMAGE_INTEGER_VALUE, 0},
9965 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9966 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9967 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9968 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9969 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9970 };
9971
9972 /* Structure describing the image type XBM. */
9973
9974 static struct image_type xpm_type =
9975 {
9976 &Qxpm,
9977 xpm_image_p,
9978 xpm_load,
9979 x_clear_image,
9980 NULL
9981 };
9982
9983
9984 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
9985 for XPM images. Such a list must consist of conses whose car and
9986 cdr are strings. */
9987
9988 static int
9989 xpm_valid_color_symbols_p (color_symbols)
9990 Lisp_Object color_symbols;
9991 {
9992 while (CONSP (color_symbols))
9993 {
9994 Lisp_Object sym = XCAR (color_symbols);
9995 if (!CONSP (sym)
9996 || !STRINGP (XCAR (sym))
9997 || !STRINGP (XCDR (sym)))
9998 break;
9999 color_symbols = XCDR (color_symbols);
10000 }
10001
10002 return NILP (color_symbols);
10003 }
10004
10005
10006 /* Value is non-zero if OBJECT is a valid XPM image specification. */
10007
10008 static int
10009 xpm_image_p (object)
10010 Lisp_Object object;
10011 {
10012 struct image_keyword fmt[XPM_LAST];
10013 bcopy (xpm_format, fmt, sizeof fmt);
10014 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
10015 /* Either `:file' or `:data' must be present. */
10016 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
10017 /* Either no `:color-symbols' or it's a list of conses
10018 whose car and cdr are strings. */
10019 && (fmt[XPM_COLOR_SYMBOLS].count == 0
10020 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
10021 && (fmt[XPM_ASCENT].count == 0
10022 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
10023 }
10024
10025
10026 /* Load image IMG which will be displayed on frame F. Value is
10027 non-zero if successful. */
10028
10029 static int
10030 xpm_load (f, img)
10031 struct frame *f;
10032 struct image *img;
10033 {
10034 int rc, i;
10035 XpmAttributes attrs;
10036 Lisp_Object specified_file, color_symbols;
10037
10038 /* Configure the XPM lib. Use the visual of frame F. Allocate
10039 close colors. Return colors allocated. */
10040 bzero (&attrs, sizeof attrs);
10041 attrs.visual = FRAME_X_VISUAL (f);
10042 attrs.colormap = FRAME_X_COLORMAP (f);
10043 attrs.valuemask |= XpmVisual;
10044 attrs.valuemask |= XpmColormap;
10045 attrs.valuemask |= XpmReturnAllocPixels;
10046 #ifdef XpmAllocCloseColors
10047 attrs.alloc_close_colors = 1;
10048 attrs.valuemask |= XpmAllocCloseColors;
10049 #else
10050 attrs.closeness = 600;
10051 attrs.valuemask |= XpmCloseness;
10052 #endif
10053
10054 /* If image specification contains symbolic color definitions, add
10055 these to `attrs'. */
10056 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
10057 if (CONSP (color_symbols))
10058 {
10059 Lisp_Object tail;
10060 XpmColorSymbol *xpm_syms;
10061 int i, size;
10062
10063 attrs.valuemask |= XpmColorSymbols;
10064
10065 /* Count number of symbols. */
10066 attrs.numsymbols = 0;
10067 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
10068 ++attrs.numsymbols;
10069
10070 /* Allocate an XpmColorSymbol array. */
10071 size = attrs.numsymbols * sizeof *xpm_syms;
10072 xpm_syms = (XpmColorSymbol *) alloca (size);
10073 bzero (xpm_syms, size);
10074 attrs.colorsymbols = xpm_syms;
10075
10076 /* Fill the color symbol array. */
10077 for (tail = color_symbols, i = 0;
10078 CONSP (tail);
10079 ++i, tail = XCDR (tail))
10080 {
10081 Lisp_Object name = XCAR (XCAR (tail));
10082 Lisp_Object color = XCDR (XCAR (tail));
10083 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
10084 strcpy (xpm_syms[i].name, XSTRING (name)->data);
10085 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
10086 strcpy (xpm_syms[i].value, XSTRING (color)->data);
10087 }
10088 }
10089
10090 /* Create a pixmap for the image, either from a file, or from a
10091 string buffer containing data in the same format as an XPM file. */
10092 BLOCK_INPUT;
10093 specified_file = image_spec_value (img->spec, QCfile, NULL);
10094 if (STRINGP (specified_file))
10095 {
10096 Lisp_Object file = x_find_image_file (specified_file);
10097 if (!STRINGP (file))
10098 {
10099 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10100 UNBLOCK_INPUT;
10101 return 0;
10102 }
10103
10104 rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
10105 XSTRING (file)->data, &img->pixmap, &img->mask,
10106 &attrs);
10107 }
10108 else
10109 {
10110 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
10111 rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
10112 XSTRING (buffer)->data,
10113 &img->pixmap, &img->mask,
10114 &attrs);
10115 }
10116 UNBLOCK_INPUT;
10117
10118 if (rc == XpmSuccess)
10119 {
10120 /* Remember allocated colors. */
10121 img->ncolors = attrs.nalloc_pixels;
10122 img->colors = (unsigned long *) xmalloc (img->ncolors
10123 * sizeof *img->colors);
10124 for (i = 0; i < attrs.nalloc_pixels; ++i)
10125 img->colors[i] = attrs.alloc_pixels[i];
10126
10127 img->width = attrs.width;
10128 img->height = attrs.height;
10129 xassert (img->width > 0 && img->height > 0);
10130
10131 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
10132 BLOCK_INPUT;
10133 XpmFreeAttributes (&attrs);
10134 UNBLOCK_INPUT;
10135 }
10136 else
10137 {
10138 switch (rc)
10139 {
10140 case XpmOpenFailed:
10141 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
10142 break;
10143
10144 case XpmFileInvalid:
10145 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
10146 break;
10147
10148 case XpmNoMemory:
10149 image_error ("Out of memory (%s)", img->spec, Qnil);
10150 break;
10151
10152 case XpmColorFailed:
10153 image_error ("Color allocation error (%s)", img->spec, Qnil);
10154 break;
10155
10156 default:
10157 image_error ("Unknown error (%s)", img->spec, Qnil);
10158 break;
10159 }
10160 }
10161
10162 return rc == XpmSuccess;
10163 }
10164
10165 #endif /* HAVE_XPM != 0 */
10166
10167 \f
10168 #if 0 /* TODO : Color tables on W32. */
10169 /***********************************************************************
10170 Color table
10171 ***********************************************************************/
10172
10173 /* An entry in the color table mapping an RGB color to a pixel color. */
10174
10175 struct ct_color
10176 {
10177 int r, g, b;
10178 unsigned long pixel;
10179
10180 /* Next in color table collision list. */
10181 struct ct_color *next;
10182 };
10183
10184 /* The bucket vector size to use. Must be prime. */
10185
10186 #define CT_SIZE 101
10187
10188 /* Value is a hash of the RGB color given by R, G, and B. */
10189
10190 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
10191
10192 /* The color hash table. */
10193
10194 struct ct_color **ct_table;
10195
10196 /* Number of entries in the color table. */
10197
10198 int ct_colors_allocated;
10199
10200 /* Function prototypes. */
10201
10202 static void init_color_table P_ ((void));
10203 static void free_color_table P_ ((void));
10204 static unsigned long *colors_in_color_table P_ ((int *n));
10205 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
10206 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
10207
10208
10209 /* Initialize the color table. */
10210
10211 static void
10212 init_color_table ()
10213 {
10214 int size = CT_SIZE * sizeof (*ct_table);
10215 ct_table = (struct ct_color **) xmalloc (size);
10216 bzero (ct_table, size);
10217 ct_colors_allocated = 0;
10218 }
10219
10220
10221 /* Free memory associated with the color table. */
10222
10223 static void
10224 free_color_table ()
10225 {
10226 int i;
10227 struct ct_color *p, *next;
10228
10229 for (i = 0; i < CT_SIZE; ++i)
10230 for (p = ct_table[i]; p; p = next)
10231 {
10232 next = p->next;
10233 xfree (p);
10234 }
10235
10236 xfree (ct_table);
10237 ct_table = NULL;
10238 }
10239
10240
10241 /* Value is a pixel color for RGB color R, G, B on frame F. If an
10242 entry for that color already is in the color table, return the
10243 pixel color of that entry. Otherwise, allocate a new color for R,
10244 G, B, and make an entry in the color table. */
10245
10246 static unsigned long
10247 lookup_rgb_color (f, r, g, b)
10248 struct frame *f;
10249 int r, g, b;
10250 {
10251 unsigned hash = CT_HASH_RGB (r, g, b);
10252 int i = hash % CT_SIZE;
10253 struct ct_color *p;
10254
10255 for (p = ct_table[i]; p; p = p->next)
10256 if (p->r == r && p->g == g && p->b == b)
10257 break;
10258
10259 if (p == NULL)
10260 {
10261 COLORREF color;
10262 Colormap cmap;
10263 int rc;
10264
10265 color = PALETTERGB (r, g, b);
10266
10267 ++ct_colors_allocated;
10268
10269 p = (struct ct_color *) xmalloc (sizeof *p);
10270 p->r = r;
10271 p->g = g;
10272 p->b = b;
10273 p->pixel = color;
10274 p->next = ct_table[i];
10275 ct_table[i] = p;
10276 }
10277
10278 return p->pixel;
10279 }
10280
10281
10282 /* Look up pixel color PIXEL which is used on frame F in the color
10283 table. If not already present, allocate it. Value is PIXEL. */
10284
10285 static unsigned long
10286 lookup_pixel_color (f, pixel)
10287 struct frame *f;
10288 unsigned long pixel;
10289 {
10290 int i = pixel % CT_SIZE;
10291 struct ct_color *p;
10292
10293 for (p = ct_table[i]; p; p = p->next)
10294 if (p->pixel == pixel)
10295 break;
10296
10297 if (p == NULL)
10298 {
10299 XColor color;
10300 Colormap cmap;
10301 int rc;
10302
10303 BLOCK_INPUT;
10304
10305 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
10306 color.pixel = pixel;
10307 XQueryColor (NULL, cmap, &color);
10308 rc = x_alloc_nearest_color (f, cmap, &color);
10309 UNBLOCK_INPUT;
10310
10311 if (rc)
10312 {
10313 ++ct_colors_allocated;
10314
10315 p = (struct ct_color *) xmalloc (sizeof *p);
10316 p->r = color.red;
10317 p->g = color.green;
10318 p->b = color.blue;
10319 p->pixel = pixel;
10320 p->next = ct_table[i];
10321 ct_table[i] = p;
10322 }
10323 else
10324 return FRAME_FOREGROUND_PIXEL (f);
10325 }
10326 return p->pixel;
10327 }
10328
10329
10330 /* Value is a vector of all pixel colors contained in the color table,
10331 allocated via xmalloc. Set *N to the number of colors. */
10332
10333 static unsigned long *
10334 colors_in_color_table (n)
10335 int *n;
10336 {
10337 int i, j;
10338 struct ct_color *p;
10339 unsigned long *colors;
10340
10341 if (ct_colors_allocated == 0)
10342 {
10343 *n = 0;
10344 colors = NULL;
10345 }
10346 else
10347 {
10348 colors = (unsigned long *) xmalloc (ct_colors_allocated
10349 * sizeof *colors);
10350 *n = ct_colors_allocated;
10351
10352 for (i = j = 0; i < CT_SIZE; ++i)
10353 for (p = ct_table[i]; p; p = p->next)
10354 colors[j++] = p->pixel;
10355 }
10356
10357 return colors;
10358 }
10359
10360 #endif /* TODO */
10361
10362 \f
10363 /***********************************************************************
10364 Algorithms
10365 ***********************************************************************/
10366 #if 0 /* TODO: image support. */
10367 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
10368 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
10369 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
10370
10371 /* Non-zero means draw a cross on images having `:conversion
10372 disabled'. */
10373
10374 int cross_disabled_images;
10375
10376 /* Edge detection matrices for different edge-detection
10377 strategies. */
10378
10379 static int emboss_matrix[9] = {
10380 /* x - 1 x x + 1 */
10381 2, -1, 0, /* y - 1 */
10382 -1, 0, 1, /* y */
10383 0, 1, -2 /* y + 1 */
10384 };
10385
10386 static int laplace_matrix[9] = {
10387 /* x - 1 x x + 1 */
10388 1, 0, 0, /* y - 1 */
10389 0, 0, 0, /* y */
10390 0, 0, -1 /* y + 1 */
10391 };
10392
10393 /* Value is the intensity of the color whose red/green/blue values
10394 are R, G, and B. */
10395
10396 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
10397
10398
10399 /* On frame F, return an array of XColor structures describing image
10400 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
10401 non-zero means also fill the red/green/blue members of the XColor
10402 structures. Value is a pointer to the array of XColors structures,
10403 allocated with xmalloc; it must be freed by the caller. */
10404
10405 static XColor *
10406 x_to_xcolors (f, img, rgb_p)
10407 struct frame *f;
10408 struct image *img;
10409 int rgb_p;
10410 {
10411 int x, y;
10412 XColor *colors, *p;
10413 XImage *ximg;
10414
10415 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
10416
10417 /* Get the X image IMG->pixmap. */
10418 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10419 0, 0, img->width, img->height, ~0, ZPixmap);
10420
10421 /* Fill the `pixel' members of the XColor array. I wished there
10422 were an easy and portable way to circumvent XGetPixel. */
10423 p = colors;
10424 for (y = 0; y < img->height; ++y)
10425 {
10426 XColor *row = p;
10427
10428 for (x = 0; x < img->width; ++x, ++p)
10429 p->pixel = XGetPixel (ximg, x, y);
10430
10431 if (rgb_p)
10432 x_query_colors (f, row, img->width);
10433 }
10434
10435 XDestroyImage (ximg);
10436 return colors;
10437 }
10438
10439
10440 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
10441 RGB members are set. F is the frame on which this all happens.
10442 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
10443
10444 static void
10445 x_from_xcolors (f, img, colors)
10446 struct frame *f;
10447 struct image *img;
10448 XColor *colors;
10449 {
10450 int x, y;
10451 XImage *oimg;
10452 Pixmap pixmap;
10453 XColor *p;
10454
10455 init_color_table ();
10456
10457 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
10458 &oimg, &pixmap);
10459 p = colors;
10460 for (y = 0; y < img->height; ++y)
10461 for (x = 0; x < img->width; ++x, ++p)
10462 {
10463 unsigned long pixel;
10464 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
10465 XPutPixel (oimg, x, y, pixel);
10466 }
10467
10468 xfree (colors);
10469 x_clear_image_1 (f, img, 1, 0, 1);
10470
10471 x_put_x_image (f, oimg, pixmap, img->width, img->height);
10472 x_destroy_x_image (oimg);
10473 img->pixmap = pixmap;
10474 img->colors = colors_in_color_table (&img->ncolors);
10475 free_color_table ();
10476 }
10477
10478
10479 /* On frame F, perform edge-detection on image IMG.
10480
10481 MATRIX is a nine-element array specifying the transformation
10482 matrix. See emboss_matrix for an example.
10483
10484 COLOR_ADJUST is a color adjustment added to each pixel of the
10485 outgoing image. */
10486
10487 static void
10488 x_detect_edges (f, img, matrix, color_adjust)
10489 struct frame *f;
10490 struct image *img;
10491 int matrix[9], color_adjust;
10492 {
10493 XColor *colors = x_to_xcolors (f, img, 1);
10494 XColor *new, *p;
10495 int x, y, i, sum;
10496
10497 for (i = sum = 0; i < 9; ++i)
10498 sum += abs (matrix[i]);
10499
10500 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
10501
10502 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
10503
10504 for (y = 0; y < img->height; ++y)
10505 {
10506 p = COLOR (new, 0, y);
10507 p->red = p->green = p->blue = 0xffff/2;
10508 p = COLOR (new, img->width - 1, y);
10509 p->red = p->green = p->blue = 0xffff/2;
10510 }
10511
10512 for (x = 1; x < img->width - 1; ++x)
10513 {
10514 p = COLOR (new, x, 0);
10515 p->red = p->green = p->blue = 0xffff/2;
10516 p = COLOR (new, x, img->height - 1);
10517 p->red = p->green = p->blue = 0xffff/2;
10518 }
10519
10520 for (y = 1; y < img->height - 1; ++y)
10521 {
10522 p = COLOR (new, 1, y);
10523
10524 for (x = 1; x < img->width - 1; ++x, ++p)
10525 {
10526 int r, g, b, y1, x1;
10527
10528 r = g = b = i = 0;
10529 for (y1 = y - 1; y1 < y + 2; ++y1)
10530 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
10531 if (matrix[i])
10532 {
10533 XColor *t = COLOR (colors, x1, y1);
10534 r += matrix[i] * t->red;
10535 g += matrix[i] * t->green;
10536 b += matrix[i] * t->blue;
10537 }
10538
10539 r = (r / sum + color_adjust) & 0xffff;
10540 g = (g / sum + color_adjust) & 0xffff;
10541 b = (b / sum + color_adjust) & 0xffff;
10542 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
10543 }
10544 }
10545
10546 xfree (colors);
10547 x_from_xcolors (f, img, new);
10548
10549 #undef COLOR
10550 }
10551
10552
10553 /* Perform the pre-defined `emboss' edge-detection on image IMG
10554 on frame F. */
10555
10556 static void
10557 x_emboss (f, img)
10558 struct frame *f;
10559 struct image *img;
10560 {
10561 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
10562 }
10563
10564
10565 /* Transform image IMG which is used on frame F with a Laplace
10566 edge-detection algorithm. The result is an image that can be used
10567 to draw disabled buttons, for example. */
10568
10569 static void
10570 x_laplace (f, img)
10571 struct frame *f;
10572 struct image *img;
10573 {
10574 x_detect_edges (f, img, laplace_matrix, 45000);
10575 }
10576
10577
10578 /* Perform edge-detection on image IMG on frame F, with specified
10579 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
10580
10581 MATRIX must be either
10582
10583 - a list of at least 9 numbers in row-major form
10584 - a vector of at least 9 numbers
10585
10586 COLOR_ADJUST nil means use a default; otherwise it must be a
10587 number. */
10588
10589 static void
10590 x_edge_detection (f, img, matrix, color_adjust)
10591 struct frame *f;
10592 struct image *img;
10593 Lisp_Object matrix, color_adjust;
10594 {
10595 int i = 0;
10596 int trans[9];
10597
10598 if (CONSP (matrix))
10599 {
10600 for (i = 0;
10601 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
10602 ++i, matrix = XCDR (matrix))
10603 trans[i] = XFLOATINT (XCAR (matrix));
10604 }
10605 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
10606 {
10607 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
10608 trans[i] = XFLOATINT (AREF (matrix, i));
10609 }
10610
10611 if (NILP (color_adjust))
10612 color_adjust = make_number (0xffff / 2);
10613
10614 if (i == 9 && NUMBERP (color_adjust))
10615 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
10616 }
10617
10618
10619 /* Transform image IMG on frame F so that it looks disabled. */
10620
10621 static void
10622 x_disable_image (f, img)
10623 struct frame *f;
10624 struct image *img;
10625 {
10626 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10627
10628 if (dpyinfo->n_planes >= 2)
10629 {
10630 /* Color (or grayscale). Convert to gray, and equalize. Just
10631 drawing such images with a stipple can look very odd, so
10632 we're using this method instead. */
10633 XColor *colors = x_to_xcolors (f, img, 1);
10634 XColor *p, *end;
10635 const int h = 15000;
10636 const int l = 30000;
10637
10638 for (p = colors, end = colors + img->width * img->height;
10639 p < end;
10640 ++p)
10641 {
10642 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
10643 int i2 = (0xffff - h - l) * i / 0xffff + l;
10644 p->red = p->green = p->blue = i2;
10645 }
10646
10647 x_from_xcolors (f, img, colors);
10648 }
10649
10650 /* Draw a cross over the disabled image, if we must or if we
10651 should. */
10652 if (dpyinfo->n_planes < 2 || cross_disabled_images)
10653 {
10654 Display *dpy = FRAME_X_DISPLAY (f);
10655 GC gc;
10656
10657 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
10658 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
10659 XDrawLine (dpy, img->pixmap, gc, 0, 0,
10660 img->width - 1, img->height - 1);
10661 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
10662 img->width - 1, 0);
10663 XFreeGC (dpy, gc);
10664
10665 if (img->mask)
10666 {
10667 gc = XCreateGC (dpy, img->mask, 0, NULL);
10668 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
10669 XDrawLine (dpy, img->mask, gc, 0, 0,
10670 img->width - 1, img->height - 1);
10671 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
10672 img->width - 1, 0);
10673 XFreeGC (dpy, gc);
10674 }
10675 }
10676 }
10677
10678
10679 /* Build a mask for image IMG which is used on frame F. FILE is the
10680 name of an image file, for error messages. HOW determines how to
10681 determine the background color of IMG. If it is a list '(R G B)',
10682 with R, G, and B being integers >= 0, take that as the color of the
10683 background. Otherwise, determine the background color of IMG
10684 heuristically. Value is non-zero if successful. */
10685
10686 static int
10687 x_build_heuristic_mask (f, img, how)
10688 struct frame *f;
10689 struct image *img;
10690 Lisp_Object how;
10691 {
10692 Display *dpy = FRAME_W32_DISPLAY (f);
10693 XImage *ximg, *mask_img;
10694 int x, y, rc, use_img_background;
10695 unsigned long bg = 0;
10696
10697 if (img->mask)
10698 {
10699 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
10700 img->mask = None;
10701 img->background_transparent_valid = 0;
10702 }
10703
10704 /* Create an image and pixmap serving as mask. */
10705 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
10706 &mask_img, &img->mask);
10707 if (!rc)
10708 return 0;
10709
10710 /* Get the X image of IMG->pixmap. */
10711 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
10712 ~0, ZPixmap);
10713
10714 /* Determine the background color of ximg. If HOW is `(R G B)'
10715 take that as color. Otherwise, use the image's background color. */
10716 use_img_background = 1;
10717
10718 if (CONSP (how))
10719 {
10720 int rgb[3], i;
10721
10722 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
10723 {
10724 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
10725 how = XCDR (how);
10726 }
10727
10728 if (i == 3 && NILP (how))
10729 {
10730 char color_name[30];
10731 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
10732 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
10733 use_img_background = 0;
10734 }
10735 }
10736
10737 if (use_img_background)
10738 bg = four_corners_best (ximg, img->width, img->height);
10739
10740 /* Set all bits in mask_img to 1 whose color in ximg is different
10741 from the background color bg. */
10742 for (y = 0; y < img->height; ++y)
10743 for (x = 0; x < img->width; ++x)
10744 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
10745
10746 /* Fill in the background_transparent field while we have the mask handy. */
10747 image_background_transparent (img, f, mask_img);
10748
10749 /* Put mask_img into img->mask. */
10750 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
10751 x_destroy_x_image (mask_img);
10752 XDestroyImage (ximg);
10753
10754 return 1;
10755 }
10756 #endif /* TODO */
10757
10758 \f
10759 /***********************************************************************
10760 PBM (mono, gray, color)
10761 ***********************************************************************/
10762 #ifdef HAVE_PBM
10763
10764 static int pbm_image_p P_ ((Lisp_Object object));
10765 static int pbm_load P_ ((struct frame *f, struct image *img));
10766 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
10767
10768 /* The symbol `pbm' identifying images of this type. */
10769
10770 Lisp_Object Qpbm;
10771
10772 /* Indices of image specification fields in gs_format, below. */
10773
10774 enum pbm_keyword_index
10775 {
10776 PBM_TYPE,
10777 PBM_FILE,
10778 PBM_DATA,
10779 PBM_ASCENT,
10780 PBM_MARGIN,
10781 PBM_RELIEF,
10782 PBM_ALGORITHM,
10783 PBM_HEURISTIC_MASK,
10784 PBM_MASK,
10785 PBM_FOREGROUND,
10786 PBM_BACKGROUND,
10787 PBM_LAST
10788 };
10789
10790 /* Vector of image_keyword structures describing the format
10791 of valid user-defined image specifications. */
10792
10793 static struct image_keyword pbm_format[PBM_LAST] =
10794 {
10795 {":type", IMAGE_SYMBOL_VALUE, 1},
10796 {":file", IMAGE_STRING_VALUE, 0},
10797 {":data", IMAGE_STRING_VALUE, 0},
10798 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
10799 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10800 {":relief", IMAGE_INTEGER_VALUE, 0},
10801 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10802 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10803 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10804 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
10805 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10806 };
10807
10808 /* Structure describing the image type `pbm'. */
10809
10810 static struct image_type pbm_type =
10811 {
10812 &Qpbm,
10813 pbm_image_p,
10814 pbm_load,
10815 x_clear_image,
10816 NULL
10817 };
10818
10819
10820 /* Return non-zero if OBJECT is a valid PBM image specification. */
10821
10822 static int
10823 pbm_image_p (object)
10824 Lisp_Object object;
10825 {
10826 struct image_keyword fmt[PBM_LAST];
10827
10828 bcopy (pbm_format, fmt, sizeof fmt);
10829
10830 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
10831 || (fmt[PBM_ASCENT].count
10832 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
10833 return 0;
10834
10835 /* Must specify either :data or :file. */
10836 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
10837 }
10838
10839
10840 /* Scan a decimal number from *S and return it. Advance *S while
10841 reading the number. END is the end of the string. Value is -1 at
10842 end of input. */
10843
10844 static int
10845 pbm_scan_number (s, end)
10846 unsigned char **s, *end;
10847 {
10848 int c, val = -1;
10849
10850 while (*s < end)
10851 {
10852 /* Skip white-space. */
10853 while (*s < end && (c = *(*s)++, isspace (c)))
10854 ;
10855
10856 if (c == '#')
10857 {
10858 /* Skip comment to end of line. */
10859 while (*s < end && (c = *(*s)++, c != '\n'))
10860 ;
10861 }
10862 else if (isdigit (c))
10863 {
10864 /* Read decimal number. */
10865 val = c - '0';
10866 while (*s < end && (c = *(*s)++, isdigit (c)))
10867 val = 10 * val + c - '0';
10868 break;
10869 }
10870 else
10871 break;
10872 }
10873
10874 return val;
10875 }
10876
10877
10878 /* Read FILE into memory. Value is a pointer to a buffer allocated
10879 with xmalloc holding FILE's contents. Value is null if an error
10880 occured. *SIZE is set to the size of the file. */
10881
10882 static char *
10883 pbm_read_file (file, size)
10884 Lisp_Object file;
10885 int *size;
10886 {
10887 FILE *fp = NULL;
10888 char *buf = NULL;
10889 struct stat st;
10890
10891 if (stat (XSTRING (file)->data, &st) == 0
10892 && (fp = fopen (XSTRING (file)->data, "r")) != NULL
10893 && (buf = (char *) xmalloc (st.st_size),
10894 fread (buf, 1, st.st_size, fp) == st.st_size))
10895 {
10896 *size = st.st_size;
10897 fclose (fp);
10898 }
10899 else
10900 {
10901 if (fp)
10902 fclose (fp);
10903 if (buf)
10904 {
10905 xfree (buf);
10906 buf = NULL;
10907 }
10908 }
10909
10910 return buf;
10911 }
10912
10913
10914 /* Load PBM image IMG for use on frame F. */
10915
10916 static int
10917 pbm_load (f, img)
10918 struct frame *f;
10919 struct image *img;
10920 {
10921 int raw_p, x, y;
10922 int width, height, max_color_idx = 0;
10923 XImage *ximg;
10924 Lisp_Object file, specified_file;
10925 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
10926 struct gcpro gcpro1;
10927 unsigned char *contents = NULL;
10928 unsigned char *end, *p;
10929 int size;
10930
10931 specified_file = image_spec_value (img->spec, QCfile, NULL);
10932 file = Qnil;
10933 GCPRO1 (file);
10934
10935 if (STRINGP (specified_file))
10936 {
10937 file = x_find_image_file (specified_file);
10938 if (!STRINGP (file))
10939 {
10940 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10941 UNGCPRO;
10942 return 0;
10943 }
10944
10945 contents = slurp_file (XSTRING (file)->data, &size);
10946 if (contents == NULL)
10947 {
10948 image_error ("Error reading `%s'", file, Qnil);
10949 UNGCPRO;
10950 return 0;
10951 }
10952
10953 p = contents;
10954 end = contents + size;
10955 }
10956 else
10957 {
10958 Lisp_Object data;
10959 data = image_spec_value (img->spec, QCdata, NULL);
10960 p = XSTRING (data)->data;
10961 end = p + STRING_BYTES (XSTRING (data));
10962 }
10963
10964 /* Check magic number. */
10965 if (end - p < 2 || *p++ != 'P')
10966 {
10967 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
10968 error:
10969 xfree (contents);
10970 UNGCPRO;
10971 return 0;
10972 }
10973
10974 switch (*p++)
10975 {
10976 case '1':
10977 raw_p = 0, type = PBM_MONO;
10978 break;
10979
10980 case '2':
10981 raw_p = 0, type = PBM_GRAY;
10982 break;
10983
10984 case '3':
10985 raw_p = 0, type = PBM_COLOR;
10986 break;
10987
10988 case '4':
10989 raw_p = 1, type = PBM_MONO;
10990 break;
10991
10992 case '5':
10993 raw_p = 1, type = PBM_GRAY;
10994 break;
10995
10996 case '6':
10997 raw_p = 1, type = PBM_COLOR;
10998 break;
10999
11000 default:
11001 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
11002 goto error;
11003 }
11004
11005 /* Read width, height, maximum color-component. Characters
11006 starting with `#' up to the end of a line are ignored. */
11007 width = pbm_scan_number (&p, end);
11008 height = pbm_scan_number (&p, end);
11009
11010 if (type != PBM_MONO)
11011 {
11012 max_color_idx = pbm_scan_number (&p, end);
11013 if (raw_p && max_color_idx > 255)
11014 max_color_idx = 255;
11015 }
11016
11017 if (width < 0
11018 || height < 0
11019 || (type != PBM_MONO && max_color_idx < 0))
11020 goto error;
11021
11022 if (!x_create_x_image_and_pixmap (f, width, height, 0,
11023 &ximg, &img->pixmap))
11024 goto error;
11025
11026 /* Initialize the color hash table. */
11027 init_color_table ();
11028
11029 if (type == PBM_MONO)
11030 {
11031 int c = 0, g;
11032 struct image_keyword fmt[PBM_LAST];
11033 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
11034 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
11035
11036 /* Parse the image specification. */
11037 bcopy (pbm_format, fmt, sizeof fmt);
11038 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
11039
11040 /* Get foreground and background colors, maybe allocate colors. */
11041 if (fmt[PBM_FOREGROUND].count
11042 && STRINGP (fmt[PBM_FOREGROUND].value))
11043 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
11044 if (fmt[PBM_BACKGROUND].count
11045 && STRINGP (fmt[PBM_BACKGROUND].value))
11046 {
11047 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
11048 img->background = bg;
11049 img->background_valid = 1;
11050 }
11051
11052 for (y = 0; y < height; ++y)
11053 for (x = 0; x < width; ++x)
11054 {
11055 if (raw_p)
11056 {
11057 if ((x & 7) == 0)
11058 c = *p++;
11059 g = c & 0x80;
11060 c <<= 1;
11061 }
11062 else
11063 g = pbm_scan_number (&p, end);
11064
11065 XPutPixel (ximg, x, y, g ? fg : bg);
11066 }
11067 }
11068 else
11069 {
11070 for (y = 0; y < height; ++y)
11071 for (x = 0; x < width; ++x)
11072 {
11073 int r, g, b;
11074
11075 if (type == PBM_GRAY)
11076 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
11077 else if (raw_p)
11078 {
11079 r = *p++;
11080 g = *p++;
11081 b = *p++;
11082 }
11083 else
11084 {
11085 r = pbm_scan_number (&p, end);
11086 g = pbm_scan_number (&p, end);
11087 b = pbm_scan_number (&p, end);
11088 }
11089
11090 if (r < 0 || g < 0 || b < 0)
11091 {
11092 xfree (ximg->data);
11093 ximg->data = NULL;
11094 XDestroyImage (ximg);
11095 image_error ("Invalid pixel value in image `%s'",
11096 img->spec, Qnil);
11097 goto error;
11098 }
11099
11100 /* RGB values are now in the range 0..max_color_idx.
11101 Scale this to the range 0..0xffff supported by X. */
11102 r = (double) r * 65535 / max_color_idx;
11103 g = (double) g * 65535 / max_color_idx;
11104 b = (double) b * 65535 / max_color_idx;
11105 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
11106 }
11107 }
11108
11109 /* Store in IMG->colors the colors allocated for the image, and
11110 free the color table. */
11111 img->colors = colors_in_color_table (&img->ncolors);
11112 free_color_table ();
11113
11114 /* Maybe fill in the background field while we have ximg handy. */
11115 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11116 IMAGE_BACKGROUND (img, f, ximg);
11117
11118 /* Put the image into a pixmap. */
11119 x_put_x_image (f, ximg, img->pixmap, width, height);
11120 x_destroy_x_image (ximg);
11121
11122 img->width = width;
11123 img->height = height;
11124
11125 UNGCPRO;
11126 xfree (contents);
11127 return 1;
11128 }
11129 #endif /* HAVE_PBM */
11130
11131 \f
11132 /***********************************************************************
11133 PNG
11134 ***********************************************************************/
11135
11136 #if HAVE_PNG
11137
11138 #include <png.h>
11139
11140 /* Function prototypes. */
11141
11142 static int png_image_p P_ ((Lisp_Object object));
11143 static int png_load P_ ((struct frame *f, struct image *img));
11144
11145 /* The symbol `png' identifying images of this type. */
11146
11147 Lisp_Object Qpng;
11148
11149 /* Indices of image specification fields in png_format, below. */
11150
11151 enum png_keyword_index
11152 {
11153 PNG_TYPE,
11154 PNG_DATA,
11155 PNG_FILE,
11156 PNG_ASCENT,
11157 PNG_MARGIN,
11158 PNG_RELIEF,
11159 PNG_ALGORITHM,
11160 PNG_HEURISTIC_MASK,
11161 PNG_MASK,
11162 PNG_BACKGROUND,
11163 PNG_LAST
11164 };
11165
11166 /* Vector of image_keyword structures describing the format
11167 of valid user-defined image specifications. */
11168
11169 static struct image_keyword png_format[PNG_LAST] =
11170 {
11171 {":type", IMAGE_SYMBOL_VALUE, 1},
11172 {":data", IMAGE_STRING_VALUE, 0},
11173 {":file", IMAGE_STRING_VALUE, 0},
11174 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
11175 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11176 {":relief", IMAGE_INTEGER_VALUE, 0},
11177 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11178 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11179 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11180 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11181 };
11182
11183 /* Structure describing the image type `png'. */
11184
11185 static struct image_type png_type =
11186 {
11187 &Qpng,
11188 png_image_p,
11189 png_load,
11190 x_clear_image,
11191 NULL
11192 };
11193
11194
11195 /* Return non-zero if OBJECT is a valid PNG image specification. */
11196
11197 static int
11198 png_image_p (object)
11199 Lisp_Object object;
11200 {
11201 struct image_keyword fmt[PNG_LAST];
11202 bcopy (png_format, fmt, sizeof fmt);
11203
11204 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
11205 || (fmt[PNG_ASCENT].count
11206 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
11207 return 0;
11208
11209 /* Must specify either the :data or :file keyword. */
11210 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
11211 }
11212
11213
11214 /* Error and warning handlers installed when the PNG library
11215 is initialized. */
11216
11217 static void
11218 my_png_error (png_ptr, msg)
11219 png_struct *png_ptr;
11220 char *msg;
11221 {
11222 xassert (png_ptr != NULL);
11223 image_error ("PNG error: %s", build_string (msg), Qnil);
11224 longjmp (png_ptr->jmpbuf, 1);
11225 }
11226
11227
11228 static void
11229 my_png_warning (png_ptr, msg)
11230 png_struct *png_ptr;
11231 char *msg;
11232 {
11233 xassert (png_ptr != NULL);
11234 image_error ("PNG warning: %s", build_string (msg), Qnil);
11235 }
11236
11237 /* Memory source for PNG decoding. */
11238
11239 struct png_memory_storage
11240 {
11241 unsigned char *bytes; /* The data */
11242 size_t len; /* How big is it? */
11243 int index; /* Where are we? */
11244 };
11245
11246
11247 /* Function set as reader function when reading PNG image from memory.
11248 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
11249 bytes from the input to DATA. */
11250
11251 static void
11252 png_read_from_memory (png_ptr, data, length)
11253 png_structp png_ptr;
11254 png_bytep data;
11255 png_size_t length;
11256 {
11257 struct png_memory_storage *tbr
11258 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
11259
11260 if (length > tbr->len - tbr->index)
11261 png_error (png_ptr, "Read error");
11262
11263 bcopy (tbr->bytes + tbr->index, data, length);
11264 tbr->index = tbr->index + length;
11265 }
11266
11267 /* Load PNG image IMG for use on frame F. Value is non-zero if
11268 successful. */
11269
11270 static int
11271 png_load (f, img)
11272 struct frame *f;
11273 struct image *img;
11274 {
11275 Lisp_Object file, specified_file;
11276 Lisp_Object specified_data;
11277 int x, y, i;
11278 XImage *ximg, *mask_img = NULL;
11279 struct gcpro gcpro1;
11280 png_struct *png_ptr = NULL;
11281 png_info *info_ptr = NULL, *end_info = NULL;
11282 FILE *volatile fp = NULL;
11283 png_byte sig[8];
11284 png_byte *volatile pixels = NULL;
11285 png_byte **volatile rows = NULL;
11286 png_uint_32 width, height;
11287 int bit_depth, color_type, interlace_type;
11288 png_byte channels;
11289 png_uint_32 row_bytes;
11290 int transparent_p;
11291 char *gamma_str;
11292 double screen_gamma, image_gamma;
11293 int intent;
11294 struct png_memory_storage tbr; /* Data to be read */
11295
11296 /* Find out what file to load. */
11297 specified_file = image_spec_value (img->spec, QCfile, NULL);
11298 specified_data = image_spec_value (img->spec, QCdata, NULL);
11299 file = Qnil;
11300 GCPRO1 (file);
11301
11302 if (NILP (specified_data))
11303 {
11304 file = x_find_image_file (specified_file);
11305 if (!STRINGP (file))
11306 {
11307 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11308 UNGCPRO;
11309 return 0;
11310 }
11311
11312 /* Open the image file. */
11313 fp = fopen (XSTRING (file)->data, "rb");
11314 if (!fp)
11315 {
11316 image_error ("Cannot open image file `%s'", file, Qnil);
11317 UNGCPRO;
11318 fclose (fp);
11319 return 0;
11320 }
11321
11322 /* Check PNG signature. */
11323 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
11324 || !png_check_sig (sig, sizeof sig))
11325 {
11326 image_error ("Not a PNG file:` %s'", file, Qnil);
11327 UNGCPRO;
11328 fclose (fp);
11329 return 0;
11330 }
11331 }
11332 else
11333 {
11334 /* Read from memory. */
11335 tbr.bytes = XSTRING (specified_data)->data;
11336 tbr.len = STRING_BYTES (XSTRING (specified_data));
11337 tbr.index = 0;
11338
11339 /* Check PNG signature. */
11340 if (tbr.len < sizeof sig
11341 || !png_check_sig (tbr.bytes, sizeof sig))
11342 {
11343 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
11344 UNGCPRO;
11345 return 0;
11346 }
11347
11348 /* Need to skip past the signature. */
11349 tbr.bytes += sizeof (sig);
11350 }
11351
11352 /* Initialize read and info structs for PNG lib. */
11353 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
11354 my_png_error, my_png_warning);
11355 if (!png_ptr)
11356 {
11357 if (fp) fclose (fp);
11358 UNGCPRO;
11359 return 0;
11360 }
11361
11362 info_ptr = png_create_info_struct (png_ptr);
11363 if (!info_ptr)
11364 {
11365 png_destroy_read_struct (&png_ptr, NULL, NULL);
11366 if (fp) fclose (fp);
11367 UNGCPRO;
11368 return 0;
11369 }
11370
11371 end_info = png_create_info_struct (png_ptr);
11372 if (!end_info)
11373 {
11374 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
11375 if (fp) fclose (fp);
11376 UNGCPRO;
11377 return 0;
11378 }
11379
11380 /* Set error jump-back. We come back here when the PNG library
11381 detects an error. */
11382 if (setjmp (png_ptr->jmpbuf))
11383 {
11384 error:
11385 if (png_ptr)
11386 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
11387 xfree (pixels);
11388 xfree (rows);
11389 if (fp) fclose (fp);
11390 UNGCPRO;
11391 return 0;
11392 }
11393
11394 /* Read image info. */
11395 if (!NILP (specified_data))
11396 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
11397 else
11398 png_init_io (png_ptr, fp);
11399
11400 png_set_sig_bytes (png_ptr, sizeof sig);
11401 png_read_info (png_ptr, info_ptr);
11402 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
11403 &interlace_type, NULL, NULL);
11404
11405 /* If image contains simply transparency data, we prefer to
11406 construct a clipping mask. */
11407 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
11408 transparent_p = 1;
11409 else
11410 transparent_p = 0;
11411
11412 /* This function is easier to write if we only have to handle
11413 one data format: RGB or RGBA with 8 bits per channel. Let's
11414 transform other formats into that format. */
11415
11416 /* Strip more than 8 bits per channel. */
11417 if (bit_depth == 16)
11418 png_set_strip_16 (png_ptr);
11419
11420 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
11421 if available. */
11422 png_set_expand (png_ptr);
11423
11424 /* Convert grayscale images to RGB. */
11425 if (color_type == PNG_COLOR_TYPE_GRAY
11426 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
11427 png_set_gray_to_rgb (png_ptr);
11428
11429 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
11430 gamma_str = getenv ("SCREEN_GAMMA");
11431 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
11432
11433 /* Tell the PNG lib to handle gamma correction for us. */
11434
11435 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
11436 if (png_get_sRGB (png_ptr, info_ptr, &intent))
11437 /* There is a special chunk in the image specifying the gamma. */
11438 png_set_sRGB (png_ptr, info_ptr, intent);
11439 else
11440 #endif
11441 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
11442 /* Image contains gamma information. */
11443 png_set_gamma (png_ptr, screen_gamma, image_gamma);
11444 else
11445 /* Use a default of 0.5 for the image gamma. */
11446 png_set_gamma (png_ptr, screen_gamma, 0.5);
11447
11448 /* Handle alpha channel by combining the image with a background
11449 color. Do this only if a real alpha channel is supplied. For
11450 simple transparency, we prefer a clipping mask. */
11451 if (!transparent_p)
11452 {
11453 png_color_16 *image_background;
11454 Lisp_Object specified_bg
11455 = image_spec_value (img->spec, QCbackground, NULL);
11456
11457
11458 if (STRINGP (specified_bg))
11459 /* The user specified `:background', use that. */
11460 {
11461 COLORREF color;
11462 if (w32_defined_color (f, XSTRING (specified_bg)->data, &color, 0))
11463 {
11464 png_color_16 user_bg;
11465
11466 bzero (&user_bg, sizeof user_bg);
11467 user_bg.red = color.red;
11468 user_bg.green = color.green;
11469 user_bg.blue = color.blue;
11470
11471 png_set_background (png_ptr, &user_bg,
11472 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
11473 }
11474 }
11475 else if (png_get_bKGD (png_ptr, info_ptr, &image_background))
11476 /* Image contains a background color with which to
11477 combine the image. */
11478 png_set_background (png_ptr, image_background,
11479 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
11480 else
11481 {
11482 /* Image does not contain a background color with which
11483 to combine the image data via an alpha channel. Use
11484 the frame's background instead. */
11485 XColor color;
11486 Colormap cmap;
11487 png_color_16 frame_background;
11488
11489 cmap = FRAME_X_COLORMAP (f);
11490 color.pixel = FRAME_BACKGROUND_PIXEL (f);
11491 x_query_color (f, &color);
11492
11493 bzero (&frame_background, sizeof frame_background);
11494 frame_background.red = color.red;
11495 frame_background.green = color.green;
11496 frame_background.blue = color.blue;
11497
11498 png_set_background (png_ptr, &frame_background,
11499 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
11500 }
11501 }
11502
11503 /* Update info structure. */
11504 png_read_update_info (png_ptr, info_ptr);
11505
11506 /* Get number of channels. Valid values are 1 for grayscale images
11507 and images with a palette, 2 for grayscale images with transparency
11508 information (alpha channel), 3 for RGB images, and 4 for RGB
11509 images with alpha channel, i.e. RGBA. If conversions above were
11510 sufficient we should only have 3 or 4 channels here. */
11511 channels = png_get_channels (png_ptr, info_ptr);
11512 xassert (channels == 3 || channels == 4);
11513
11514 /* Number of bytes needed for one row of the image. */
11515 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
11516
11517 /* Allocate memory for the image. */
11518 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
11519 rows = (png_byte **) xmalloc (height * sizeof *rows);
11520 for (i = 0; i < height; ++i)
11521 rows[i] = pixels + i * row_bytes;
11522
11523 /* Read the entire image. */
11524 png_read_image (png_ptr, rows);
11525 png_read_end (png_ptr, info_ptr);
11526 if (fp)
11527 {
11528 fclose (fp);
11529 fp = NULL;
11530 }
11531
11532 /* Create the X image and pixmap. */
11533 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
11534 &img->pixmap))
11535 goto error;
11536
11537 /* Create an image and pixmap serving as mask if the PNG image
11538 contains an alpha channel. */
11539 if (channels == 4
11540 && !transparent_p
11541 && !x_create_x_image_and_pixmap (f, width, height, 1,
11542 &mask_img, &img->mask))
11543 {
11544 x_destroy_x_image (ximg);
11545 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
11546 img->pixmap = 0;
11547 goto error;
11548 }
11549
11550 /* Fill the X image and mask from PNG data. */
11551 init_color_table ();
11552
11553 for (y = 0; y < height; ++y)
11554 {
11555 png_byte *p = rows[y];
11556
11557 for (x = 0; x < width; ++x)
11558 {
11559 unsigned r, g, b;
11560
11561 r = *p++ << 8;
11562 g = *p++ << 8;
11563 b = *p++ << 8;
11564 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
11565
11566 /* An alpha channel, aka mask channel, associates variable
11567 transparency with an image. Where other image formats
11568 support binary transparency---fully transparent or fully
11569 opaque---PNG allows up to 254 levels of partial transparency.
11570 The PNG library implements partial transparency by combining
11571 the image with a specified background color.
11572
11573 I'm not sure how to handle this here nicely: because the
11574 background on which the image is displayed may change, for
11575 real alpha channel support, it would be necessary to create
11576 a new image for each possible background.
11577
11578 What I'm doing now is that a mask is created if we have
11579 boolean transparency information. Otherwise I'm using
11580 the frame's background color to combine the image with. */
11581
11582 if (channels == 4)
11583 {
11584 if (mask_img)
11585 XPutPixel (mask_img, x, y, *p > 0);
11586 ++p;
11587 }
11588 }
11589 }
11590
11591 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11592 /* Set IMG's background color from the PNG image, unless the user
11593 overrode it. */
11594 {
11595 png_color_16 *bg;
11596 if (png_get_bKGD (png_ptr, info_ptr, &bg))
11597 {
11598 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
11599 img->background_valid = 1;
11600 }
11601 }
11602
11603 /* Remember colors allocated for this image. */
11604 img->colors = colors_in_color_table (&img->ncolors);
11605 free_color_table ();
11606
11607 /* Clean up. */
11608 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
11609 xfree (rows);
11610 xfree (pixels);
11611
11612 img->width = width;
11613 img->height = height;
11614
11615 /* Maybe fill in the background field while we have ximg handy. */
11616 IMAGE_BACKGROUND (img, f, ximg);
11617
11618 /* Put the image into the pixmap, then free the X image and its buffer. */
11619 x_put_x_image (f, ximg, img->pixmap, width, height);
11620 x_destroy_x_image (ximg);
11621
11622 /* Same for the mask. */
11623 if (mask_img)
11624 {
11625 /* Fill in the background_transparent field while we have the mask
11626 handy. */
11627 image_background_transparent (img, f, mask_img);
11628
11629 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
11630 x_destroy_x_image (mask_img);
11631 }
11632
11633 UNGCPRO;
11634 return 1;
11635 }
11636
11637 #endif /* HAVE_PNG != 0 */
11638
11639
11640 \f
11641 /***********************************************************************
11642 JPEG
11643 ***********************************************************************/
11644
11645 #if HAVE_JPEG
11646
11647 /* Work around a warning about HAVE_STDLIB_H being redefined in
11648 jconfig.h. */
11649 #ifdef HAVE_STDLIB_H
11650 #define HAVE_STDLIB_H_1
11651 #undef HAVE_STDLIB_H
11652 #endif /* HAVE_STLIB_H */
11653
11654 #include <jpeglib.h>
11655 #include <jerror.h>
11656 #include <setjmp.h>
11657
11658 #ifdef HAVE_STLIB_H_1
11659 #define HAVE_STDLIB_H 1
11660 #endif
11661
11662 static int jpeg_image_p P_ ((Lisp_Object object));
11663 static int jpeg_load P_ ((struct frame *f, struct image *img));
11664
11665 /* The symbol `jpeg' identifying images of this type. */
11666
11667 Lisp_Object Qjpeg;
11668
11669 /* Indices of image specification fields in gs_format, below. */
11670
11671 enum jpeg_keyword_index
11672 {
11673 JPEG_TYPE,
11674 JPEG_DATA,
11675 JPEG_FILE,
11676 JPEG_ASCENT,
11677 JPEG_MARGIN,
11678 JPEG_RELIEF,
11679 JPEG_ALGORITHM,
11680 JPEG_HEURISTIC_MASK,
11681 JPEG_MASK,
11682 JPEG_BACKGROUND,
11683 JPEG_LAST
11684 };
11685
11686 /* Vector of image_keyword structures describing the format
11687 of valid user-defined image specifications. */
11688
11689 static struct image_keyword jpeg_format[JPEG_LAST] =
11690 {
11691 {":type", IMAGE_SYMBOL_VALUE, 1},
11692 {":data", IMAGE_STRING_VALUE, 0},
11693 {":file", IMAGE_STRING_VALUE, 0},
11694 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
11695 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11696 {":relief", IMAGE_INTEGER_VALUE, 0},
11697 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11698 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11699 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11700 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11701 };
11702
11703 /* Structure describing the image type `jpeg'. */
11704
11705 static struct image_type jpeg_type =
11706 {
11707 &Qjpeg,
11708 jpeg_image_p,
11709 jpeg_load,
11710 x_clear_image,
11711 NULL
11712 };
11713
11714
11715 /* Return non-zero if OBJECT is a valid JPEG image specification. */
11716
11717 static int
11718 jpeg_image_p (object)
11719 Lisp_Object object;
11720 {
11721 struct image_keyword fmt[JPEG_LAST];
11722
11723 bcopy (jpeg_format, fmt, sizeof fmt);
11724
11725 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
11726 || (fmt[JPEG_ASCENT].count
11727 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
11728 return 0;
11729
11730 /* Must specify either the :data or :file keyword. */
11731 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
11732 }
11733
11734
11735 struct my_jpeg_error_mgr
11736 {
11737 struct jpeg_error_mgr pub;
11738 jmp_buf setjmp_buffer;
11739 };
11740
11741 static void
11742 my_error_exit (cinfo)
11743 j_common_ptr cinfo;
11744 {
11745 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
11746 longjmp (mgr->setjmp_buffer, 1);
11747 }
11748
11749 /* Init source method for JPEG data source manager. Called by
11750 jpeg_read_header() before any data is actually read. See
11751 libjpeg.doc from the JPEG lib distribution. */
11752
11753 static void
11754 our_init_source (cinfo)
11755 j_decompress_ptr cinfo;
11756 {
11757 }
11758
11759
11760 /* Fill input buffer method for JPEG data source manager. Called
11761 whenever more data is needed. We read the whole image in one step,
11762 so this only adds a fake end of input marker at the end. */
11763
11764 static boolean
11765 our_fill_input_buffer (cinfo)
11766 j_decompress_ptr cinfo;
11767 {
11768 /* Insert a fake EOI marker. */
11769 struct jpeg_source_mgr *src = cinfo->src;
11770 static JOCTET buffer[2];
11771
11772 buffer[0] = (JOCTET) 0xFF;
11773 buffer[1] = (JOCTET) JPEG_EOI;
11774
11775 src->next_input_byte = buffer;
11776 src->bytes_in_buffer = 2;
11777 return TRUE;
11778 }
11779
11780
11781 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
11782 is the JPEG data source manager. */
11783
11784 static void
11785 our_skip_input_data (cinfo, num_bytes)
11786 j_decompress_ptr cinfo;
11787 long num_bytes;
11788 {
11789 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
11790
11791 if (src)
11792 {
11793 if (num_bytes > src->bytes_in_buffer)
11794 ERREXIT (cinfo, JERR_INPUT_EOF);
11795
11796 src->bytes_in_buffer -= num_bytes;
11797 src->next_input_byte += num_bytes;
11798 }
11799 }
11800
11801
11802 /* Method to terminate data source. Called by
11803 jpeg_finish_decompress() after all data has been processed. */
11804
11805 static void
11806 our_term_source (cinfo)
11807 j_decompress_ptr cinfo;
11808 {
11809 }
11810
11811
11812 /* Set up the JPEG lib for reading an image from DATA which contains
11813 LEN bytes. CINFO is the decompression info structure created for
11814 reading the image. */
11815
11816 static void
11817 jpeg_memory_src (cinfo, data, len)
11818 j_decompress_ptr cinfo;
11819 JOCTET *data;
11820 unsigned int len;
11821 {
11822 struct jpeg_source_mgr *src;
11823
11824 if (cinfo->src == NULL)
11825 {
11826 /* First time for this JPEG object? */
11827 cinfo->src = (struct jpeg_source_mgr *)
11828 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
11829 sizeof (struct jpeg_source_mgr));
11830 src = (struct jpeg_source_mgr *) cinfo->src;
11831 src->next_input_byte = data;
11832 }
11833
11834 src = (struct jpeg_source_mgr *) cinfo->src;
11835 src->init_source = our_init_source;
11836 src->fill_input_buffer = our_fill_input_buffer;
11837 src->skip_input_data = our_skip_input_data;
11838 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
11839 src->term_source = our_term_source;
11840 src->bytes_in_buffer = len;
11841 src->next_input_byte = data;
11842 }
11843
11844
11845 /* Load image IMG for use on frame F. Patterned after example.c
11846 from the JPEG lib. */
11847
11848 static int
11849 jpeg_load (f, img)
11850 struct frame *f;
11851 struct image *img;
11852 {
11853 struct jpeg_decompress_struct cinfo;
11854 struct my_jpeg_error_mgr mgr;
11855 Lisp_Object file, specified_file;
11856 Lisp_Object specified_data;
11857 FILE * volatile fp = NULL;
11858 JSAMPARRAY buffer;
11859 int row_stride, x, y;
11860 XImage *ximg = NULL;
11861 int rc;
11862 unsigned long *colors;
11863 int width, height;
11864 struct gcpro gcpro1;
11865
11866 /* Open the JPEG file. */
11867 specified_file = image_spec_value (img->spec, QCfile, NULL);
11868 specified_data = image_spec_value (img->spec, QCdata, NULL);
11869 file = Qnil;
11870 GCPRO1 (file);
11871
11872 if (NILP (specified_data))
11873 {
11874 file = x_find_image_file (specified_file);
11875 if (!STRINGP (file))
11876 {
11877 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11878 UNGCPRO;
11879 return 0;
11880 }
11881
11882 fp = fopen (XSTRING (file)->data, "r");
11883 if (fp == NULL)
11884 {
11885 image_error ("Cannot open `%s'", file, Qnil);
11886 UNGCPRO;
11887 return 0;
11888 }
11889 }
11890
11891 /* Customize libjpeg's error handling to call my_error_exit when an
11892 error is detected. This function will perform a longjmp. */
11893 cinfo.err = jpeg_std_error (&mgr.pub);
11894 mgr.pub.error_exit = my_error_exit;
11895
11896 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
11897 {
11898 if (rc == 1)
11899 {
11900 /* Called from my_error_exit. Display a JPEG error. */
11901 char buffer[JMSG_LENGTH_MAX];
11902 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
11903 image_error ("Error reading JPEG image `%s': %s", img->spec,
11904 build_string (buffer));
11905 }
11906
11907 /* Close the input file and destroy the JPEG object. */
11908 if (fp)
11909 fclose (fp);
11910 jpeg_destroy_decompress (&cinfo);
11911
11912 /* If we already have an XImage, free that. */
11913 x_destroy_x_image (ximg);
11914
11915 /* Free pixmap and colors. */
11916 x_clear_image (f, img);
11917
11918 UNGCPRO;
11919 return 0;
11920 }
11921
11922 /* Create the JPEG decompression object. Let it read from fp.
11923 Read the JPEG image header. */
11924 jpeg_create_decompress (&cinfo);
11925
11926 if (NILP (specified_data))
11927 jpeg_stdio_src (&cinfo, fp);
11928 else
11929 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
11930 STRING_BYTES (XSTRING (specified_data)));
11931
11932 jpeg_read_header (&cinfo, TRUE);
11933
11934 /* Customize decompression so that color quantization will be used.
11935 Start decompression. */
11936 cinfo.quantize_colors = TRUE;
11937 jpeg_start_decompress (&cinfo);
11938 width = img->width = cinfo.output_width;
11939 height = img->height = cinfo.output_height;
11940
11941 /* Create X image and pixmap. */
11942 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
11943 &img->pixmap))
11944 longjmp (mgr.setjmp_buffer, 2);
11945
11946 /* Allocate colors. When color quantization is used,
11947 cinfo.actual_number_of_colors has been set with the number of
11948 colors generated, and cinfo.colormap is a two-dimensional array
11949 of color indices in the range 0..cinfo.actual_number_of_colors.
11950 No more than 255 colors will be generated. */
11951 {
11952 int i, ir, ig, ib;
11953
11954 if (cinfo.out_color_components > 2)
11955 ir = 0, ig = 1, ib = 2;
11956 else if (cinfo.out_color_components > 1)
11957 ir = 0, ig = 1, ib = 0;
11958 else
11959 ir = 0, ig = 0, ib = 0;
11960
11961 /* Use the color table mechanism because it handles colors that
11962 cannot be allocated nicely. Such colors will be replaced with
11963 a default color, and we don't have to care about which colors
11964 can be freed safely, and which can't. */
11965 init_color_table ();
11966 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
11967 * sizeof *colors);
11968
11969 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
11970 {
11971 /* Multiply RGB values with 255 because X expects RGB values
11972 in the range 0..0xffff. */
11973 int r = cinfo.colormap[ir][i] << 8;
11974 int g = cinfo.colormap[ig][i] << 8;
11975 int b = cinfo.colormap[ib][i] << 8;
11976 colors[i] = lookup_rgb_color (f, r, g, b);
11977 }
11978
11979 /* Remember those colors actually allocated. */
11980 img->colors = colors_in_color_table (&img->ncolors);
11981 free_color_table ();
11982 }
11983
11984 /* Read pixels. */
11985 row_stride = width * cinfo.output_components;
11986 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
11987 row_stride, 1);
11988 for (y = 0; y < height; ++y)
11989 {
11990 jpeg_read_scanlines (&cinfo, buffer, 1);
11991 for (x = 0; x < cinfo.output_width; ++x)
11992 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
11993 }
11994
11995 /* Clean up. */
11996 jpeg_finish_decompress (&cinfo);
11997 jpeg_destroy_decompress (&cinfo);
11998 if (fp)
11999 fclose (fp);
12000
12001 /* Maybe fill in the background field while we have ximg handy. */
12002 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12003 IMAGE_BACKGROUND (img, f, ximg);
12004
12005 /* Put the image into the pixmap. */
12006 x_put_x_image (f, ximg, img->pixmap, width, height);
12007 x_destroy_x_image (ximg);
12008 UNBLOCK_INPUT;
12009 UNGCPRO;
12010 return 1;
12011 }
12012
12013 #endif /* HAVE_JPEG */
12014
12015
12016 \f
12017 /***********************************************************************
12018 TIFF
12019 ***********************************************************************/
12020
12021 #if HAVE_TIFF
12022
12023 #include <tiffio.h>
12024
12025 static int tiff_image_p P_ ((Lisp_Object object));
12026 static int tiff_load P_ ((struct frame *f, struct image *img));
12027
12028 /* The symbol `tiff' identifying images of this type. */
12029
12030 Lisp_Object Qtiff;
12031
12032 /* Indices of image specification fields in tiff_format, below. */
12033
12034 enum tiff_keyword_index
12035 {
12036 TIFF_TYPE,
12037 TIFF_DATA,
12038 TIFF_FILE,
12039 TIFF_ASCENT,
12040 TIFF_MARGIN,
12041 TIFF_RELIEF,
12042 TIFF_ALGORITHM,
12043 TIFF_HEURISTIC_MASK,
12044 TIFF_MASK,
12045 TIFF_BACKGROUND,
12046 TIFF_LAST
12047 };
12048
12049 /* Vector of image_keyword structures describing the format
12050 of valid user-defined image specifications. */
12051
12052 static struct image_keyword tiff_format[TIFF_LAST] =
12053 {
12054 {":type", IMAGE_SYMBOL_VALUE, 1},
12055 {":data", IMAGE_STRING_VALUE, 0},
12056 {":file", IMAGE_STRING_VALUE, 0},
12057 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12058 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12059 {":relief", IMAGE_INTEGER_VALUE, 0},
12060 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12061 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12062 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12063 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12064 };
12065
12066 /* Structure describing the image type `tiff'. */
12067
12068 static struct image_type tiff_type =
12069 {
12070 &Qtiff,
12071 tiff_image_p,
12072 tiff_load,
12073 x_clear_image,
12074 NULL
12075 };
12076
12077
12078 /* Return non-zero if OBJECT is a valid TIFF image specification. */
12079
12080 static int
12081 tiff_image_p (object)
12082 Lisp_Object object;
12083 {
12084 struct image_keyword fmt[TIFF_LAST];
12085 bcopy (tiff_format, fmt, sizeof fmt);
12086
12087 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
12088 || (fmt[TIFF_ASCENT].count
12089 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
12090 return 0;
12091
12092 /* Must specify either the :data or :file keyword. */
12093 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
12094 }
12095
12096
12097 /* Reading from a memory buffer for TIFF images Based on the PNG
12098 memory source, but we have to provide a lot of extra functions.
12099 Blah.
12100
12101 We really only need to implement read and seek, but I am not
12102 convinced that the TIFF library is smart enough not to destroy
12103 itself if we only hand it the function pointers we need to
12104 override. */
12105
12106 typedef struct
12107 {
12108 unsigned char *bytes;
12109 size_t len;
12110 int index;
12111 }
12112 tiff_memory_source;
12113
12114 static size_t
12115 tiff_read_from_memory (data, buf, size)
12116 thandle_t data;
12117 tdata_t buf;
12118 tsize_t size;
12119 {
12120 tiff_memory_source *src = (tiff_memory_source *) data;
12121
12122 if (size > src->len - src->index)
12123 return (size_t) -1;
12124 bcopy (src->bytes + src->index, buf, size);
12125 src->index += size;
12126 return size;
12127 }
12128
12129 static size_t
12130 tiff_write_from_memory (data, buf, size)
12131 thandle_t data;
12132 tdata_t buf;
12133 tsize_t size;
12134 {
12135 return (size_t) -1;
12136 }
12137
12138 static toff_t
12139 tiff_seek_in_memory (data, off, whence)
12140 thandle_t data;
12141 toff_t off;
12142 int whence;
12143 {
12144 tiff_memory_source *src = (tiff_memory_source *) data;
12145 int idx;
12146
12147 switch (whence)
12148 {
12149 case SEEK_SET: /* Go from beginning of source. */
12150 idx = off;
12151 break;
12152
12153 case SEEK_END: /* Go from end of source. */
12154 idx = src->len + off;
12155 break;
12156
12157 case SEEK_CUR: /* Go from current position. */
12158 idx = src->index + off;
12159 break;
12160
12161 default: /* Invalid `whence'. */
12162 return -1;
12163 }
12164
12165 if (idx > src->len || idx < 0)
12166 return -1;
12167
12168 src->index = idx;
12169 return src->index;
12170 }
12171
12172 static int
12173 tiff_close_memory (data)
12174 thandle_t data;
12175 {
12176 /* NOOP */
12177 return 0;
12178 }
12179
12180 static int
12181 tiff_mmap_memory (data, pbase, psize)
12182 thandle_t data;
12183 tdata_t *pbase;
12184 toff_t *psize;
12185 {
12186 /* It is already _IN_ memory. */
12187 return 0;
12188 }
12189
12190 static void
12191 tiff_unmap_memory (data, base, size)
12192 thandle_t data;
12193 tdata_t base;
12194 toff_t size;
12195 {
12196 /* We don't need to do this. */
12197 }
12198
12199 static toff_t
12200 tiff_size_of_memory (data)
12201 thandle_t data;
12202 {
12203 return ((tiff_memory_source *) data)->len;
12204 }
12205
12206
12207 static void
12208 tiff_error_handler (title, format, ap)
12209 const char *title, *format;
12210 va_list ap;
12211 {
12212 char buf[512];
12213 int len;
12214
12215 len = sprintf (buf, "TIFF error: %s ", title);
12216 vsprintf (buf + len, format, ap);
12217 add_to_log (buf, Qnil, Qnil);
12218 }
12219
12220
12221 static void
12222 tiff_warning_handler (title, format, ap)
12223 const char *title, *format;
12224 va_list ap;
12225 {
12226 char buf[512];
12227 int len;
12228
12229 len = sprintf (buf, "TIFF warning: %s ", title);
12230 vsprintf (buf + len, format, ap);
12231 add_to_log (buf, Qnil, Qnil);
12232 }
12233
12234
12235 /* Load TIFF image IMG for use on frame F. Value is non-zero if
12236 successful. */
12237
12238 static int
12239 tiff_load (f, img)
12240 struct frame *f;
12241 struct image *img;
12242 {
12243 Lisp_Object file, specified_file;
12244 Lisp_Object specified_data;
12245 TIFF *tiff;
12246 int width, height, x, y;
12247 uint32 *buf;
12248 int rc;
12249 XImage *ximg;
12250 struct gcpro gcpro1;
12251 tiff_memory_source memsrc;
12252
12253 specified_file = image_spec_value (img->spec, QCfile, NULL);
12254 specified_data = image_spec_value (img->spec, QCdata, NULL);
12255 file = Qnil;
12256 GCPRO1 (file);
12257
12258 TIFFSetErrorHandler (tiff_error_handler);
12259 TIFFSetWarningHandler (tiff_warning_handler);
12260
12261 if (NILP (specified_data))
12262 {
12263 /* Read from a file */
12264 file = x_find_image_file (specified_file);
12265 if (!STRINGP (file))
12266 {
12267 image_error ("Cannot find image file `%s'", file, Qnil);
12268 UNGCPRO;
12269 return 0;
12270 }
12271
12272 /* Try to open the image file. */
12273 tiff = TIFFOpen (XSTRING (file)->data, "r");
12274 if (tiff == NULL)
12275 {
12276 image_error ("Cannot open `%s'", file, Qnil);
12277 UNGCPRO;
12278 return 0;
12279 }
12280 }
12281 else
12282 {
12283 /* Memory source! */
12284 memsrc.bytes = XSTRING (specified_data)->data;
12285 memsrc.len = STRING_BYTES (XSTRING (specified_data));
12286 memsrc.index = 0;
12287
12288 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
12289 (TIFFReadWriteProc) tiff_read_from_memory,
12290 (TIFFReadWriteProc) tiff_write_from_memory,
12291 tiff_seek_in_memory,
12292 tiff_close_memory,
12293 tiff_size_of_memory,
12294 tiff_mmap_memory,
12295 tiff_unmap_memory);
12296
12297 if (!tiff)
12298 {
12299 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
12300 UNGCPRO;
12301 return 0;
12302 }
12303 }
12304
12305 /* Get width and height of the image, and allocate a raster buffer
12306 of width x height 32-bit values. */
12307 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
12308 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
12309 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
12310
12311 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
12312 TIFFClose (tiff);
12313 if (!rc)
12314 {
12315 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
12316 xfree (buf);
12317 UNGCPRO;
12318 return 0;
12319 }
12320
12321 /* Create the X image and pixmap. */
12322 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
12323 {
12324 xfree (buf);
12325 UNGCPRO;
12326 return 0;
12327 }
12328
12329 /* Initialize the color table. */
12330 init_color_table ();
12331
12332 /* Process the pixel raster. Origin is in the lower-left corner. */
12333 for (y = 0; y < height; ++y)
12334 {
12335 uint32 *row = buf + y * width;
12336
12337 for (x = 0; x < width; ++x)
12338 {
12339 uint32 abgr = row[x];
12340 int r = TIFFGetR (abgr) << 8;
12341 int g = TIFFGetG (abgr) << 8;
12342 int b = TIFFGetB (abgr) << 8;
12343 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
12344 }
12345 }
12346
12347 /* Remember the colors allocated for the image. Free the color table. */
12348 img->colors = colors_in_color_table (&img->ncolors);
12349 free_color_table ();
12350
12351 img->width = width;
12352 img->height = height;
12353
12354 /* Maybe fill in the background field while we have ximg handy. */
12355 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12356 IMAGE_BACKGROUND (img, f, ximg);
12357
12358 /* Put the image into the pixmap, then free the X image and its buffer. */
12359 x_put_x_image (f, ximg, img->pixmap, width, height);
12360 x_destroy_x_image (ximg);
12361 xfree (buf);
12362
12363 UNGCPRO;
12364 return 1;
12365 }
12366
12367 #endif /* HAVE_TIFF != 0 */
12368
12369
12370 \f
12371 /***********************************************************************
12372 GIF
12373 ***********************************************************************/
12374
12375 #if HAVE_GIF
12376
12377 #include <gif_lib.h>
12378
12379 static int gif_image_p P_ ((Lisp_Object object));
12380 static int gif_load P_ ((struct frame *f, struct image *img));
12381
12382 /* The symbol `gif' identifying images of this type. */
12383
12384 Lisp_Object Qgif;
12385
12386 /* Indices of image specification fields in gif_format, below. */
12387
12388 enum gif_keyword_index
12389 {
12390 GIF_TYPE,
12391 GIF_DATA,
12392 GIF_FILE,
12393 GIF_ASCENT,
12394 GIF_MARGIN,
12395 GIF_RELIEF,
12396 GIF_ALGORITHM,
12397 GIF_HEURISTIC_MASK,
12398 GIF_MASK,
12399 GIF_IMAGE,
12400 GIF_BACKGROUND,
12401 GIF_LAST
12402 };
12403
12404 /* Vector of image_keyword structures describing the format
12405 of valid user-defined image specifications. */
12406
12407 static struct image_keyword gif_format[GIF_LAST] =
12408 {
12409 {":type", IMAGE_SYMBOL_VALUE, 1},
12410 {":data", IMAGE_STRING_VALUE, 0},
12411 {":file", IMAGE_STRING_VALUE, 0},
12412 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12413 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12414 {":relief", IMAGE_INTEGER_VALUE, 0},
12415 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12416 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12417 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12418 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12419 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12420 };
12421
12422 /* Structure describing the image type `gif'. */
12423
12424 static struct image_type gif_type =
12425 {
12426 &Qgif,
12427 gif_image_p,
12428 gif_load,
12429 x_clear_image,
12430 NULL
12431 };
12432
12433 /* Return non-zero if OBJECT is a valid GIF image specification. */
12434
12435 static int
12436 gif_image_p (object)
12437 Lisp_Object object;
12438 {
12439 struct image_keyword fmt[GIF_LAST];
12440 bcopy (gif_format, fmt, sizeof fmt);
12441
12442 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
12443 || (fmt[GIF_ASCENT].count
12444 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
12445 return 0;
12446
12447 /* Must specify either the :data or :file keyword. */
12448 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
12449 }
12450
12451 /* Reading a GIF image from memory
12452 Based on the PNG memory stuff to a certain extent. */
12453
12454 typedef struct
12455 {
12456 unsigned char *bytes;
12457 size_t len;
12458 int index;
12459 }
12460 gif_memory_source;
12461
12462 /* Make the current memory source available to gif_read_from_memory.
12463 It's done this way because not all versions of libungif support
12464 a UserData field in the GifFileType structure. */
12465 static gif_memory_source *current_gif_memory_src;
12466
12467 static int
12468 gif_read_from_memory (file, buf, len)
12469 GifFileType *file;
12470 GifByteType *buf;
12471 int len;
12472 {
12473 gif_memory_source *src = current_gif_memory_src;
12474
12475 if (len > src->len - src->index)
12476 return -1;
12477
12478 bcopy (src->bytes + src->index, buf, len);
12479 src->index += len;
12480 return len;
12481 }
12482
12483
12484 /* Load GIF image IMG for use on frame F. Value is non-zero if
12485 successful. */
12486
12487 static int
12488 gif_load (f, img)
12489 struct frame *f;
12490 struct image *img;
12491 {
12492 Lisp_Object file, specified_file;
12493 Lisp_Object specified_data;
12494 int rc, width, height, x, y, i;
12495 XImage *ximg;
12496 ColorMapObject *gif_color_map;
12497 unsigned long pixel_colors[256];
12498 GifFileType *gif;
12499 struct gcpro gcpro1;
12500 Lisp_Object image;
12501 int ino, image_left, image_top, image_width, image_height;
12502 gif_memory_source memsrc;
12503 unsigned char *raster;
12504
12505 specified_file = image_spec_value (img->spec, QCfile, NULL);
12506 specified_data = image_spec_value (img->spec, QCdata, NULL);
12507 file = Qnil;
12508 GCPRO1 (file);
12509
12510 if (NILP (specified_data))
12511 {
12512 file = x_find_image_file (specified_file);
12513 if (!STRINGP (file))
12514 {
12515 image_error ("Cannot find image file `%s'", specified_file, Qnil);
12516 UNGCPRO;
12517 return 0;
12518 }
12519
12520 /* Open the GIF file. */
12521 gif = DGifOpenFileName (XSTRING (file)->data);
12522 if (gif == NULL)
12523 {
12524 image_error ("Cannot open `%s'", file, Qnil);
12525 UNGCPRO;
12526 return 0;
12527 }
12528 }
12529 else
12530 {
12531 /* Read from memory! */
12532 current_gif_memory_src = &memsrc;
12533 memsrc.bytes = XSTRING (specified_data)->data;
12534 memsrc.len = STRING_BYTES (XSTRING (specified_data));
12535 memsrc.index = 0;
12536
12537 gif = DGifOpen(&memsrc, gif_read_from_memory);
12538 if (!gif)
12539 {
12540 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
12541 UNGCPRO;
12542 return 0;
12543 }
12544 }
12545
12546 /* Read entire contents. */
12547 rc = DGifSlurp (gif);
12548 if (rc == GIF_ERROR)
12549 {
12550 image_error ("Error reading `%s'", img->spec, Qnil);
12551 DGifCloseFile (gif);
12552 UNGCPRO;
12553 return 0;
12554 }
12555
12556 image = image_spec_value (img->spec, QCindex, NULL);
12557 ino = INTEGERP (image) ? XFASTINT (image) : 0;
12558 if (ino >= gif->ImageCount)
12559 {
12560 image_error ("Invalid image number `%s' in image `%s'",
12561 image, img->spec);
12562 DGifCloseFile (gif);
12563 UNGCPRO;
12564 return 0;
12565 }
12566
12567 width = img->width = gif->SWidth;
12568 height = img->height = gif->SHeight;
12569
12570 /* Create the X image and pixmap. */
12571 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
12572 {
12573 DGifCloseFile (gif);
12574 UNGCPRO;
12575 return 0;
12576 }
12577
12578 /* Allocate colors. */
12579 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
12580 if (!gif_color_map)
12581 gif_color_map = gif->SColorMap;
12582 init_color_table ();
12583 bzero (pixel_colors, sizeof pixel_colors);
12584
12585 for (i = 0; i < gif_color_map->ColorCount; ++i)
12586 {
12587 int r = gif_color_map->Colors[i].Red << 8;
12588 int g = gif_color_map->Colors[i].Green << 8;
12589 int b = gif_color_map->Colors[i].Blue << 8;
12590 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
12591 }
12592
12593 img->colors = colors_in_color_table (&img->ncolors);
12594 free_color_table ();
12595
12596 /* Clear the part of the screen image that are not covered by
12597 the image from the GIF file. Full animated GIF support
12598 requires more than can be done here (see the gif89 spec,
12599 disposal methods). Let's simply assume that the part
12600 not covered by a sub-image is in the frame's background color. */
12601 image_top = gif->SavedImages[ino].ImageDesc.Top;
12602 image_left = gif->SavedImages[ino].ImageDesc.Left;
12603 image_width = gif->SavedImages[ino].ImageDesc.Width;
12604 image_height = gif->SavedImages[ino].ImageDesc.Height;
12605
12606 for (y = 0; y < image_top; ++y)
12607 for (x = 0; x < width; ++x)
12608 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12609
12610 for (y = image_top + image_height; y < height; ++y)
12611 for (x = 0; x < width; ++x)
12612 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12613
12614 for (y = image_top; y < image_top + image_height; ++y)
12615 {
12616 for (x = 0; x < image_left; ++x)
12617 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12618 for (x = image_left + image_width; x < width; ++x)
12619 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12620 }
12621
12622 /* Read the GIF image into the X image. We use a local variable
12623 `raster' here because RasterBits below is a char *, and invites
12624 problems with bytes >= 0x80. */
12625 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
12626
12627 if (gif->SavedImages[ino].ImageDesc.Interlace)
12628 {
12629 static int interlace_start[] = {0, 4, 2, 1};
12630 static int interlace_increment[] = {8, 8, 4, 2};
12631 int pass;
12632 int row = interlace_start[0];
12633
12634 pass = 0;
12635
12636 for (y = 0; y < image_height; y++)
12637 {
12638 if (row >= image_height)
12639 {
12640 row = interlace_start[++pass];
12641 while (row >= image_height)
12642 row = interlace_start[++pass];
12643 }
12644
12645 for (x = 0; x < image_width; x++)
12646 {
12647 int i = raster[(y * image_width) + x];
12648 XPutPixel (ximg, x + image_left, row + image_top,
12649 pixel_colors[i]);
12650 }
12651
12652 row += interlace_increment[pass];
12653 }
12654 }
12655 else
12656 {
12657 for (y = 0; y < image_height; ++y)
12658 for (x = 0; x < image_width; ++x)
12659 {
12660 int i = raster[y* image_width + x];
12661 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
12662 }
12663 }
12664
12665 DGifCloseFile (gif);
12666
12667 /* Maybe fill in the background field while we have ximg handy. */
12668 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12669 IMAGE_BACKGROUND (img, f, ximg);
12670
12671 /* Put the image into the pixmap, then free the X image and its buffer. */
12672 x_put_x_image (f, ximg, img->pixmap, width, height);
12673 x_destroy_x_image (ximg);
12674
12675 UNGCPRO;
12676 return 1;
12677 }
12678
12679 #endif /* HAVE_GIF != 0 */
12680
12681
12682 \f
12683 /***********************************************************************
12684 Ghostscript
12685 ***********************************************************************/
12686
12687 Lisp_Object Qpostscript;
12688
12689 #ifdef HAVE_GHOSTSCRIPT
12690 static int gs_image_p P_ ((Lisp_Object object));
12691 static int gs_load P_ ((struct frame *f, struct image *img));
12692 static void gs_clear_image P_ ((struct frame *f, struct image *img));
12693
12694 /* The symbol `postscript' identifying images of this type. */
12695
12696 /* Keyword symbols. */
12697
12698 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
12699
12700 /* Indices of image specification fields in gs_format, below. */
12701
12702 enum gs_keyword_index
12703 {
12704 GS_TYPE,
12705 GS_PT_WIDTH,
12706 GS_PT_HEIGHT,
12707 GS_FILE,
12708 GS_LOADER,
12709 GS_BOUNDING_BOX,
12710 GS_ASCENT,
12711 GS_MARGIN,
12712 GS_RELIEF,
12713 GS_ALGORITHM,
12714 GS_HEURISTIC_MASK,
12715 GS_MASK,
12716 GS_BACKGROUND,
12717 GS_LAST
12718 };
12719
12720 /* Vector of image_keyword structures describing the format
12721 of valid user-defined image specifications. */
12722
12723 static struct image_keyword gs_format[GS_LAST] =
12724 {
12725 {":type", IMAGE_SYMBOL_VALUE, 1},
12726 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12727 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12728 {":file", IMAGE_STRING_VALUE, 1},
12729 {":loader", IMAGE_FUNCTION_VALUE, 0},
12730 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
12731 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12732 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12733 {":relief", IMAGE_INTEGER_VALUE, 0},
12734 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12735 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12736 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12737 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12738 };
12739
12740 /* Structure describing the image type `ghostscript'. */
12741
12742 static struct image_type gs_type =
12743 {
12744 &Qpostscript,
12745 gs_image_p,
12746 gs_load,
12747 gs_clear_image,
12748 NULL
12749 };
12750
12751
12752 /* Free X resources of Ghostscript image IMG which is used on frame F. */
12753
12754 static void
12755 gs_clear_image (f, img)
12756 struct frame *f;
12757 struct image *img;
12758 {
12759 /* IMG->data.ptr_val may contain a recorded colormap. */
12760 xfree (img->data.ptr_val);
12761 x_clear_image (f, img);
12762 }
12763
12764
12765 /* Return non-zero if OBJECT is a valid Ghostscript image
12766 specification. */
12767
12768 static int
12769 gs_image_p (object)
12770 Lisp_Object object;
12771 {
12772 struct image_keyword fmt[GS_LAST];
12773 Lisp_Object tem;
12774 int i;
12775
12776 bcopy (gs_format, fmt, sizeof fmt);
12777
12778 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
12779 || (fmt[GS_ASCENT].count
12780 && XFASTINT (fmt[GS_ASCENT].value) > 100))
12781 return 0;
12782
12783 /* Bounding box must be a list or vector containing 4 integers. */
12784 tem = fmt[GS_BOUNDING_BOX].value;
12785 if (CONSP (tem))
12786 {
12787 for (i = 0; i < 4; ++i, tem = XCDR (tem))
12788 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
12789 return 0;
12790 if (!NILP (tem))
12791 return 0;
12792 }
12793 else if (VECTORP (tem))
12794 {
12795 if (XVECTOR (tem)->size != 4)
12796 return 0;
12797 for (i = 0; i < 4; ++i)
12798 if (!INTEGERP (XVECTOR (tem)->contents[i]))
12799 return 0;
12800 }
12801 else
12802 return 0;
12803
12804 return 1;
12805 }
12806
12807
12808 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
12809 if successful. */
12810
12811 static int
12812 gs_load (f, img)
12813 struct frame *f;
12814 struct image *img;
12815 {
12816 char buffer[100];
12817 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
12818 struct gcpro gcpro1, gcpro2;
12819 Lisp_Object frame;
12820 double in_width, in_height;
12821 Lisp_Object pixel_colors = Qnil;
12822
12823 /* Compute pixel size of pixmap needed from the given size in the
12824 image specification. Sizes in the specification are in pt. 1 pt
12825 = 1/72 in, xdpi and ydpi are stored in the frame's X display
12826 info. */
12827 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
12828 in_width = XFASTINT (pt_width) / 72.0;
12829 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
12830 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
12831 in_height = XFASTINT (pt_height) / 72.0;
12832 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
12833
12834 /* Create the pixmap. */
12835 BLOCK_INPUT;
12836 xassert (img->pixmap == 0);
12837 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12838 img->width, img->height,
12839 one_w32_display_info.n_cbits);
12840 UNBLOCK_INPUT;
12841
12842 if (!img->pixmap)
12843 {
12844 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
12845 return 0;
12846 }
12847
12848 /* Call the loader to fill the pixmap. It returns a process object
12849 if successful. We do not record_unwind_protect here because
12850 other places in redisplay like calling window scroll functions
12851 don't either. Let the Lisp loader use `unwind-protect' instead. */
12852 GCPRO2 (window_and_pixmap_id, pixel_colors);
12853
12854 sprintf (buffer, "%lu %lu",
12855 (unsigned long) FRAME_W32_WINDOW (f),
12856 (unsigned long) img->pixmap);
12857 window_and_pixmap_id = build_string (buffer);
12858
12859 sprintf (buffer, "%lu %lu",
12860 FRAME_FOREGROUND_PIXEL (f),
12861 FRAME_BACKGROUND_PIXEL (f));
12862 pixel_colors = build_string (buffer);
12863
12864 XSETFRAME (frame, f);
12865 loader = image_spec_value (img->spec, QCloader, NULL);
12866 if (NILP (loader))
12867 loader = intern ("gs-load-image");
12868
12869 img->data.lisp_val = call6 (loader, frame, img->spec,
12870 make_number (img->width),
12871 make_number (img->height),
12872 window_and_pixmap_id,
12873 pixel_colors);
12874 UNGCPRO;
12875 return PROCESSP (img->data.lisp_val);
12876 }
12877
12878
12879 /* Kill the Ghostscript process that was started to fill PIXMAP on
12880 frame F. Called from XTread_socket when receiving an event
12881 telling Emacs that Ghostscript has finished drawing. */
12882
12883 void
12884 x_kill_gs_process (pixmap, f)
12885 Pixmap pixmap;
12886 struct frame *f;
12887 {
12888 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
12889 int class, i;
12890 struct image *img;
12891
12892 /* Find the image containing PIXMAP. */
12893 for (i = 0; i < c->used; ++i)
12894 if (c->images[i]->pixmap == pixmap)
12895 break;
12896
12897 /* Should someone in between have cleared the image cache, for
12898 instance, give up. */
12899 if (i == c->used)
12900 return;
12901
12902 /* Kill the GS process. We should have found PIXMAP in the image
12903 cache and its image should contain a process object. */
12904 img = c->images[i];
12905 xassert (PROCESSP (img->data.lisp_val));
12906 Fkill_process (img->data.lisp_val, Qnil);
12907 img->data.lisp_val = Qnil;
12908
12909 /* On displays with a mutable colormap, figure out the colors
12910 allocated for the image by looking at the pixels of an XImage for
12911 img->pixmap. */
12912 class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
12913 if (class != StaticColor && class != StaticGray && class != TrueColor)
12914 {
12915 XImage *ximg;
12916
12917 BLOCK_INPUT;
12918
12919 /* Try to get an XImage for img->pixmep. */
12920 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
12921 0, 0, img->width, img->height, ~0, ZPixmap);
12922 if (ximg)
12923 {
12924 int x, y;
12925
12926 /* Initialize the color table. */
12927 init_color_table ();
12928
12929 /* For each pixel of the image, look its color up in the
12930 color table. After having done so, the color table will
12931 contain an entry for each color used by the image. */
12932 for (y = 0; y < img->height; ++y)
12933 for (x = 0; x < img->width; ++x)
12934 {
12935 unsigned long pixel = XGetPixel (ximg, x, y);
12936 lookup_pixel_color (f, pixel);
12937 }
12938
12939 /* Record colors in the image. Free color table and XImage. */
12940 img->colors = colors_in_color_table (&img->ncolors);
12941 free_color_table ();
12942 XDestroyImage (ximg);
12943
12944 #if 0 /* This doesn't seem to be the case. If we free the colors
12945 here, we get a BadAccess later in x_clear_image when
12946 freeing the colors. */
12947 /* We have allocated colors once, but Ghostscript has also
12948 allocated colors on behalf of us. So, to get the
12949 reference counts right, free them once. */
12950 if (img->ncolors)
12951 x_free_colors (FRAME_W32_DISPLAY (f), cmap,
12952 img->colors, img->ncolors, 0);
12953 #endif
12954 }
12955 else
12956 image_error ("Cannot get X image of `%s'; colors will not be freed",
12957 img->spec, Qnil);
12958
12959 UNBLOCK_INPUT;
12960 }
12961
12962 /* Now that we have the pixmap, compute mask and transform the
12963 image if requested. */
12964 BLOCK_INPUT;
12965 postprocess_image (f, img);
12966 UNBLOCK_INPUT;
12967 }
12968
12969 #endif /* HAVE_GHOSTSCRIPT */
12970
12971 \f
12972 /***********************************************************************
12973 Window properties
12974 ***********************************************************************/
12975
12976 DEFUN ("x-change-window-property", Fx_change_window_property,
12977 Sx_change_window_property, 2, 3, 0,
12978 doc: /* Change window property PROP to VALUE on the X window of FRAME.
12979 PROP and VALUE must be strings. FRAME nil or omitted means use the
12980 selected frame. Value is VALUE. */)
12981 (prop, value, frame)
12982 Lisp_Object frame, prop, value;
12983 {
12984 #if 0 /* TODO : port window properties to W32 */
12985 struct frame *f = check_x_frame (frame);
12986 Atom prop_atom;
12987
12988 CHECK_STRING (prop);
12989 CHECK_STRING (value);
12990
12991 BLOCK_INPUT;
12992 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
12993 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12994 prop_atom, XA_STRING, 8, PropModeReplace,
12995 XSTRING (value)->data, XSTRING (value)->size);
12996
12997 /* Make sure the property is set when we return. */
12998 XFlush (FRAME_W32_DISPLAY (f));
12999 UNBLOCK_INPUT;
13000
13001 #endif /* TODO */
13002
13003 return value;
13004 }
13005
13006
13007 DEFUN ("x-delete-window-property", Fx_delete_window_property,
13008 Sx_delete_window_property, 1, 2, 0,
13009 doc: /* Remove window property PROP from X window of FRAME.
13010 FRAME nil or omitted means use the selected frame. Value is PROP. */)
13011 (prop, frame)
13012 Lisp_Object prop, frame;
13013 {
13014 #if 0 /* TODO : port window properties to W32 */
13015
13016 struct frame *f = check_x_frame (frame);
13017 Atom prop_atom;
13018
13019 CHECK_STRING (prop);
13020 BLOCK_INPUT;
13021 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
13022 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
13023
13024 /* Make sure the property is removed when we return. */
13025 XFlush (FRAME_W32_DISPLAY (f));
13026 UNBLOCK_INPUT;
13027 #endif /* TODO */
13028
13029 return prop;
13030 }
13031
13032
13033 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
13034 1, 2, 0,
13035 doc: /* Value is the value of window property PROP on FRAME.
13036 If FRAME is nil or omitted, use the selected frame. Value is nil
13037 if FRAME hasn't a property with name PROP or if PROP has no string
13038 value. */)
13039 (prop, frame)
13040 Lisp_Object prop, frame;
13041 {
13042 #if 0 /* TODO : port window properties to W32 */
13043
13044 struct frame *f = check_x_frame (frame);
13045 Atom prop_atom;
13046 int rc;
13047 Lisp_Object prop_value = Qnil;
13048 char *tmp_data = NULL;
13049 Atom actual_type;
13050 int actual_format;
13051 unsigned long actual_size, bytes_remaining;
13052
13053 CHECK_STRING (prop);
13054 BLOCK_INPUT;
13055 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
13056 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
13057 prop_atom, 0, 0, False, XA_STRING,
13058 &actual_type, &actual_format, &actual_size,
13059 &bytes_remaining, (unsigned char **) &tmp_data);
13060 if (rc == Success)
13061 {
13062 int size = bytes_remaining;
13063
13064 XFree (tmp_data);
13065 tmp_data = NULL;
13066
13067 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
13068 prop_atom, 0, bytes_remaining,
13069 False, XA_STRING,
13070 &actual_type, &actual_format,
13071 &actual_size, &bytes_remaining,
13072 (unsigned char **) &tmp_data);
13073 if (rc == Success)
13074 prop_value = make_string (tmp_data, size);
13075
13076 XFree (tmp_data);
13077 }
13078
13079 UNBLOCK_INPUT;
13080
13081 return prop_value;
13082
13083 #endif /* TODO */
13084 return Qnil;
13085 }
13086
13087
13088 \f
13089 /***********************************************************************
13090 Busy cursor
13091 ***********************************************************************/
13092
13093 /* If non-null, an asynchronous timer that, when it expires, displays
13094 an hourglass cursor on all frames. */
13095
13096 static struct atimer *hourglass_atimer;
13097
13098 /* Non-zero means an hourglass cursor is currently shown. */
13099
13100 static int hourglass_shown_p;
13101
13102 /* Number of seconds to wait before displaying an hourglass cursor. */
13103
13104 static Lisp_Object Vhourglass_delay;
13105
13106 /* Default number of seconds to wait before displaying an hourglass
13107 cursor. */
13108
13109 #define DEFAULT_HOURGLASS_DELAY 1
13110
13111 /* Function prototypes. */
13112
13113 static void show_hourglass P_ ((struct atimer *));
13114 static void hide_hourglass P_ ((void));
13115
13116
13117 /* Cancel a currently active hourglass timer, and start a new one. */
13118
13119 void
13120 start_hourglass ()
13121 {
13122 #if 0 /* TODO: cursor shape changes. */
13123 EMACS_TIME delay;
13124 int secs, usecs = 0;
13125
13126 cancel_hourglass ();
13127
13128 if (INTEGERP (Vhourglass_delay)
13129 && XINT (Vhourglass_delay) > 0)
13130 secs = XFASTINT (Vhourglass_delay);
13131 else if (FLOATP (Vhourglass_delay)
13132 && XFLOAT_DATA (Vhourglass_delay) > 0)
13133 {
13134 Lisp_Object tem;
13135 tem = Ftruncate (Vhourglass_delay, Qnil);
13136 secs = XFASTINT (tem);
13137 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
13138 }
13139 else
13140 secs = DEFAULT_HOURGLASS_DELAY;
13141
13142 EMACS_SET_SECS_USECS (delay, secs, usecs);
13143 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
13144 show_hourglass, NULL);
13145 #endif
13146 }
13147
13148
13149 /* Cancel the hourglass cursor timer if active, hide an hourglass
13150 cursor if shown. */
13151
13152 void
13153 cancel_hourglass ()
13154 {
13155 if (hourglass_atimer)
13156 {
13157 cancel_atimer (hourglass_atimer);
13158 hourglass_atimer = NULL;
13159 }
13160
13161 if (hourglass_shown_p)
13162 hide_hourglass ();
13163 }
13164
13165
13166 /* Timer function of hourglass_atimer. TIMER is equal to
13167 hourglass_atimer.
13168
13169 Display an hourglass cursor on all frames by mapping the frames'
13170 hourglass_window. Set the hourglass_p flag in the frames'
13171 output_data.x structure to indicate that an hourglass cursor is
13172 shown on the frames. */
13173
13174 static void
13175 show_hourglass (timer)
13176 struct atimer *timer;
13177 {
13178 #if 0 /* TODO: cursor shape changes. */
13179 /* The timer implementation will cancel this timer automatically
13180 after this function has run. Set hourglass_atimer to null
13181 so that we know the timer doesn't have to be canceled. */
13182 hourglass_atimer = NULL;
13183
13184 if (!hourglass_shown_p)
13185 {
13186 Lisp_Object rest, frame;
13187
13188 BLOCK_INPUT;
13189
13190 FOR_EACH_FRAME (rest, frame)
13191 if (FRAME_W32_P (XFRAME (frame)))
13192 {
13193 struct frame *f = XFRAME (frame);
13194
13195 f->output_data.w32->hourglass_p = 1;
13196
13197 if (!f->output_data.w32->hourglass_window)
13198 {
13199 unsigned long mask = CWCursor;
13200 XSetWindowAttributes attrs;
13201
13202 attrs.cursor = f->output_data.w32->hourglass_cursor;
13203
13204 f->output_data.w32->hourglass_window
13205 = XCreateWindow (FRAME_X_DISPLAY (f),
13206 FRAME_OUTER_WINDOW (f),
13207 0, 0, 32000, 32000, 0, 0,
13208 InputOnly,
13209 CopyFromParent,
13210 mask, &attrs);
13211 }
13212
13213 XMapRaised (FRAME_X_DISPLAY (f),
13214 f->output_data.w32->hourglass_window);
13215 XFlush (FRAME_X_DISPLAY (f));
13216 }
13217
13218 hourglass_shown_p = 1;
13219 UNBLOCK_INPUT;
13220 }
13221 #endif
13222 }
13223
13224
13225 /* Hide the hourglass cursor on all frames, if it is currently shown. */
13226
13227 static void
13228 hide_hourglass ()
13229 {
13230 #if 0 /* TODO: cursor shape changes. */
13231 if (hourglass_shown_p)
13232 {
13233 Lisp_Object rest, frame;
13234
13235 BLOCK_INPUT;
13236 FOR_EACH_FRAME (rest, frame)
13237 {
13238 struct frame *f = XFRAME (frame);
13239
13240 if (FRAME_W32_P (f)
13241 /* Watch out for newly created frames. */
13242 && f->output_data.x->hourglass_window)
13243 {
13244 XUnmapWindow (FRAME_X_DISPLAY (f),
13245 f->output_data.x->hourglass_window);
13246 /* Sync here because XTread_socket looks at the
13247 hourglass_p flag that is reset to zero below. */
13248 XSync (FRAME_X_DISPLAY (f), False);
13249 f->output_data.x->hourglass_p = 0;
13250 }
13251 }
13252
13253 hourglass_shown_p = 0;
13254 UNBLOCK_INPUT;
13255 }
13256 #endif
13257 }
13258
13259
13260 \f
13261 /***********************************************************************
13262 Tool tips
13263 ***********************************************************************/
13264
13265 static Lisp_Object x_create_tip_frame P_ ((struct w32_display_info *,
13266 Lisp_Object, Lisp_Object));
13267 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
13268 Lisp_Object, int, int, int *, int *));
13269
13270 /* The frame of a currently visible tooltip. */
13271
13272 Lisp_Object tip_frame;
13273
13274 /* If non-nil, a timer started that hides the last tooltip when it
13275 fires. */
13276
13277 Lisp_Object tip_timer;
13278 Window tip_window;
13279
13280 /* If non-nil, a vector of 3 elements containing the last args
13281 with which x-show-tip was called. See there. */
13282
13283 Lisp_Object last_show_tip_args;
13284
13285 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
13286
13287 Lisp_Object Vx_max_tooltip_size;
13288
13289
13290 static Lisp_Object
13291 unwind_create_tip_frame (frame)
13292 Lisp_Object frame;
13293 {
13294 Lisp_Object deleted;
13295
13296 deleted = unwind_create_frame (frame);
13297 if (EQ (deleted, Qt))
13298 {
13299 tip_window = NULL;
13300 tip_frame = Qnil;
13301 }
13302
13303 return deleted;
13304 }
13305
13306
13307 /* Create a frame for a tooltip on the display described by DPYINFO.
13308 PARMS is a list of frame parameters. TEXT is the string to
13309 display in the tip frame. Value is the frame.
13310
13311 Note that functions called here, esp. x_default_parameter can
13312 signal errors, for instance when a specified color name is
13313 undefined. We have to make sure that we're in a consistent state
13314 when this happens. */
13315
13316 static Lisp_Object
13317 x_create_tip_frame (dpyinfo, parms, text)
13318 struct w32_display_info *dpyinfo;
13319 Lisp_Object parms, text;
13320 {
13321 struct frame *f;
13322 Lisp_Object frame, tem;
13323 Lisp_Object name;
13324 long window_prompting = 0;
13325 int width, height;
13326 int count = BINDING_STACK_SIZE ();
13327 struct gcpro gcpro1, gcpro2, gcpro3;
13328 struct kboard *kb;
13329 int face_change_count_before = face_change_count;
13330 Lisp_Object buffer;
13331 struct buffer *old_buffer;
13332
13333 check_w32 ();
13334
13335 /* Use this general default value to start with until we know if
13336 this frame has a specified name. */
13337 Vx_resource_name = Vinvocation_name;
13338
13339 #ifdef MULTI_KBOARD
13340 kb = dpyinfo->kboard;
13341 #else
13342 kb = &the_only_kboard;
13343 #endif
13344
13345 /* Get the name of the frame to use for resource lookup. */
13346 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
13347 if (!STRINGP (name)
13348 && !EQ (name, Qunbound)
13349 && !NILP (name))
13350 error ("Invalid frame name--not a string or nil");
13351 Vx_resource_name = name;
13352
13353 frame = Qnil;
13354 GCPRO3 (parms, name, frame);
13355 /* Make a frame without minibuffer nor mode-line. */
13356 f = make_frame (0);
13357 f->wants_modeline = 0;
13358 XSETFRAME (frame, f);
13359
13360 buffer = Fget_buffer_create (build_string (" *tip*"));
13361 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
13362 old_buffer = current_buffer;
13363 set_buffer_internal_1 (XBUFFER (buffer));
13364 current_buffer->truncate_lines = Qnil;
13365 Ferase_buffer ();
13366 Finsert (1, &text);
13367 set_buffer_internal_1 (old_buffer);
13368
13369 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
13370 record_unwind_protect (unwind_create_tip_frame, frame);
13371
13372 /* By setting the output method, we're essentially saying that
13373 the frame is live, as per FRAME_LIVE_P. If we get a signal
13374 from this point on, x_destroy_window might screw up reference
13375 counts etc. */
13376 f->output_method = output_w32;
13377 f->output_data.w32 =
13378 (struct w32_output *) xmalloc (sizeof (struct w32_output));
13379 bzero (f->output_data.w32, sizeof (struct w32_output));
13380
13381 FRAME_FONTSET (f) = -1;
13382 f->icon_name = Qnil;
13383
13384 #if 0 /* GLYPH_DEBUG TODO: image support. */
13385 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
13386 dpyinfo_refcount = dpyinfo->reference_count;
13387 #endif /* GLYPH_DEBUG */
13388 #ifdef MULTI_KBOARD
13389 FRAME_KBOARD (f) = kb;
13390 #endif
13391 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
13392 f->output_data.w32->explicit_parent = 0;
13393
13394 /* Set the name; the functions to which we pass f expect the name to
13395 be set. */
13396 if (EQ (name, Qunbound) || NILP (name))
13397 {
13398 f->name = build_string (dpyinfo->w32_id_name);
13399 f->explicit_name = 0;
13400 }
13401 else
13402 {
13403 f->name = name;
13404 f->explicit_name = 1;
13405 /* use the frame's title when getting resources for this frame. */
13406 specbind (Qx_resource_name, name);
13407 }
13408
13409 /* Extract the window parameters from the supplied values
13410 that are needed to determine window geometry. */
13411 {
13412 Lisp_Object font;
13413
13414 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
13415
13416 BLOCK_INPUT;
13417 /* First, try whatever font the caller has specified. */
13418 if (STRINGP (font))
13419 {
13420 tem = Fquery_fontset (font, Qnil);
13421 if (STRINGP (tem))
13422 font = x_new_fontset (f, XSTRING (tem)->data);
13423 else
13424 font = x_new_font (f, XSTRING (font)->data);
13425 }
13426
13427 /* Try out a font which we hope has bold and italic variations. */
13428 if (!STRINGP (font))
13429 font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
13430 if (! STRINGP (font))
13431 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
13432 /* If those didn't work, look for something which will at least work. */
13433 if (! STRINGP (font))
13434 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
13435 UNBLOCK_INPUT;
13436 if (! STRINGP (font))
13437 font = build_string ("Fixedsys");
13438
13439 x_default_parameter (f, parms, Qfont, font,
13440 "font", "Font", RES_TYPE_STRING);
13441 }
13442
13443 x_default_parameter (f, parms, Qborder_width, make_number (2),
13444 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
13445 /* This defaults to 2 in order to match xterm. We recognize either
13446 internalBorderWidth or internalBorder (which is what xterm calls
13447 it). */
13448 if (NILP (Fassq (Qinternal_border_width, parms)))
13449 {
13450 Lisp_Object value;
13451
13452 value = w32_get_arg (parms, Qinternal_border_width,
13453 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
13454 if (! EQ (value, Qunbound))
13455 parms = Fcons (Fcons (Qinternal_border_width, value),
13456 parms);
13457 }
13458 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
13459 "internalBorderWidth", "internalBorderWidth",
13460 RES_TYPE_NUMBER);
13461
13462 /* Also do the stuff which must be set before the window exists. */
13463 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
13464 "foreground", "Foreground", RES_TYPE_STRING);
13465 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
13466 "background", "Background", RES_TYPE_STRING);
13467 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
13468 "pointerColor", "Foreground", RES_TYPE_STRING);
13469 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
13470 "cursorColor", "Foreground", RES_TYPE_STRING);
13471 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
13472 "borderColor", "BorderColor", RES_TYPE_STRING);
13473
13474 /* Init faces before x_default_parameter is called for scroll-bar
13475 parameters because that function calls x_set_scroll_bar_width,
13476 which calls change_frame_size, which calls Fset_window_buffer,
13477 which runs hooks, which call Fvertical_motion. At the end, we
13478 end up in init_iterator with a null face cache, which should not
13479 happen. */
13480 init_frame_faces (f);
13481
13482 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
13483 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
13484
13485 window_prompting = x_figure_window_size (f, parms);
13486
13487 /* No fringes on tip frame. */
13488 f->output_data.w32->fringes_extra = 0;
13489 f->output_data.w32->fringe_cols = 0;
13490 f->output_data.w32->left_fringe_width = 0;
13491 f->output_data.w32->right_fringe_width = 0;
13492
13493 if (window_prompting & XNegative)
13494 {
13495 if (window_prompting & YNegative)
13496 f->output_data.w32->win_gravity = SouthEastGravity;
13497 else
13498 f->output_data.w32->win_gravity = NorthEastGravity;
13499 }
13500 else
13501 {
13502 if (window_prompting & YNegative)
13503 f->output_data.w32->win_gravity = SouthWestGravity;
13504 else
13505 f->output_data.w32->win_gravity = NorthWestGravity;
13506 }
13507
13508 f->output_data.w32->size_hint_flags = window_prompting;
13509
13510 BLOCK_INPUT;
13511 my_create_tip_window (f);
13512 UNBLOCK_INPUT;
13513
13514 x_make_gc (f);
13515
13516 x_default_parameter (f, parms, Qauto_raise, Qnil,
13517 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
13518 x_default_parameter (f, parms, Qauto_lower, Qnil,
13519 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
13520 x_default_parameter (f, parms, Qcursor_type, Qbox,
13521 "cursorType", "CursorType", RES_TYPE_SYMBOL);
13522
13523 /* Dimensions, especially f->height, must be done via change_frame_size.
13524 Change will not be effected unless different from the current
13525 f->height. */
13526 width = f->width;
13527 height = f->height;
13528 f->height = 0;
13529 SET_FRAME_WIDTH (f, 0);
13530 change_frame_size (f, height, width, 1, 0, 0);
13531
13532 /* Set up faces after all frame parameters are known. This call
13533 also merges in face attributes specified for new frames.
13534
13535 Frame parameters may be changed if .Xdefaults contains
13536 specifications for the default font. For example, if there is an
13537 `Emacs.default.attributeBackground: pink', the `background-color'
13538 attribute of the frame get's set, which let's the internal border
13539 of the tooltip frame appear in pink. Prevent this. */
13540 {
13541 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
13542
13543 /* Set tip_frame here, so that */
13544 tip_frame = frame;
13545 call1 (Qface_set_after_frame_default, frame);
13546
13547 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
13548 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
13549 Qnil));
13550 }
13551
13552 f->no_split = 1;
13553
13554 UNGCPRO;
13555
13556 /* It is now ok to make the frame official even if we get an error
13557 below. And the frame needs to be on Vframe_list or making it
13558 visible won't work. */
13559 Vframe_list = Fcons (frame, Vframe_list);
13560
13561 /* Now that the frame is official, it counts as a reference to
13562 its display. */
13563 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
13564
13565 /* Setting attributes of faces of the tooltip frame from resources
13566 and similar will increment face_change_count, which leads to the
13567 clearing of all current matrices. Since this isn't necessary
13568 here, avoid it by resetting face_change_count to the value it
13569 had before we created the tip frame. */
13570 face_change_count = face_change_count_before;
13571
13572 /* Discard the unwind_protect. */
13573 return unbind_to (count, frame);
13574 }
13575
13576
13577 /* Compute where to display tip frame F. PARMS is the list of frame
13578 parameters for F. DX and DY are specified offsets from the current
13579 location of the mouse. WIDTH and HEIGHT are the width and height
13580 of the tooltip. Return coordinates relative to the root window of
13581 the display in *ROOT_X, and *ROOT_Y. */
13582
13583 static void
13584 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
13585 struct frame *f;
13586 Lisp_Object parms, dx, dy;
13587 int width, height;
13588 int *root_x, *root_y;
13589 {
13590 Lisp_Object left, top;
13591
13592 /* User-specified position? */
13593 left = Fcdr (Fassq (Qleft, parms));
13594 top = Fcdr (Fassq (Qtop, parms));
13595
13596 /* Move the tooltip window where the mouse pointer is. Resize and
13597 show it. */
13598 if (!INTEGERP (left) || !INTEGERP (top))
13599 {
13600 POINT pt;
13601
13602 BLOCK_INPUT;
13603 GetCursorPos (&pt);
13604 *root_x = pt.x;
13605 *root_y = pt.y;
13606 UNBLOCK_INPUT;
13607 }
13608
13609 if (INTEGERP (top))
13610 *root_y = XINT (top);
13611 else if (*root_y + XINT (dy) - height < 0)
13612 *root_y -= XINT (dy);
13613 else
13614 {
13615 *root_y -= height;
13616 *root_y += XINT (dy);
13617 }
13618
13619 if (INTEGERP (left))
13620 *root_x = XINT (left);
13621 else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width)
13622 /* It fits to the right of the pointer. */
13623 *root_x += XINT (dx);
13624 else if (width + XINT (dx) <= *root_x)
13625 /* It fits to the left of the pointer. */
13626 *root_x -= width + XINT (dx);
13627 else
13628 /* Put it left justified on the screen -- it ought to fit that way. */
13629 *root_x = 0;
13630 }
13631
13632
13633 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
13634 doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
13635 A tooltip window is a small window displaying a string.
13636
13637 FRAME nil or omitted means use the selected frame.
13638
13639 PARMS is an optional list of frame parameters which can be
13640 used to change the tooltip's appearance.
13641
13642 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
13643 means use the default timeout of 5 seconds.
13644
13645 If the list of frame parameters PARAMS contains a `left' parameter,
13646 the tooltip is displayed at that x-position. Otherwise it is
13647 displayed at the mouse position, with offset DX added (default is 5 if
13648 DX isn't specified). Likewise for the y-position; if a `top' frame
13649 parameter is specified, it determines the y-position of the tooltip
13650 window, otherwise it is displayed at the mouse position, with offset
13651 DY added (default is -10).
13652
13653 A tooltip's maximum size is specified by `x-max-tooltip-size'.
13654 Text larger than the specified size is clipped. */)
13655 (string, frame, parms, timeout, dx, dy)
13656 Lisp_Object string, frame, parms, timeout, dx, dy;
13657 {
13658 struct frame *f;
13659 struct window *w;
13660 int root_x, root_y;
13661 struct buffer *old_buffer;
13662 struct text_pos pos;
13663 int i, width, height;
13664 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
13665 int old_windows_or_buffers_changed = windows_or_buffers_changed;
13666 int count = BINDING_STACK_SIZE ();
13667
13668 specbind (Qinhibit_redisplay, Qt);
13669
13670 GCPRO4 (string, parms, frame, timeout);
13671
13672 CHECK_STRING (string);
13673 f = check_x_frame (frame);
13674 if (NILP (timeout))
13675 timeout = make_number (5);
13676 else
13677 CHECK_NATNUM (timeout);
13678
13679 if (NILP (dx))
13680 dx = make_number (5);
13681 else
13682 CHECK_NUMBER (dx);
13683
13684 if (NILP (dy))
13685 dy = make_number (-10);
13686 else
13687 CHECK_NUMBER (dy);
13688
13689 if (NILP (last_show_tip_args))
13690 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
13691
13692 if (!NILP (tip_frame))
13693 {
13694 Lisp_Object last_string = AREF (last_show_tip_args, 0);
13695 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
13696 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
13697
13698 if (EQ (frame, last_frame)
13699 && !NILP (Fequal (last_string, string))
13700 && !NILP (Fequal (last_parms, parms)))
13701 {
13702 struct frame *f = XFRAME (tip_frame);
13703
13704 /* Only DX and DY have changed. */
13705 if (!NILP (tip_timer))
13706 {
13707 Lisp_Object timer = tip_timer;
13708 tip_timer = Qnil;
13709 call1 (Qcancel_timer, timer);
13710 }
13711
13712 BLOCK_INPUT;
13713 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
13714 PIXEL_HEIGHT (f), &root_x, &root_y);
13715
13716 /* Put tooltip in topmost group and in position. */
13717 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
13718 root_x, root_y, 0, 0,
13719 SWP_NOSIZE | SWP_NOACTIVATE);
13720
13721 /* Ensure tooltip is on top of other topmost windows (eg menus). */
13722 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
13723 0, 0, 0, 0,
13724 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
13725
13726 UNBLOCK_INPUT;
13727 goto start_timer;
13728 }
13729 }
13730
13731 /* Hide a previous tip, if any. */
13732 Fx_hide_tip ();
13733
13734 ASET (last_show_tip_args, 0, string);
13735 ASET (last_show_tip_args, 1, frame);
13736 ASET (last_show_tip_args, 2, parms);
13737
13738 /* Add default values to frame parameters. */
13739 if (NILP (Fassq (Qname, parms)))
13740 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
13741 if (NILP (Fassq (Qinternal_border_width, parms)))
13742 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
13743 if (NILP (Fassq (Qborder_width, parms)))
13744 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
13745 if (NILP (Fassq (Qborder_color, parms)))
13746 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
13747 if (NILP (Fassq (Qbackground_color, parms)))
13748 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
13749 parms);
13750
13751 /* Block input until the tip has been fully drawn, to avoid crashes
13752 when drawing tips in menus. */
13753 BLOCK_INPUT;
13754
13755 /* Create a frame for the tooltip, and record it in the global
13756 variable tip_frame. */
13757 frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
13758 f = XFRAME (frame);
13759
13760 /* Set up the frame's root window. */
13761 w = XWINDOW (FRAME_ROOT_WINDOW (f));
13762 w->left = w->top = make_number (0);
13763
13764 if (CONSP (Vx_max_tooltip_size)
13765 && INTEGERP (XCAR (Vx_max_tooltip_size))
13766 && XINT (XCAR (Vx_max_tooltip_size)) > 0
13767 && INTEGERP (XCDR (Vx_max_tooltip_size))
13768 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
13769 {
13770 w->width = XCAR (Vx_max_tooltip_size);
13771 w->height = XCDR (Vx_max_tooltip_size);
13772 }
13773 else
13774 {
13775 w->width = make_number (80);
13776 w->height = make_number (40);
13777 }
13778
13779 f->window_width = XINT (w->width);
13780 adjust_glyphs (f);
13781 w->pseudo_window_p = 1;
13782
13783 /* Display the tooltip text in a temporary buffer. */
13784 old_buffer = current_buffer;
13785 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
13786 current_buffer->truncate_lines = Qnil;
13787 clear_glyph_matrix (w->desired_matrix);
13788 clear_glyph_matrix (w->current_matrix);
13789 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
13790 try_window (FRAME_ROOT_WINDOW (f), pos);
13791
13792 /* Compute width and height of the tooltip. */
13793 width = height = 0;
13794 for (i = 0; i < w->desired_matrix->nrows; ++i)
13795 {
13796 struct glyph_row *row = &w->desired_matrix->rows[i];
13797 struct glyph *last;
13798 int row_width;
13799
13800 /* Stop at the first empty row at the end. */
13801 if (!row->enabled_p || !row->displays_text_p)
13802 break;
13803
13804 /* Let the row go over the full width of the frame. */
13805 row->full_width_p = 1;
13806
13807 #ifdef TODO /* Investigate why some fonts need more width than is
13808 calculated for some tooltips. */
13809 /* There's a glyph at the end of rows that is use to place
13810 the cursor there. Don't include the width of this glyph. */
13811 if (row->used[TEXT_AREA])
13812 {
13813 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
13814 row_width = row->pixel_width - last->pixel_width;
13815 }
13816 else
13817 #endif
13818 row_width = row->pixel_width;
13819
13820 /* TODO: find why tips do not draw along baseline as instructed. */
13821 height += row->height;
13822 width = max (width, row_width);
13823 }
13824
13825 /* Add the frame's internal border to the width and height the X
13826 window should have. */
13827 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
13828 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
13829
13830 /* Move the tooltip window where the mouse pointer is. Resize and
13831 show it. */
13832 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
13833
13834 {
13835 /* Adjust Window size to take border into account. */
13836 RECT rect;
13837 rect.left = rect.top = 0;
13838 rect.right = width;
13839 rect.bottom = height;
13840 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
13841 FRAME_EXTERNAL_MENU_BAR (f));
13842
13843 /* Position and size tooltip, and put it in the topmost group. */
13844 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
13845 root_x, root_y, rect.right - rect.left,
13846 rect.bottom - rect.top, SWP_NOACTIVATE);
13847
13848 /* Ensure tooltip is on top of other topmost windows (eg menus). */
13849 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
13850 0, 0, 0, 0,
13851 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
13852
13853 /* Let redisplay know that we have made the frame visible already. */
13854 f->async_visible = 1;
13855
13856 ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
13857 }
13858
13859 /* Draw into the window. */
13860 w->must_be_updated_p = 1;
13861 update_single_window (w, 1);
13862
13863 UNBLOCK_INPUT;
13864
13865 /* Restore original current buffer. */
13866 set_buffer_internal_1 (old_buffer);
13867 windows_or_buffers_changed = old_windows_or_buffers_changed;
13868
13869 start_timer:
13870 /* Let the tip disappear after timeout seconds. */
13871 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
13872 intern ("x-hide-tip"));
13873
13874 UNGCPRO;
13875 return unbind_to (count, Qnil);
13876 }
13877
13878
13879 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
13880 doc: /* Hide the current tooltip window, if there is any.
13881 Value is t if tooltip was open, nil otherwise. */)
13882 ()
13883 {
13884 int count;
13885 Lisp_Object deleted, frame, timer;
13886 struct gcpro gcpro1, gcpro2;
13887
13888 /* Return quickly if nothing to do. */
13889 if (NILP (tip_timer) && NILP (tip_frame))
13890 return Qnil;
13891
13892 frame = tip_frame;
13893 timer = tip_timer;
13894 GCPRO2 (frame, timer);
13895 tip_frame = tip_timer = deleted = Qnil;
13896
13897 count = BINDING_STACK_SIZE ();
13898 specbind (Qinhibit_redisplay, Qt);
13899 specbind (Qinhibit_quit, Qt);
13900
13901 if (!NILP (timer))
13902 call1 (Qcancel_timer, timer);
13903
13904 if (FRAMEP (frame))
13905 {
13906 Fdelete_frame (frame, Qnil);
13907 deleted = Qt;
13908 }
13909
13910 UNGCPRO;
13911 return unbind_to (count, deleted);
13912 }
13913
13914
13915 \f
13916 /***********************************************************************
13917 File selection dialog
13918 ***********************************************************************/
13919
13920 extern Lisp_Object Qfile_name_history;
13921
13922 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
13923 doc: /* Read file name, prompting with PROMPT in directory DIR.
13924 Use a file selection dialog.
13925 Select DEFAULT-FILENAME in the dialog's file selection box, if
13926 specified. Ensure that file exists if MUSTMATCH is non-nil. */)
13927 (prompt, dir, default_filename, mustmatch)
13928 Lisp_Object prompt, dir, default_filename, mustmatch;
13929 {
13930 struct frame *f = SELECTED_FRAME ();
13931 Lisp_Object file = Qnil;
13932 int count = specpdl_ptr - specpdl;
13933 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
13934 char filename[MAX_PATH + 1];
13935 char init_dir[MAX_PATH + 1];
13936 int use_dialog_p = 1;
13937
13938 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
13939 CHECK_STRING (prompt);
13940 CHECK_STRING (dir);
13941
13942 /* Create the dialog with PROMPT as title, using DIR as initial
13943 directory and using "*" as pattern. */
13944 dir = Fexpand_file_name (dir, Qnil);
13945 strncpy (init_dir, XSTRING (dir)->data, MAX_PATH);
13946 init_dir[MAX_PATH] = '\0';
13947 unixtodos_filename (init_dir);
13948
13949 if (STRINGP (default_filename))
13950 {
13951 char *file_name_only;
13952 char *full_path_name = XSTRING (default_filename)->data;
13953
13954 unixtodos_filename (full_path_name);
13955
13956 file_name_only = strrchr (full_path_name, '\\');
13957 if (!file_name_only)
13958 file_name_only = full_path_name;
13959 else
13960 {
13961 file_name_only++;
13962
13963 /* If default_file_name is a directory, don't use the open
13964 file dialog, as it does not support selecting
13965 directories. */
13966 if (!(*file_name_only))
13967 use_dialog_p = 0;
13968 }
13969
13970 strncpy (filename, file_name_only, MAX_PATH);
13971 filename[MAX_PATH] = '\0';
13972 }
13973 else
13974 filename[0] = '\0';
13975
13976 if (use_dialog_p)
13977 {
13978 OPENFILENAME file_details;
13979
13980 /* Prevent redisplay. */
13981 specbind (Qinhibit_redisplay, Qt);
13982 BLOCK_INPUT;
13983
13984 bzero (&file_details, sizeof (file_details));
13985 file_details.lStructSize = sizeof (file_details);
13986 file_details.hwndOwner = FRAME_W32_WINDOW (f);
13987 /* Undocumented Bug in Common File Dialog:
13988 If a filter is not specified, shell links are not resolved. */
13989 file_details.lpstrFilter = "ALL Files (*.*)\0*.*\0\0";
13990 file_details.lpstrFile = filename;
13991 file_details.nMaxFile = sizeof (filename);
13992 file_details.lpstrInitialDir = init_dir;
13993 file_details.lpstrTitle = XSTRING (prompt)->data;
13994 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
13995
13996 if (!NILP (mustmatch))
13997 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
13998
13999 if (GetOpenFileName (&file_details))
14000 {
14001 dostounix_filename (filename);
14002 file = build_string (filename);
14003 }
14004 else
14005 file = Qnil;
14006
14007 UNBLOCK_INPUT;
14008 file = unbind_to (count, file);
14009 }
14010 /* Open File dialog will not allow folders to be selected, so resort
14011 to minibuffer completing reads for directories. */
14012 else
14013 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
14014 dir, mustmatch, dir, Qfile_name_history,
14015 default_filename, Qnil);
14016
14017 UNGCPRO;
14018
14019 /* Make "Cancel" equivalent to C-g. */
14020 if (NILP (file))
14021 Fsignal (Qquit, Qnil);
14022
14023 return unbind_to (count, file);
14024 }
14025
14026
14027 \f
14028 /***********************************************************************
14029 w32 specialized functions
14030 ***********************************************************************/
14031
14032 DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 2, 0,
14033 doc: /* Select a font using the W32 font dialog.
14034 Returns an X font string corresponding to the selection. */)
14035 (frame, include_proportional)
14036 Lisp_Object frame, include_proportional;
14037 {
14038 FRAME_PTR f = check_x_frame (frame);
14039 CHOOSEFONT cf;
14040 LOGFONT lf;
14041 TEXTMETRIC tm;
14042 HDC hdc;
14043 HANDLE oldobj;
14044 char buf[100];
14045
14046 bzero (&cf, sizeof (cf));
14047 bzero (&lf, sizeof (lf));
14048
14049 cf.lStructSize = sizeof (cf);
14050 cf.hwndOwner = FRAME_W32_WINDOW (f);
14051 cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS | CF_NOVERTFONTS;
14052
14053 /* Unless include_proportional is non-nil, limit the selection to
14054 monospaced fonts. */
14055 if (NILP (include_proportional))
14056 cf.Flags |= CF_FIXEDPITCHONLY;
14057
14058 cf.lpLogFont = &lf;
14059
14060 /* Initialize as much of the font details as we can from the current
14061 default font. */
14062 hdc = GetDC (FRAME_W32_WINDOW (f));
14063 oldobj = SelectObject (hdc, FRAME_FONT (f)->hfont);
14064 GetTextFace (hdc, LF_FACESIZE, lf.lfFaceName);
14065 if (GetTextMetrics (hdc, &tm))
14066 {
14067 lf.lfHeight = tm.tmInternalLeading - tm.tmHeight;
14068 lf.lfWeight = tm.tmWeight;
14069 lf.lfItalic = tm.tmItalic;
14070 lf.lfUnderline = tm.tmUnderlined;
14071 lf.lfStrikeOut = tm.tmStruckOut;
14072 lf.lfCharSet = tm.tmCharSet;
14073 cf.Flags |= CF_INITTOLOGFONTSTRUCT;
14074 }
14075 SelectObject (hdc, oldobj);
14076 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
14077
14078 if (!ChooseFont (&cf) || !w32_to_x_font (&lf, buf, 100, NULL))
14079 return Qnil;
14080
14081 return build_string (buf);
14082 }
14083
14084 DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
14085 Sw32_send_sys_command, 1, 2, 0,
14086 doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
14087 Some useful values for command are #xf030 to maximise frame (#xf020
14088 to minimize), #xf120 to restore frame to original size, and #xf100
14089 to activate the menubar for keyboard access. #xf140 activates the
14090 screen saver if defined.
14091
14092 If optional parameter FRAME is not specified, use selected frame. */)
14093 (command, frame)
14094 Lisp_Object command, frame;
14095 {
14096 FRAME_PTR f = check_x_frame (frame);
14097
14098 CHECK_NUMBER (command);
14099
14100 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
14101
14102 return Qnil;
14103 }
14104
14105 DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
14106 doc: /* Get Windows to perform OPERATION on DOCUMENT.
14107 This is a wrapper around the ShellExecute system function, which
14108 invokes the application registered to handle OPERATION for DOCUMENT.
14109 OPERATION is typically \"open\", \"print\" or \"explore\" (but can be
14110 nil for the default action), and DOCUMENT is typically the name of a
14111 document file or URL, but can also be a program executable to run or
14112 a directory to open in the Windows Explorer.
14113
14114 If DOCUMENT is a program executable, PARAMETERS can be a string
14115 containing command line parameters, but otherwise should be nil.
14116
14117 SHOW-FLAG can be used to control whether the invoked application is hidden
14118 or minimized. If SHOW-FLAG is nil, the application is displayed normally,
14119 otherwise it is an integer representing a ShowWindow flag:
14120
14121 0 - start hidden
14122 1 - start normally
14123 3 - start maximized
14124 6 - start minimized */)
14125 (operation, document, parameters, show_flag)
14126 Lisp_Object operation, document, parameters, show_flag;
14127 {
14128 Lisp_Object current_dir;
14129
14130 CHECK_STRING (document);
14131
14132 /* Encode filename and current directory. */
14133 current_dir = ENCODE_FILE (current_buffer->directory);
14134 document = ENCODE_FILE (document);
14135 if ((int) ShellExecute (NULL,
14136 (STRINGP (operation) ?
14137 XSTRING (operation)->data : NULL),
14138 XSTRING (document)->data,
14139 (STRINGP (parameters) ?
14140 XSTRING (parameters)->data : NULL),
14141 XSTRING (current_dir)->data,
14142 (INTEGERP (show_flag) ?
14143 XINT (show_flag) : SW_SHOWDEFAULT))
14144 > 32)
14145 return Qt;
14146 error ("ShellExecute failed: %s", w32_strerror (0));
14147 }
14148
14149 /* Lookup virtual keycode from string representing the name of a
14150 non-ascii keystroke into the corresponding virtual key, using
14151 lispy_function_keys. */
14152 static int
14153 lookup_vk_code (char *key)
14154 {
14155 int i;
14156
14157 for (i = 0; i < 256; i++)
14158 if (lispy_function_keys[i] != 0
14159 && strcmp (lispy_function_keys[i], key) == 0)
14160 return i;
14161
14162 return -1;
14163 }
14164
14165 /* Convert a one-element vector style key sequence to a hot key
14166 definition. */
14167 static int
14168 w32_parse_hot_key (key)
14169 Lisp_Object key;
14170 {
14171 /* Copied from Fdefine_key and store_in_keymap. */
14172 register Lisp_Object c;
14173 int vk_code;
14174 int lisp_modifiers;
14175 int w32_modifiers;
14176 struct gcpro gcpro1;
14177
14178 CHECK_VECTOR (key);
14179
14180 if (XFASTINT (Flength (key)) != 1)
14181 return Qnil;
14182
14183 GCPRO1 (key);
14184
14185 c = Faref (key, make_number (0));
14186
14187 if (CONSP (c) && lucid_event_type_list_p (c))
14188 c = Fevent_convert_list (c);
14189
14190 UNGCPRO;
14191
14192 if (! INTEGERP (c) && ! SYMBOLP (c))
14193 error ("Key definition is invalid");
14194
14195 /* Work out the base key and the modifiers. */
14196 if (SYMBOLP (c))
14197 {
14198 c = parse_modifiers (c);
14199 lisp_modifiers = Fcar (Fcdr (c));
14200 c = Fcar (c);
14201 if (!SYMBOLP (c))
14202 abort ();
14203 vk_code = lookup_vk_code (XSYMBOL (c)->name->data);
14204 }
14205 else if (INTEGERP (c))
14206 {
14207 lisp_modifiers = XINT (c) & ~CHARACTERBITS;
14208 /* Many ascii characters are their own virtual key code. */
14209 vk_code = XINT (c) & CHARACTERBITS;
14210 }
14211
14212 if (vk_code < 0 || vk_code > 255)
14213 return Qnil;
14214
14215 if ((lisp_modifiers & meta_modifier) != 0
14216 && !NILP (Vw32_alt_is_meta))
14217 lisp_modifiers |= alt_modifier;
14218
14219 /* Supply defs missing from mingw32. */
14220 #ifndef MOD_ALT
14221 #define MOD_ALT 0x0001
14222 #define MOD_CONTROL 0x0002
14223 #define MOD_SHIFT 0x0004
14224 #define MOD_WIN 0x0008
14225 #endif
14226
14227 /* Convert lisp modifiers to Windows hot-key form. */
14228 w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0;
14229 w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0;
14230 w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0;
14231 w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0;
14232
14233 return HOTKEY (vk_code, w32_modifiers);
14234 }
14235
14236 DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
14237 Sw32_register_hot_key, 1, 1, 0,
14238 doc: /* Register KEY as a hot-key combination.
14239 Certain key combinations like Alt-Tab are reserved for system use on
14240 Windows, and therefore are normally intercepted by the system. However,
14241 most of these key combinations can be received by registering them as
14242 hot-keys, overriding their special meaning.
14243
14244 KEY must be a one element key definition in vector form that would be
14245 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
14246 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
14247 is always interpreted as the Windows modifier keys.
14248
14249 The return value is the hotkey-id if registered, otherwise nil. */)
14250 (key)
14251 Lisp_Object key;
14252 {
14253 key = w32_parse_hot_key (key);
14254
14255 if (NILP (Fmemq (key, w32_grabbed_keys)))
14256 {
14257 /* Reuse an empty slot if possible. */
14258 Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
14259
14260 /* Safe to add new key to list, even if we have focus. */
14261 if (NILP (item))
14262 w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
14263 else
14264 XSETCAR (item, key);
14265
14266 /* Notify input thread about new hot-key definition, so that it
14267 takes effect without needing to switch focus. */
14268 PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
14269 (WPARAM) key, 0);
14270 }
14271
14272 return key;
14273 }
14274
14275 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
14276 Sw32_unregister_hot_key, 1, 1, 0,
14277 doc: /* Unregister HOTKEY as a hot-key combination. */)
14278 (key)
14279 Lisp_Object key;
14280 {
14281 Lisp_Object item;
14282
14283 if (!INTEGERP (key))
14284 key = w32_parse_hot_key (key);
14285
14286 item = Fmemq (key, w32_grabbed_keys);
14287
14288 if (!NILP (item))
14289 {
14290 /* Notify input thread about hot-key definition being removed, so
14291 that it takes effect without needing focus switch. */
14292 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
14293 (WPARAM) XINT (XCAR (item)), (LPARAM) item))
14294 {
14295 MSG msg;
14296 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
14297 }
14298 return Qt;
14299 }
14300 return Qnil;
14301 }
14302
14303 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
14304 Sw32_registered_hot_keys, 0, 0, 0,
14305 doc: /* Return list of registered hot-key IDs. */)
14306 ()
14307 {
14308 return Fcopy_sequence (w32_grabbed_keys);
14309 }
14310
14311 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
14312 Sw32_reconstruct_hot_key, 1, 1, 0,
14313 doc: /* Convert hot-key ID to a lisp key combination. */)
14314 (hotkeyid)
14315 Lisp_Object hotkeyid;
14316 {
14317 int vk_code, w32_modifiers;
14318 Lisp_Object key;
14319
14320 CHECK_NUMBER (hotkeyid);
14321
14322 vk_code = HOTKEY_VK_CODE (hotkeyid);
14323 w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
14324
14325 if (lispy_function_keys[vk_code])
14326 key = intern (lispy_function_keys[vk_code]);
14327 else
14328 key = make_number (vk_code);
14329
14330 key = Fcons (key, Qnil);
14331 if (w32_modifiers & MOD_SHIFT)
14332 key = Fcons (Qshift, key);
14333 if (w32_modifiers & MOD_CONTROL)
14334 key = Fcons (Qctrl, key);
14335 if (w32_modifiers & MOD_ALT)
14336 key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
14337 if (w32_modifiers & MOD_WIN)
14338 key = Fcons (Qhyper, key);
14339
14340 return key;
14341 }
14342
14343 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
14344 Sw32_toggle_lock_key, 1, 2, 0,
14345 doc: /* Toggle the state of the lock key KEY.
14346 KEY can be `capslock', `kp-numlock', or `scroll'.
14347 If the optional parameter NEW-STATE is a number, then the state of KEY
14348 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
14349 (key, new_state)
14350 Lisp_Object key, new_state;
14351 {
14352 int vk_code;
14353
14354 if (EQ (key, intern ("capslock")))
14355 vk_code = VK_CAPITAL;
14356 else if (EQ (key, intern ("kp-numlock")))
14357 vk_code = VK_NUMLOCK;
14358 else if (EQ (key, intern ("scroll")))
14359 vk_code = VK_SCROLL;
14360 else
14361 return Qnil;
14362
14363 if (!dwWindowsThreadId)
14364 return make_number (w32_console_toggle_lock_key (vk_code, new_state));
14365
14366 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
14367 (WPARAM) vk_code, (LPARAM) new_state))
14368 {
14369 MSG msg;
14370 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
14371 return make_number (msg.wParam);
14372 }
14373 return Qnil;
14374 }
14375 \f
14376 DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
14377 doc: /* Return storage information about the file system FILENAME is on.
14378 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
14379 storage of the file system, FREE is the free storage, and AVAIL is the
14380 storage available to a non-superuser. All 3 numbers are in bytes.
14381 If the underlying system call fails, value is nil. */)
14382 (filename)
14383 Lisp_Object filename;
14384 {
14385 Lisp_Object encoded, value;
14386
14387 CHECK_STRING (filename);
14388 filename = Fexpand_file_name (filename, Qnil);
14389 encoded = ENCODE_FILE (filename);
14390
14391 value = Qnil;
14392
14393 /* Determining the required information on Windows turns out, sadly,
14394 to be more involved than one would hope. The original Win32 api
14395 call for this will return bogus information on some systems, but we
14396 must dynamically probe for the replacement api, since that was
14397 added rather late on. */
14398 {
14399 HMODULE hKernel = GetModuleHandle ("kernel32");
14400 BOOL (*pfn_GetDiskFreeSpaceEx)
14401 (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
14402 = (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceEx");
14403
14404 /* On Windows, we may need to specify the root directory of the
14405 volume holding FILENAME. */
14406 char rootname[MAX_PATH];
14407 char *name = XSTRING (encoded)->data;
14408
14409 /* find the root name of the volume if given */
14410 if (isalpha (name[0]) && name[1] == ':')
14411 {
14412 rootname[0] = name[0];
14413 rootname[1] = name[1];
14414 rootname[2] = '\\';
14415 rootname[3] = 0;
14416 }
14417 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
14418 {
14419 char *str = rootname;
14420 int slashes = 4;
14421 do
14422 {
14423 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
14424 break;
14425 *str++ = *name++;
14426 }
14427 while ( *name );
14428
14429 *str++ = '\\';
14430 *str = 0;
14431 }
14432
14433 if (pfn_GetDiskFreeSpaceEx)
14434 {
14435 LARGE_INTEGER availbytes;
14436 LARGE_INTEGER freebytes;
14437 LARGE_INTEGER totalbytes;
14438
14439 if (pfn_GetDiskFreeSpaceEx(rootname,
14440 &availbytes,
14441 &totalbytes,
14442 &freebytes))
14443 value = list3 (make_float ((double) totalbytes.QuadPart),
14444 make_float ((double) freebytes.QuadPart),
14445 make_float ((double) availbytes.QuadPart));
14446 }
14447 else
14448 {
14449 DWORD sectors_per_cluster;
14450 DWORD bytes_per_sector;
14451 DWORD free_clusters;
14452 DWORD total_clusters;
14453
14454 if (GetDiskFreeSpace(rootname,
14455 &sectors_per_cluster,
14456 &bytes_per_sector,
14457 &free_clusters,
14458 &total_clusters))
14459 value = list3 (make_float ((double) total_clusters
14460 * sectors_per_cluster * bytes_per_sector),
14461 make_float ((double) free_clusters
14462 * sectors_per_cluster * bytes_per_sector),
14463 make_float ((double) free_clusters
14464 * sectors_per_cluster * bytes_per_sector));
14465 }
14466 }
14467
14468 return value;
14469 }
14470 \f
14471 /***********************************************************************
14472 Initialization
14473 ***********************************************************************/
14474
14475 void
14476 syms_of_w32fns ()
14477 {
14478 HMODULE user32_lib = GetModuleHandle ("user32.dll");
14479
14480 /* This is zero if not using MS-Windows. */
14481 w32_in_use = 0;
14482
14483 /* TrackMouseEvent not available in all versions of Windows, so must load
14484 it dynamically. Do it once, here, instead of every time it is used. */
14485 track_mouse_event_fn = GetProcAddress (user32_lib, "TrackMouseEvent");
14486 track_mouse_window = NULL;
14487
14488 w32_visible_system_caret_hwnd = NULL;
14489
14490 /* The section below is built by the lisp expression at the top of the file,
14491 just above where these variables are declared. */
14492 /*&&& init symbols here &&&*/
14493 Qauto_raise = intern ("auto-raise");
14494 staticpro (&Qauto_raise);
14495 Qauto_lower = intern ("auto-lower");
14496 staticpro (&Qauto_lower);
14497 Qbar = intern ("bar");
14498 staticpro (&Qbar);
14499 Qborder_color = intern ("border-color");
14500 staticpro (&Qborder_color);
14501 Qborder_width = intern ("border-width");
14502 staticpro (&Qborder_width);
14503 Qbox = intern ("box");
14504 staticpro (&Qbox);
14505 Qcursor_color = intern ("cursor-color");
14506 staticpro (&Qcursor_color);
14507 Qcursor_type = intern ("cursor-type");
14508 staticpro (&Qcursor_type);
14509 Qgeometry = intern ("geometry");
14510 staticpro (&Qgeometry);
14511 Qicon_left = intern ("icon-left");
14512 staticpro (&Qicon_left);
14513 Qicon_top = intern ("icon-top");
14514 staticpro (&Qicon_top);
14515 Qicon_type = intern ("icon-type");
14516 staticpro (&Qicon_type);
14517 Qicon_name = intern ("icon-name");
14518 staticpro (&Qicon_name);
14519 Qinternal_border_width = intern ("internal-border-width");
14520 staticpro (&Qinternal_border_width);
14521 Qleft = intern ("left");
14522 staticpro (&Qleft);
14523 Qright = intern ("right");
14524 staticpro (&Qright);
14525 Qmouse_color = intern ("mouse-color");
14526 staticpro (&Qmouse_color);
14527 Qnone = intern ("none");
14528 staticpro (&Qnone);
14529 Qparent_id = intern ("parent-id");
14530 staticpro (&Qparent_id);
14531 Qscroll_bar_width = intern ("scroll-bar-width");
14532 staticpro (&Qscroll_bar_width);
14533 Qsuppress_icon = intern ("suppress-icon");
14534 staticpro (&Qsuppress_icon);
14535 Qundefined_color = intern ("undefined-color");
14536 staticpro (&Qundefined_color);
14537 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
14538 staticpro (&Qvertical_scroll_bars);
14539 Qvisibility = intern ("visibility");
14540 staticpro (&Qvisibility);
14541 Qwindow_id = intern ("window-id");
14542 staticpro (&Qwindow_id);
14543 Qx_frame_parameter = intern ("x-frame-parameter");
14544 staticpro (&Qx_frame_parameter);
14545 Qx_resource_name = intern ("x-resource-name");
14546 staticpro (&Qx_resource_name);
14547 Quser_position = intern ("user-position");
14548 staticpro (&Quser_position);
14549 Quser_size = intern ("user-size");
14550 staticpro (&Quser_size);
14551 Qscreen_gamma = intern ("screen-gamma");
14552 staticpro (&Qscreen_gamma);
14553 Qline_spacing = intern ("line-spacing");
14554 staticpro (&Qline_spacing);
14555 Qcenter = intern ("center");
14556 staticpro (&Qcenter);
14557 Qcancel_timer = intern ("cancel-timer");
14558 staticpro (&Qcancel_timer);
14559 /* This is the end of symbol initialization. */
14560
14561 Qhyper = intern ("hyper");
14562 staticpro (&Qhyper);
14563 Qsuper = intern ("super");
14564 staticpro (&Qsuper);
14565 Qmeta = intern ("meta");
14566 staticpro (&Qmeta);
14567 Qalt = intern ("alt");
14568 staticpro (&Qalt);
14569 Qctrl = intern ("ctrl");
14570 staticpro (&Qctrl);
14571 Qcontrol = intern ("control");
14572 staticpro (&Qcontrol);
14573 Qshift = intern ("shift");
14574 staticpro (&Qshift);
14575
14576 /* Text property `display' should be nonsticky by default. */
14577 Vtext_property_default_nonsticky
14578 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
14579
14580
14581 Qlaplace = intern ("laplace");
14582 staticpro (&Qlaplace);
14583 Qemboss = intern ("emboss");
14584 staticpro (&Qemboss);
14585 Qedge_detection = intern ("edge-detection");
14586 staticpro (&Qedge_detection);
14587 Qheuristic = intern ("heuristic");
14588 staticpro (&Qheuristic);
14589 QCmatrix = intern (":matrix");
14590 staticpro (&QCmatrix);
14591 QCcolor_adjustment = intern (":color-adjustment");
14592 staticpro (&QCcolor_adjustment);
14593 QCmask = intern (":mask");
14594 staticpro (&QCmask);
14595
14596 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
14597 staticpro (&Qface_set_after_frame_default);
14598
14599 Fput (Qundefined_color, Qerror_conditions,
14600 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
14601 Fput (Qundefined_color, Qerror_message,
14602 build_string ("Undefined color"));
14603
14604 staticpro (&w32_grabbed_keys);
14605 w32_grabbed_keys = Qnil;
14606
14607 DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
14608 doc: /* An array of color name mappings for windows. */);
14609 Vw32_color_map = Qnil;
14610
14611 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
14612 doc: /* Non-nil if alt key presses are passed on to Windows.
14613 When non-nil, for example, alt pressed and released and then space will
14614 open the System menu. When nil, Emacs silently swallows alt key events. */);
14615 Vw32_pass_alt_to_system = Qnil;
14616
14617 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
14618 doc: /* Non-nil if the alt key is to be considered the same as the meta key.
14619 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta. */);
14620 Vw32_alt_is_meta = Qt;
14621
14622 DEFVAR_INT ("w32-quit-key", &Vw32_quit_key,
14623 doc: /* If non-zero, the virtual key code for an alternative quit key. */);
14624 XSETINT (Vw32_quit_key, 0);
14625
14626 DEFVAR_LISP ("w32-pass-lwindow-to-system",
14627 &Vw32_pass_lwindow_to_system,
14628 doc: /* Non-nil if the left \"Windows\" key is passed on to Windows.
14629 When non-nil, the Start menu is opened by tapping the key. */);
14630 Vw32_pass_lwindow_to_system = Qt;
14631
14632 DEFVAR_LISP ("w32-pass-rwindow-to-system",
14633 &Vw32_pass_rwindow_to_system,
14634 doc: /* Non-nil if the right \"Windows\" key is passed on to Windows.
14635 When non-nil, the Start menu is opened by tapping the key. */);
14636 Vw32_pass_rwindow_to_system = Qt;
14637
14638 DEFVAR_INT ("w32-phantom-key-code",
14639 &Vw32_phantom_key_code,
14640 doc: /* Virtual key code used to generate \"phantom\" key presses.
14641 Value is a number between 0 and 255.
14642
14643 Phantom key presses are generated in order to stop the system from
14644 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
14645 `w32-pass-rwindow-to-system' is nil. */);
14646 /* Although 255 is technically not a valid key code, it works and
14647 means that this hack won't interfere with any real key code. */
14648 Vw32_phantom_key_code = 255;
14649
14650 DEFVAR_LISP ("w32-enable-num-lock",
14651 &Vw32_enable_num_lock,
14652 doc: /* Non-nil if Num Lock should act normally.
14653 Set to nil to see Num Lock as the key `kp-numlock'. */);
14654 Vw32_enable_num_lock = Qt;
14655
14656 DEFVAR_LISP ("w32-enable-caps-lock",
14657 &Vw32_enable_caps_lock,
14658 doc: /* Non-nil if Caps Lock should act normally.
14659 Set to nil to see Caps Lock as the key `capslock'. */);
14660 Vw32_enable_caps_lock = Qt;
14661
14662 DEFVAR_LISP ("w32-scroll-lock-modifier",
14663 &Vw32_scroll_lock_modifier,
14664 doc: /* Modifier to use for the Scroll Lock on state.
14665 The value can be hyper, super, meta, alt, control or shift for the
14666 respective modifier, or nil to see Scroll Lock as the key `scroll'.
14667 Any other value will cause the key to be ignored. */);
14668 Vw32_scroll_lock_modifier = Qt;
14669
14670 DEFVAR_LISP ("w32-lwindow-modifier",
14671 &Vw32_lwindow_modifier,
14672 doc: /* Modifier to use for the left \"Windows\" key.
14673 The value can be hyper, super, meta, alt, control or shift for the
14674 respective modifier, or nil to appear as the key `lwindow'.
14675 Any other value will cause the key to be ignored. */);
14676 Vw32_lwindow_modifier = Qnil;
14677
14678 DEFVAR_LISP ("w32-rwindow-modifier",
14679 &Vw32_rwindow_modifier,
14680 doc: /* Modifier to use for the right \"Windows\" key.
14681 The value can be hyper, super, meta, alt, control or shift for the
14682 respective modifier, or nil to appear as the key `rwindow'.
14683 Any other value will cause the key to be ignored. */);
14684 Vw32_rwindow_modifier = Qnil;
14685
14686 DEFVAR_LISP ("w32-apps-modifier",
14687 &Vw32_apps_modifier,
14688 doc: /* Modifier to use for the \"Apps\" key.
14689 The value can be hyper, super, meta, alt, control or shift for the
14690 respective modifier, or nil to appear as the key `apps'.
14691 Any other value will cause the key to be ignored. */);
14692 Vw32_apps_modifier = Qnil;
14693
14694 DEFVAR_BOOL ("w32-enable-synthesized-fonts", &w32_enable_synthesized_fonts,
14695 doc: /* Non-nil enables selection of artificially italicized and bold fonts. */);
14696 w32_enable_synthesized_fonts = 0;
14697
14698 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette,
14699 doc: /* Non-nil enables Windows palette management to map colors exactly. */);
14700 Vw32_enable_palette = Qt;
14701
14702 DEFVAR_INT ("w32-mouse-button-tolerance",
14703 &Vw32_mouse_button_tolerance,
14704 doc: /* Analogue of double click interval for faking middle mouse events.
14705 The value is the minimum time in milliseconds that must elapse between
14706 left/right button down events before they are considered distinct events.
14707 If both mouse buttons are depressed within this interval, a middle mouse
14708 button down event is generated instead. */);
14709 XSETINT (Vw32_mouse_button_tolerance, GetDoubleClickTime () / 2);
14710
14711 DEFVAR_INT ("w32-mouse-move-interval",
14712 &Vw32_mouse_move_interval,
14713 doc: /* Minimum interval between mouse move events.
14714 The value is the minimum time in milliseconds that must elapse between
14715 successive mouse move (or scroll bar drag) events before they are
14716 reported as lisp events. */);
14717 XSETINT (Vw32_mouse_move_interval, 0);
14718
14719 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
14720 &w32_pass_extra_mouse_buttons_to_system,
14721 doc: /* Non-nil if the fourth and fifth mouse buttons are passed to Windows.
14722 Recent versions of Windows support mice with up to five buttons.
14723 Since most applications don't support these extra buttons, most mouse
14724 drivers will allow you to map them to functions at the system level.
14725 If this variable is non-nil, Emacs will pass them on, allowing the
14726 system to handle them. */);
14727 w32_pass_extra_mouse_buttons_to_system = 0;
14728
14729 init_x_parm_symbols ();
14730
14731 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
14732 doc: /* List of directories to search for bitmap files for w32. */);
14733 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
14734
14735 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
14736 doc: /* The shape of the pointer when over text.
14737 Changing the value does not affect existing frames
14738 unless you set the mouse color. */);
14739 Vx_pointer_shape = Qnil;
14740
14741 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
14742 doc: /* The name Emacs uses to look up resources; for internal use only.
14743 `x-get-resource' uses this as the first component of the instance name
14744 when requesting resource values.
14745 Emacs initially sets `x-resource-name' to the name under which Emacs
14746 was invoked, or to the value specified with the `-name' or `-rn'
14747 switches, if present. */);
14748 Vx_resource_name = Qnil;
14749
14750 Vx_nontext_pointer_shape = Qnil;
14751
14752 Vx_mode_pointer_shape = Qnil;
14753
14754 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
14755 doc: /* The shape of the pointer when Emacs is busy.
14756 This variable takes effect when you create a new frame
14757 or when you set the mouse color. */);
14758 Vx_hourglass_pointer_shape = Qnil;
14759
14760 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
14761 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
14762 display_hourglass_p = 1;
14763
14764 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
14765 doc: /* *Seconds to wait before displaying an hourglass pointer.
14766 Value must be an integer or float. */);
14767 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
14768
14769 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
14770 &Vx_sensitive_text_pointer_shape,
14771 doc: /* The shape of the pointer when over mouse-sensitive text.
14772 This variable takes effect when you create a new frame
14773 or when you set the mouse color. */);
14774 Vx_sensitive_text_pointer_shape = Qnil;
14775
14776 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
14777 &Vx_window_horizontal_drag_shape,
14778 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
14779 This variable takes effect when you create a new frame
14780 or when you set the mouse color. */);
14781 Vx_window_horizontal_drag_shape = Qnil;
14782
14783 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
14784 doc: /* A string indicating the foreground color of the cursor box. */);
14785 Vx_cursor_fore_pixel = Qnil;
14786
14787 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
14788 doc: /* Maximum size for tooltips.
14789 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
14790 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
14791
14792 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
14793 doc: /* Non-nil if no window manager is in use.
14794 Emacs doesn't try to figure this out; this is always nil
14795 unless you set it to something else. */);
14796 /* We don't have any way to find this out, so set it to nil
14797 and maybe the user would like to set it to t. */
14798 Vx_no_window_manager = Qnil;
14799
14800 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
14801 &Vx_pixel_size_width_font_regexp,
14802 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
14803
14804 Since Emacs gets width of a font matching with this regexp from
14805 PIXEL_SIZE field of the name, font finding mechanism gets faster for
14806 such a font. This is especially effective for such large fonts as
14807 Chinese, Japanese, and Korean. */);
14808 Vx_pixel_size_width_font_regexp = Qnil;
14809
14810 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
14811 doc: /* Time after which cached images are removed from the cache.
14812 When an image has not been displayed this many seconds, remove it
14813 from the image cache. Value must be an integer or nil with nil
14814 meaning don't clear the cache. */);
14815 Vimage_cache_eviction_delay = make_number (30 * 60);
14816
14817 DEFVAR_LISP ("w32-bdf-filename-alist",
14818 &Vw32_bdf_filename_alist,
14819 doc: /* List of bdf fonts and their corresponding filenames. */);
14820 Vw32_bdf_filename_alist = Qnil;
14821
14822 DEFVAR_BOOL ("w32-strict-fontnames",
14823 &w32_strict_fontnames,
14824 doc: /* Non-nil means only use fonts that are exact matches for those requested.
14825 Default is nil, which allows old fontnames that are not XLFD compliant,
14826 and allows third-party CJK display to work by specifying false charset
14827 fields to trick Emacs into translating to Big5, SJIS etc.
14828 Setting this to t will prevent wrong fonts being selected when
14829 fontsets are automatically created. */);
14830 w32_strict_fontnames = 0;
14831
14832 DEFVAR_BOOL ("w32-strict-painting",
14833 &w32_strict_painting,
14834 doc: /* Non-nil means use strict rules for repainting frames.
14835 Set this to nil to get the old behaviour for repainting; this should
14836 only be necessary if the default setting causes problems. */);
14837 w32_strict_painting = 1;
14838
14839 DEFVAR_LISP ("w32-charset-info-alist",
14840 &Vw32_charset_info_alist,
14841 doc: /* Alist linking Emacs character sets to Windows fonts and codepages.
14842 Each entry should be of the form:
14843
14844 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))
14845
14846 where CHARSET_NAME is a string used in font names to identify the charset,
14847 WINDOWS_CHARSET is a symbol that can be one of:
14848 w32-charset-ansi, w32-charset-default, w32-charset-symbol,
14849 w32-charset-shiftjis, w32-charset-hangeul, w32-charset-gb2312,
14850 w32-charset-chinesebig5,
14851 #ifdef JOHAB_CHARSET
14852 w32-charset-johab, w32-charset-hebrew,
14853 w32-charset-arabic, w32-charset-greek, w32-charset-turkish,
14854 w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,
14855 w32-charset-russian, w32-charset-mac, w32-charset-baltic,
14856 #endif
14857 #ifdef UNICODE_CHARSET
14858 w32-charset-unicode,
14859 #endif
14860 or w32-charset-oem.
14861 CODEPAGE should be an integer specifying the codepage that should be used
14862 to display the character set, t to do no translation and output as Unicode,
14863 or nil to do no translation and output as 8 bit (or multibyte on far-east
14864 versions of Windows) characters. */);
14865 Vw32_charset_info_alist = Qnil;
14866
14867 staticpro (&Qw32_charset_ansi);
14868 Qw32_charset_ansi = intern ("w32-charset-ansi");
14869 staticpro (&Qw32_charset_symbol);
14870 Qw32_charset_symbol = intern ("w32-charset-symbol");
14871 staticpro (&Qw32_charset_shiftjis);
14872 Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
14873 staticpro (&Qw32_charset_hangeul);
14874 Qw32_charset_hangeul = intern ("w32-charset-hangeul");
14875 staticpro (&Qw32_charset_chinesebig5);
14876 Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
14877 staticpro (&Qw32_charset_gb2312);
14878 Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
14879 staticpro (&Qw32_charset_oem);
14880 Qw32_charset_oem = intern ("w32-charset-oem");
14881
14882 #ifdef JOHAB_CHARSET
14883 {
14884 static int w32_extra_charsets_defined = 1;
14885 DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined,
14886 doc: /* Internal variable. */);
14887
14888 staticpro (&Qw32_charset_johab);
14889 Qw32_charset_johab = intern ("w32-charset-johab");
14890 staticpro (&Qw32_charset_easteurope);
14891 Qw32_charset_easteurope = intern ("w32-charset-easteurope");
14892 staticpro (&Qw32_charset_turkish);
14893 Qw32_charset_turkish = intern ("w32-charset-turkish");
14894 staticpro (&Qw32_charset_baltic);
14895 Qw32_charset_baltic = intern ("w32-charset-baltic");
14896 staticpro (&Qw32_charset_russian);
14897 Qw32_charset_russian = intern ("w32-charset-russian");
14898 staticpro (&Qw32_charset_arabic);
14899 Qw32_charset_arabic = intern ("w32-charset-arabic");
14900 staticpro (&Qw32_charset_greek);
14901 Qw32_charset_greek = intern ("w32-charset-greek");
14902 staticpro (&Qw32_charset_hebrew);
14903 Qw32_charset_hebrew = intern ("w32-charset-hebrew");
14904 staticpro (&Qw32_charset_vietnamese);
14905 Qw32_charset_vietnamese = intern ("w32-charset-vietnamese");
14906 staticpro (&Qw32_charset_thai);
14907 Qw32_charset_thai = intern ("w32-charset-thai");
14908 staticpro (&Qw32_charset_mac);
14909 Qw32_charset_mac = intern ("w32-charset-mac");
14910 }
14911 #endif
14912
14913 #ifdef UNICODE_CHARSET
14914 {
14915 static int w32_unicode_charset_defined = 1;
14916 DEFVAR_BOOL ("w32-unicode-charset-defined",
14917 &w32_unicode_charset_defined,
14918 doc: /* Internal variable. */);
14919
14920 staticpro (&Qw32_charset_unicode);
14921 Qw32_charset_unicode = intern ("w32-charset-unicode");
14922 #endif
14923
14924 defsubr (&Sx_get_resource);
14925 #if 0 /* TODO: Port to W32 */
14926 defsubr (&Sx_change_window_property);
14927 defsubr (&Sx_delete_window_property);
14928 defsubr (&Sx_window_property);
14929 #endif
14930 defsubr (&Sxw_display_color_p);
14931 defsubr (&Sx_display_grayscale_p);
14932 defsubr (&Sxw_color_defined_p);
14933 defsubr (&Sxw_color_values);
14934 defsubr (&Sx_server_max_request_size);
14935 defsubr (&Sx_server_vendor);
14936 defsubr (&Sx_server_version);
14937 defsubr (&Sx_display_pixel_width);
14938 defsubr (&Sx_display_pixel_height);
14939 defsubr (&Sx_display_mm_width);
14940 defsubr (&Sx_display_mm_height);
14941 defsubr (&Sx_display_screens);
14942 defsubr (&Sx_display_planes);
14943 defsubr (&Sx_display_color_cells);
14944 defsubr (&Sx_display_visual_class);
14945 defsubr (&Sx_display_backing_store);
14946 defsubr (&Sx_display_save_under);
14947 defsubr (&Sx_parse_geometry);
14948 defsubr (&Sx_create_frame);
14949 defsubr (&Sx_open_connection);
14950 defsubr (&Sx_close_connection);
14951 defsubr (&Sx_display_list);
14952 defsubr (&Sx_synchronize);
14953
14954 /* W32 specific functions */
14955
14956 defsubr (&Sw32_focus_frame);
14957 defsubr (&Sw32_select_font);
14958 defsubr (&Sw32_define_rgb_color);
14959 defsubr (&Sw32_default_color_map);
14960 defsubr (&Sw32_load_color_file);
14961 defsubr (&Sw32_send_sys_command);
14962 defsubr (&Sw32_shell_execute);
14963 defsubr (&Sw32_register_hot_key);
14964 defsubr (&Sw32_unregister_hot_key);
14965 defsubr (&Sw32_registered_hot_keys);
14966 defsubr (&Sw32_reconstruct_hot_key);
14967 defsubr (&Sw32_toggle_lock_key);
14968 defsubr (&Sw32_find_bdf_fonts);
14969
14970 defsubr (&Sfile_system_info);
14971
14972 /* Setting callback functions for fontset handler. */
14973 get_font_info_func = w32_get_font_info;
14974
14975 #if 0 /* This function pointer doesn't seem to be used anywhere.
14976 And the pointer assigned has the wrong type, anyway. */
14977 list_fonts_func = w32_list_fonts;
14978 #endif
14979
14980 load_font_func = w32_load_font;
14981 find_ccl_program_func = w32_find_ccl_program;
14982 query_font_func = w32_query_font;
14983 set_frame_fontset_func = x_set_font;
14984 check_window_system_func = check_w32;
14985
14986 #if 0 /* TODO Image support for W32 */
14987 /* Images. */
14988 Qxbm = intern ("xbm");
14989 staticpro (&Qxbm);
14990 QCtype = intern (":type");
14991 staticpro (&QCtype);
14992 QCconversion = intern (":conversion");
14993 staticpro (&QCconversion);
14994 QCheuristic_mask = intern (":heuristic-mask");
14995 staticpro (&QCheuristic_mask);
14996 QCcolor_symbols = intern (":color-symbols");
14997 staticpro (&QCcolor_symbols);
14998 QCascent = intern (":ascent");
14999 staticpro (&QCascent);
15000 QCmargin = intern (":margin");
15001 staticpro (&QCmargin);
15002 QCrelief = intern (":relief");
15003 staticpro (&QCrelief);
15004 Qpostscript = intern ("postscript");
15005 staticpro (&Qpostscript);
15006 QCloader = intern (":loader");
15007 staticpro (&QCloader);
15008 QCbounding_box = intern (":bounding-box");
15009 staticpro (&QCbounding_box);
15010 QCpt_width = intern (":pt-width");
15011 staticpro (&QCpt_width);
15012 QCpt_height = intern (":pt-height");
15013 staticpro (&QCpt_height);
15014 QCindex = intern (":index");
15015 staticpro (&QCindex);
15016 Qpbm = intern ("pbm");
15017 staticpro (&Qpbm);
15018
15019 #if HAVE_XPM
15020 Qxpm = intern ("xpm");
15021 staticpro (&Qxpm);
15022 #endif
15023
15024 #if HAVE_JPEG
15025 Qjpeg = intern ("jpeg");
15026 staticpro (&Qjpeg);
15027 #endif
15028
15029 #if HAVE_TIFF
15030 Qtiff = intern ("tiff");
15031 staticpro (&Qtiff);
15032 #endif
15033
15034 #if HAVE_GIF
15035 Qgif = intern ("gif");
15036 staticpro (&Qgif);
15037 #endif
15038
15039 #if HAVE_PNG
15040 Qpng = intern ("png");
15041 staticpro (&Qpng);
15042 #endif
15043
15044 defsubr (&Sclear_image_cache);
15045
15046 #if GLYPH_DEBUG
15047 defsubr (&Simagep);
15048 defsubr (&Slookup_image);
15049 #endif
15050 #endif /* TODO */
15051
15052 hourglass_atimer = NULL;
15053 hourglass_shown_p = 0;
15054 defsubr (&Sx_show_tip);
15055 defsubr (&Sx_hide_tip);
15056 tip_timer = Qnil;
15057 staticpro (&tip_timer);
15058 tip_frame = Qnil;
15059 staticpro (&tip_frame);
15060
15061 last_show_tip_args = Qnil;
15062 staticpro (&last_show_tip_args);
15063
15064 defsubr (&Sx_file_dialog);
15065 }
15066
15067
15068 void
15069 init_xfns ()
15070 {
15071 image_types = NULL;
15072 Vimage_types = Qnil;
15073
15074 #if 0 /* TODO : Image support for W32 */
15075 define_image_type (&xbm_type);
15076 define_image_type (&gs_type);
15077 define_image_type (&pbm_type);
15078
15079 #if HAVE_XPM
15080 define_image_type (&xpm_type);
15081 #endif
15082
15083 #if HAVE_JPEG
15084 define_image_type (&jpeg_type);
15085 #endif
15086
15087 #if HAVE_TIFF
15088 define_image_type (&tiff_type);
15089 #endif
15090
15091 #if HAVE_GIF
15092 define_image_type (&gif_type);
15093 #endif
15094
15095 #if HAVE_PNG
15096 define_image_type (&png_type);
15097 #endif
15098 #endif /* TODO */
15099 }
15100
15101 #undef abort
15102
15103 void
15104 w32_abort()
15105 {
15106 int button;
15107 button = MessageBox (NULL,
15108 "A fatal error has occurred!\n\n"
15109 "Select Abort to exit, Retry to debug, Ignore to continue",
15110 "Emacs Abort Dialog",
15111 MB_ICONEXCLAMATION | MB_TASKMODAL
15112 | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
15113 switch (button)
15114 {
15115 case IDRETRY:
15116 DebugBreak ();
15117 break;
15118 case IDIGNORE:
15119 break;
15120 case IDABORT:
15121 default:
15122 abort ();
15123 break;
15124 }
15125 }
15126
15127 /* For convenience when debugging. */
15128 int
15129 w32_last_error()
15130 {
15131 return GetLastError ();
15132 }