(w32_pass_extra_mouse_buttons_to_system): New user option.
[bpt/emacs.git] / 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 Lisp_Object Vw32_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 extern int w32_system_caret_width;
319 extern int w32_system_caret_height;
320 extern int w32_system_caret_x;
321 extern int w32_system_caret_y;
322
323 \f
324 /* Error if we are not connected to MS-Windows. */
325 void
326 check_w32 ()
327 {
328 if (! w32_in_use)
329 error ("MS-Windows not in use or not initialized");
330 }
331
332 /* Nonzero if we can use mouse menus.
333 You should not call this unless HAVE_MENUS is defined. */
334
335 int
336 have_menus_p ()
337 {
338 return w32_in_use;
339 }
340
341 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
342 and checking validity for W32. */
343
344 FRAME_PTR
345 check_x_frame (frame)
346 Lisp_Object frame;
347 {
348 FRAME_PTR f;
349
350 if (NILP (frame))
351 frame = selected_frame;
352 CHECK_LIVE_FRAME (frame);
353 f = XFRAME (frame);
354 if (! FRAME_W32_P (f))
355 error ("non-w32 frame used");
356 return f;
357 }
358
359 /* Let the user specify an display with a frame.
360 nil stands for the selected frame--or, if that is not a w32 frame,
361 the first display on the list. */
362
363 static struct w32_display_info *
364 check_x_display_info (frame)
365 Lisp_Object frame;
366 {
367 if (NILP (frame))
368 {
369 struct frame *sf = XFRAME (selected_frame);
370
371 if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
372 return FRAME_W32_DISPLAY_INFO (sf);
373 else
374 return &one_w32_display_info;
375 }
376 else if (STRINGP (frame))
377 return x_display_info_for_name (frame);
378 else
379 {
380 FRAME_PTR f;
381
382 CHECK_LIVE_FRAME (frame);
383 f = XFRAME (frame);
384 if (! FRAME_W32_P (f))
385 error ("non-w32 frame used");
386 return FRAME_W32_DISPLAY_INFO (f);
387 }
388 }
389 \f
390 /* Return the Emacs frame-object corresponding to an w32 window.
391 It could be the frame's main window or an icon window. */
392
393 /* This function can be called during GC, so use GC_xxx type test macros. */
394
395 struct frame *
396 x_window_to_frame (dpyinfo, wdesc)
397 struct w32_display_info *dpyinfo;
398 HWND wdesc;
399 {
400 Lisp_Object tail, frame;
401 struct frame *f;
402
403 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
404 {
405 frame = XCAR (tail);
406 if (!GC_FRAMEP (frame))
407 continue;
408 f = XFRAME (frame);
409 if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
410 continue;
411 if (f->output_data.w32->hourglass_window == wdesc)
412 return f;
413
414 if (FRAME_W32_WINDOW (f) == wdesc)
415 return f;
416 }
417 return 0;
418 }
419
420 \f
421
422 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
423 id, which is just an int that this section returns. Bitmaps are
424 reference counted so they can be shared among frames.
425
426 Bitmap indices are guaranteed to be > 0, so a negative number can
427 be used to indicate no bitmap.
428
429 If you use x_create_bitmap_from_data, then you must keep track of
430 the bitmaps yourself. That is, creating a bitmap from the same
431 data more than once will not be caught. */
432
433
434 /* Functions to access the contents of a bitmap, given an id. */
435
436 int
437 x_bitmap_height (f, id)
438 FRAME_PTR f;
439 int id;
440 {
441 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
442 }
443
444 int
445 x_bitmap_width (f, id)
446 FRAME_PTR f;
447 int id;
448 {
449 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
450 }
451
452 int
453 x_bitmap_pixmap (f, id)
454 FRAME_PTR f;
455 int id;
456 {
457 return (int) FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
458 }
459
460
461 /* Allocate a new bitmap record. Returns index of new record. */
462
463 static int
464 x_allocate_bitmap_record (f)
465 FRAME_PTR f;
466 {
467 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
468 int i;
469
470 if (dpyinfo->bitmaps == NULL)
471 {
472 dpyinfo->bitmaps_size = 10;
473 dpyinfo->bitmaps
474 = (struct w32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
475 dpyinfo->bitmaps_last = 1;
476 return 1;
477 }
478
479 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
480 return ++dpyinfo->bitmaps_last;
481
482 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
483 if (dpyinfo->bitmaps[i].refcount == 0)
484 return i + 1;
485
486 dpyinfo->bitmaps_size *= 2;
487 dpyinfo->bitmaps
488 = (struct w32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
489 dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
490 return ++dpyinfo->bitmaps_last;
491 }
492
493 /* Add one reference to the reference count of the bitmap with id ID. */
494
495 void
496 x_reference_bitmap (f, id)
497 FRAME_PTR f;
498 int id;
499 {
500 ++FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
501 }
502
503 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
504
505 int
506 x_create_bitmap_from_data (f, bits, width, height)
507 struct frame *f;
508 char *bits;
509 unsigned int width, height;
510 {
511 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
512 Pixmap bitmap;
513 int id;
514
515 bitmap = CreateBitmap (width, height,
516 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes,
517 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
518 bits);
519
520 if (! bitmap)
521 return -1;
522
523 id = x_allocate_bitmap_record (f);
524 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
525 dpyinfo->bitmaps[id - 1].file = NULL;
526 dpyinfo->bitmaps[id - 1].hinst = NULL;
527 dpyinfo->bitmaps[id - 1].refcount = 1;
528 dpyinfo->bitmaps[id - 1].depth = 1;
529 dpyinfo->bitmaps[id - 1].height = height;
530 dpyinfo->bitmaps[id - 1].width = width;
531
532 return id;
533 }
534
535 /* Create bitmap from file FILE for frame F. */
536
537 int
538 x_create_bitmap_from_file (f, file)
539 struct frame *f;
540 Lisp_Object file;
541 {
542 return -1;
543 #if 0 /* TODO : bitmap support */
544 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
545 unsigned int width, height;
546 HBITMAP bitmap;
547 int xhot, yhot, result, id;
548 Lisp_Object found;
549 int fd;
550 char *filename;
551 HINSTANCE hinst;
552
553 /* Look for an existing bitmap with the same name. */
554 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
555 {
556 if (dpyinfo->bitmaps[id].refcount
557 && dpyinfo->bitmaps[id].file
558 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
559 {
560 ++dpyinfo->bitmaps[id].refcount;
561 return id + 1;
562 }
563 }
564
565 /* Search bitmap-file-path for the file, if appropriate. */
566 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, 0);
567 if (fd < 0)
568 return -1;
569 emacs_close (fd);
570
571 filename = (char *) XSTRING (found)->data;
572
573 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
574
575 if (hinst == NULL)
576 return -1;
577
578
579 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
580 filename, &width, &height, &bitmap, &xhot, &yhot);
581 if (result != BitmapSuccess)
582 return -1;
583
584 id = x_allocate_bitmap_record (f);
585 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
586 dpyinfo->bitmaps[id - 1].refcount = 1;
587 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
588 dpyinfo->bitmaps[id - 1].depth = 1;
589 dpyinfo->bitmaps[id - 1].height = height;
590 dpyinfo->bitmaps[id - 1].width = width;
591 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
592
593 return id;
594 #endif /* TODO */
595 }
596
597 /* Remove reference to bitmap with id number ID. */
598
599 void
600 x_destroy_bitmap (f, id)
601 FRAME_PTR f;
602 int id;
603 {
604 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
605
606 if (id > 0)
607 {
608 --dpyinfo->bitmaps[id - 1].refcount;
609 if (dpyinfo->bitmaps[id - 1].refcount == 0)
610 {
611 BLOCK_INPUT;
612 DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
613 if (dpyinfo->bitmaps[id - 1].file)
614 {
615 xfree (dpyinfo->bitmaps[id - 1].file);
616 dpyinfo->bitmaps[id - 1].file = NULL;
617 }
618 UNBLOCK_INPUT;
619 }
620 }
621 }
622
623 /* Free all the bitmaps for the display specified by DPYINFO. */
624
625 static void
626 x_destroy_all_bitmaps (dpyinfo)
627 struct w32_display_info *dpyinfo;
628 {
629 int i;
630 for (i = 0; i < dpyinfo->bitmaps_last; i++)
631 if (dpyinfo->bitmaps[i].refcount > 0)
632 {
633 DeleteObject (dpyinfo->bitmaps[i].pixmap);
634 if (dpyinfo->bitmaps[i].file)
635 xfree (dpyinfo->bitmaps[i].file);
636 }
637 dpyinfo->bitmaps_last = 0;
638 }
639 \f
640 /* Connect the frame-parameter names for W32 frames
641 to the ways of passing the parameter values to the window system.
642
643 The name of a parameter, as a Lisp symbol,
644 has an `x-frame-parameter' property which is an integer in Lisp
645 but can be interpreted as an `enum x_frame_parm' in C. */
646
647 enum x_frame_parm
648 {
649 X_PARM_FOREGROUND_COLOR,
650 X_PARM_BACKGROUND_COLOR,
651 X_PARM_MOUSE_COLOR,
652 X_PARM_CURSOR_COLOR,
653 X_PARM_BORDER_COLOR,
654 X_PARM_ICON_TYPE,
655 X_PARM_FONT,
656 X_PARM_BORDER_WIDTH,
657 X_PARM_INTERNAL_BORDER_WIDTH,
658 X_PARM_NAME,
659 X_PARM_AUTORAISE,
660 X_PARM_AUTOLOWER,
661 X_PARM_VERT_SCROLL_BAR,
662 X_PARM_VISIBILITY,
663 X_PARM_MENU_BAR_LINES
664 };
665
666
667 struct x_frame_parm_table
668 {
669 char *name;
670 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
671 };
672
673 BOOL my_show_window P_ ((struct frame *, HWND, int));
674 void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
675 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
676 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
677 static void x_change_window_heights P_ ((Lisp_Object, int));
678 /* TODO: Native Input Method support; see x_create_im. */
679 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
680 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
681 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
682 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
683 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
684 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
685 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
686 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
687 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
688 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
689 static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
690 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
691 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
692 Lisp_Object));
693 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
694 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
695 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
696 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
697 Lisp_Object));
698 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
699 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
700 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
701 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
702 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
703 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
704 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
705 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
706 Lisp_Object));
707
708 static struct x_frame_parm_table x_frame_parms[] =
709 {
710 {"auto-raise", x_set_autoraise},
711 {"auto-lower", x_set_autolower},
712 {"background-color", x_set_background_color},
713 {"border-color", x_set_border_color},
714 {"border-width", x_set_border_width},
715 {"cursor-color", x_set_cursor_color},
716 {"cursor-type", x_set_cursor_type},
717 {"font", x_set_font},
718 {"foreground-color", x_set_foreground_color},
719 {"icon-name", x_set_icon_name},
720 {"icon-type", x_set_icon_type},
721 {"internal-border-width", x_set_internal_border_width},
722 {"menu-bar-lines", x_set_menu_bar_lines},
723 {"mouse-color", x_set_mouse_color},
724 {"name", x_explicitly_set_name},
725 {"scroll-bar-width", x_set_scroll_bar_width},
726 {"title", x_set_title},
727 {"unsplittable", x_set_unsplittable},
728 {"vertical-scroll-bars", x_set_vertical_scroll_bars},
729 {"visibility", x_set_visibility},
730 {"tool-bar-lines", x_set_tool_bar_lines},
731 {"screen-gamma", x_set_screen_gamma},
732 {"line-spacing", x_set_line_spacing},
733 {"left-fringe", x_set_fringe_width},
734 {"right-fringe", x_set_fringe_width}
735 };
736
737 /* Attach the `x-frame-parameter' properties to
738 the Lisp symbol names of parameters relevant to W32. */
739
740 void
741 init_x_parm_symbols ()
742 {
743 int i;
744
745 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
746 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
747 make_number (i));
748 }
749 \f
750 /* Change the parameters of frame F as specified by ALIST.
751 If a parameter is not specially recognized, do nothing;
752 otherwise call the `x_set_...' function for that parameter. */
753
754 void
755 x_set_frame_parameters (f, alist)
756 FRAME_PTR f;
757 Lisp_Object alist;
758 {
759 Lisp_Object tail;
760
761 /* If both of these parameters are present, it's more efficient to
762 set them both at once. So we wait until we've looked at the
763 entire list before we set them. */
764 int width, height;
765
766 /* Same here. */
767 Lisp_Object left, top;
768
769 /* Same with these. */
770 Lisp_Object icon_left, icon_top;
771
772 /* Record in these vectors all the parms specified. */
773 Lisp_Object *parms;
774 Lisp_Object *values;
775 int i, p;
776 int left_no_change = 0, top_no_change = 0;
777 int icon_left_no_change = 0, icon_top_no_change = 0;
778
779 struct gcpro gcpro1, gcpro2;
780
781 i = 0;
782 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
783 i++;
784
785 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
786 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
787
788 /* Extract parm names and values into those vectors. */
789
790 i = 0;
791 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
792 {
793 Lisp_Object elt;
794
795 elt = Fcar (tail);
796 parms[i] = Fcar (elt);
797 values[i] = Fcdr (elt);
798 i++;
799 }
800 /* TAIL and ALIST are not used again below here. */
801 alist = tail = Qnil;
802
803 GCPRO2 (*parms, *values);
804 gcpro1.nvars = i;
805 gcpro2.nvars = i;
806
807 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
808 because their values appear in VALUES and strings are not valid. */
809 top = left = Qunbound;
810 icon_left = icon_top = Qunbound;
811
812 /* Provide default values for HEIGHT and WIDTH. */
813 if (FRAME_NEW_WIDTH (f))
814 width = FRAME_NEW_WIDTH (f);
815 else
816 width = FRAME_WIDTH (f);
817
818 if (FRAME_NEW_HEIGHT (f))
819 height = FRAME_NEW_HEIGHT (f);
820 else
821 height = FRAME_HEIGHT (f);
822
823 /* Process foreground_color and background_color before anything else.
824 They are independent of other properties, but other properties (e.g.,
825 cursor_color) are dependent upon them. */
826 /* Process default font as well, since fringe widths depends on it. */
827 for (p = 0; p < i; p++)
828 {
829 Lisp_Object prop, val;
830
831 prop = parms[p];
832 val = values[p];
833 if (EQ (prop, Qforeground_color)
834 || EQ (prop, Qbackground_color)
835 || EQ (prop, Qfont))
836 {
837 register Lisp_Object param_index, old_value;
838
839 old_value = get_frame_param (f, prop);
840
841 if (NILP (Fequal (val, old_value)))
842 {
843 store_frame_param (f, prop, val);
844
845 param_index = Fget (prop, Qx_frame_parameter);
846 if (NATNUMP (param_index)
847 && (XFASTINT (param_index)
848 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
849 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
850 }
851 }
852 }
853
854 /* Now process them in reverse of specified order. */
855 for (i--; i >= 0; i--)
856 {
857 Lisp_Object prop, val;
858
859 prop = parms[i];
860 val = values[i];
861
862 if (EQ (prop, Qwidth) && NUMBERP (val))
863 width = XFASTINT (val);
864 else if (EQ (prop, Qheight) && NUMBERP (val))
865 height = XFASTINT (val);
866 else if (EQ (prop, Qtop))
867 top = val;
868 else if (EQ (prop, Qleft))
869 left = val;
870 else if (EQ (prop, Qicon_top))
871 icon_top = val;
872 else if (EQ (prop, Qicon_left))
873 icon_left = val;
874 else if (EQ (prop, Qforeground_color)
875 || EQ (prop, Qbackground_color)
876 || EQ (prop, Qfont))
877 /* Processed above. */
878 continue;
879 else
880 {
881 register Lisp_Object param_index, old_value;
882
883 old_value = get_frame_param (f, prop);
884
885 store_frame_param (f, prop, val);
886
887 param_index = Fget (prop, Qx_frame_parameter);
888 if (NATNUMP (param_index)
889 && (XFASTINT (param_index)
890 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
891 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
892 }
893 }
894
895 /* Don't die if just one of these was set. */
896 if (EQ (left, Qunbound))
897 {
898 left_no_change = 1;
899 if (f->output_data.w32->left_pos < 0)
900 left = Fcons (Qplus, Fcons (make_number (f->output_data.w32->left_pos), Qnil));
901 else
902 XSETINT (left, f->output_data.w32->left_pos);
903 }
904 if (EQ (top, Qunbound))
905 {
906 top_no_change = 1;
907 if (f->output_data.w32->top_pos < 0)
908 top = Fcons (Qplus, Fcons (make_number (f->output_data.w32->top_pos), Qnil));
909 else
910 XSETINT (top, f->output_data.w32->top_pos);
911 }
912
913 /* If one of the icon positions was not set, preserve or default it. */
914 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
915 {
916 icon_left_no_change = 1;
917 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
918 if (NILP (icon_left))
919 XSETINT (icon_left, 0);
920 }
921 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
922 {
923 icon_top_no_change = 1;
924 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
925 if (NILP (icon_top))
926 XSETINT (icon_top, 0);
927 }
928
929 /* Don't set these parameters unless they've been explicitly
930 specified. The window might be mapped or resized while we're in
931 this function, and we don't want to override that unless the lisp
932 code has asked for it.
933
934 Don't set these parameters unless they actually differ from the
935 window's current parameters; the window may not actually exist
936 yet. */
937 {
938 Lisp_Object frame;
939
940 check_frame_size (f, &height, &width);
941
942 XSETFRAME (frame, f);
943
944 if (width != FRAME_WIDTH (f)
945 || height != FRAME_HEIGHT (f)
946 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
947 Fset_frame_size (frame, make_number (width), make_number (height));
948
949 if ((!NILP (left) || !NILP (top))
950 && ! (left_no_change && top_no_change)
951 && ! (NUMBERP (left) && XINT (left) == f->output_data.w32->left_pos
952 && NUMBERP (top) && XINT (top) == f->output_data.w32->top_pos))
953 {
954 int leftpos = 0;
955 int toppos = 0;
956
957 /* Record the signs. */
958 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
959 if (EQ (left, Qminus))
960 f->output_data.w32->size_hint_flags |= XNegative;
961 else if (INTEGERP (left))
962 {
963 leftpos = XINT (left);
964 if (leftpos < 0)
965 f->output_data.w32->size_hint_flags |= XNegative;
966 }
967 else if (CONSP (left) && EQ (XCAR (left), Qminus)
968 && CONSP (XCDR (left))
969 && INTEGERP (XCAR (XCDR (left))))
970 {
971 leftpos = - XINT (XCAR (XCDR (left)));
972 f->output_data.w32->size_hint_flags |= XNegative;
973 }
974 else if (CONSP (left) && EQ (XCAR (left), Qplus)
975 && CONSP (XCDR (left))
976 && INTEGERP (XCAR (XCDR (left))))
977 {
978 leftpos = XINT (XCAR (XCDR (left)));
979 }
980
981 if (EQ (top, Qminus))
982 f->output_data.w32->size_hint_flags |= YNegative;
983 else if (INTEGERP (top))
984 {
985 toppos = XINT (top);
986 if (toppos < 0)
987 f->output_data.w32->size_hint_flags |= YNegative;
988 }
989 else if (CONSP (top) && EQ (XCAR (top), Qminus)
990 && CONSP (XCDR (top))
991 && INTEGERP (XCAR (XCDR (top))))
992 {
993 toppos = - XINT (XCAR (XCDR (top)));
994 f->output_data.w32->size_hint_flags |= YNegative;
995 }
996 else if (CONSP (top) && EQ (XCAR (top), Qplus)
997 && CONSP (XCDR (top))
998 && INTEGERP (XCAR (XCDR (top))))
999 {
1000 toppos = XINT (XCAR (XCDR (top)));
1001 }
1002
1003
1004 /* Store the numeric value of the position. */
1005 f->output_data.w32->top_pos = toppos;
1006 f->output_data.w32->left_pos = leftpos;
1007
1008 f->output_data.w32->win_gravity = NorthWestGravity;
1009
1010 /* Actually set that position, and convert to absolute. */
1011 x_set_offset (f, leftpos, toppos, -1);
1012 }
1013
1014 if ((!NILP (icon_left) || !NILP (icon_top))
1015 && ! (icon_left_no_change && icon_top_no_change))
1016 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1017 }
1018
1019 UNGCPRO;
1020 }
1021
1022 /* Store the screen positions of frame F into XPTR and YPTR.
1023 These are the positions of the containing window manager window,
1024 not Emacs's own window. */
1025
1026 void
1027 x_real_positions (f, xptr, yptr)
1028 FRAME_PTR f;
1029 int *xptr, *yptr;
1030 {
1031 POINT pt;
1032
1033 {
1034 RECT rect;
1035
1036 GetClientRect(FRAME_W32_WINDOW(f), &rect);
1037 AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
1038
1039 pt.x = rect.left;
1040 pt.y = rect.top;
1041 }
1042
1043 ClientToScreen (FRAME_W32_WINDOW(f), &pt);
1044
1045 *xptr = pt.x;
1046 *yptr = pt.y;
1047 }
1048
1049 /* Insert a description of internally-recorded parameters of frame X
1050 into the parameter alist *ALISTPTR that is to be given to the user.
1051 Only parameters that are specific to W32
1052 and whose values are not correctly recorded in the frame's
1053 param_alist need to be considered here. */
1054
1055 void
1056 x_report_frame_params (f, alistptr)
1057 struct frame *f;
1058 Lisp_Object *alistptr;
1059 {
1060 char buf[16];
1061 Lisp_Object tem;
1062
1063 /* Represent negative positions (off the top or left screen edge)
1064 in a way that Fmodify_frame_parameters will understand correctly. */
1065 XSETINT (tem, f->output_data.w32->left_pos);
1066 if (f->output_data.w32->left_pos >= 0)
1067 store_in_alist (alistptr, Qleft, tem);
1068 else
1069 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1070
1071 XSETINT (tem, f->output_data.w32->top_pos);
1072 if (f->output_data.w32->top_pos >= 0)
1073 store_in_alist (alistptr, Qtop, tem);
1074 else
1075 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1076
1077 store_in_alist (alistptr, Qborder_width,
1078 make_number (f->output_data.w32->border_width));
1079 store_in_alist (alistptr, Qinternal_border_width,
1080 make_number (f->output_data.w32->internal_border_width));
1081 store_in_alist (alistptr, Qleft_fringe,
1082 make_number (f->output_data.w32->left_fringe_width));
1083 store_in_alist (alistptr, Qright_fringe,
1084 make_number (f->output_data.w32->right_fringe_width));
1085 store_in_alist (alistptr, Qscroll_bar_width,
1086 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
1087 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f)
1088 : 0));
1089 sprintf (buf, "%ld", (long) FRAME_W32_WINDOW (f));
1090 store_in_alist (alistptr, Qwindow_id,
1091 build_string (buf));
1092 store_in_alist (alistptr, Qicon_name, f->icon_name);
1093 FRAME_SAMPLE_VISIBILITY (f);
1094 store_in_alist (alistptr, Qvisibility,
1095 (FRAME_VISIBLE_P (f) ? Qt
1096 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1097 store_in_alist (alistptr, Qdisplay,
1098 XCAR (FRAME_W32_DISPLAY_INFO (f)->name_list_element));
1099 }
1100 \f
1101
1102 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
1103 Sw32_define_rgb_color, 4, 4, 0,
1104 doc: /* Convert RGB numbers to a windows color reference and associate with NAME.
1105 This adds or updates a named color to w32-color-map, making it
1106 available for use. The original entry's RGB ref is returned, or nil
1107 if the entry is new. */)
1108 (red, green, blue, name)
1109 Lisp_Object red, green, blue, name;
1110 {
1111 Lisp_Object rgb;
1112 Lisp_Object oldrgb = Qnil;
1113 Lisp_Object entry;
1114
1115 CHECK_NUMBER (red);
1116 CHECK_NUMBER (green);
1117 CHECK_NUMBER (blue);
1118 CHECK_STRING (name);
1119
1120 XSET (rgb, Lisp_Int, RGB(XUINT (red), XUINT (green), XUINT (blue)));
1121
1122 BLOCK_INPUT;
1123
1124 /* replace existing entry in w32-color-map or add new entry. */
1125 entry = Fassoc (name, Vw32_color_map);
1126 if (NILP (entry))
1127 {
1128 entry = Fcons (name, rgb);
1129 Vw32_color_map = Fcons (entry, Vw32_color_map);
1130 }
1131 else
1132 {
1133 oldrgb = Fcdr (entry);
1134 Fsetcdr (entry, rgb);
1135 }
1136
1137 UNBLOCK_INPUT;
1138
1139 return (oldrgb);
1140 }
1141
1142 DEFUN ("w32-load-color-file", Fw32_load_color_file,
1143 Sw32_load_color_file, 1, 1, 0,
1144 doc: /* Create an alist of color entries from an external file.
1145 Assign this value to w32-color-map to replace the existing color map.
1146
1147 The file should define one named RGB color per line like so:
1148 R G B name
1149 where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
1150 (filename)
1151 Lisp_Object filename;
1152 {
1153 FILE *fp;
1154 Lisp_Object cmap = Qnil;
1155 Lisp_Object abspath;
1156
1157 CHECK_STRING (filename);
1158 abspath = Fexpand_file_name (filename, Qnil);
1159
1160 fp = fopen (XSTRING (filename)->data, "rt");
1161 if (fp)
1162 {
1163 char buf[512];
1164 int red, green, blue;
1165 int num;
1166
1167 BLOCK_INPUT;
1168
1169 while (fgets (buf, sizeof (buf), fp) != NULL) {
1170 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
1171 {
1172 char *name = buf + num;
1173 num = strlen (name) - 1;
1174 if (name[num] == '\n')
1175 name[num] = 0;
1176 cmap = Fcons (Fcons (build_string (name),
1177 make_number (RGB (red, green, blue))),
1178 cmap);
1179 }
1180 }
1181 fclose (fp);
1182
1183 UNBLOCK_INPUT;
1184 }
1185
1186 return cmap;
1187 }
1188
1189 /* The default colors for the w32 color map */
1190 typedef struct colormap_t
1191 {
1192 char *name;
1193 COLORREF colorref;
1194 } colormap_t;
1195
1196 colormap_t w32_color_map[] =
1197 {
1198 {"snow" , PALETTERGB (255,250,250)},
1199 {"ghost white" , PALETTERGB (248,248,255)},
1200 {"GhostWhite" , PALETTERGB (248,248,255)},
1201 {"white smoke" , PALETTERGB (245,245,245)},
1202 {"WhiteSmoke" , PALETTERGB (245,245,245)},
1203 {"gainsboro" , PALETTERGB (220,220,220)},
1204 {"floral white" , PALETTERGB (255,250,240)},
1205 {"FloralWhite" , PALETTERGB (255,250,240)},
1206 {"old lace" , PALETTERGB (253,245,230)},
1207 {"OldLace" , PALETTERGB (253,245,230)},
1208 {"linen" , PALETTERGB (250,240,230)},
1209 {"antique white" , PALETTERGB (250,235,215)},
1210 {"AntiqueWhite" , PALETTERGB (250,235,215)},
1211 {"papaya whip" , PALETTERGB (255,239,213)},
1212 {"PapayaWhip" , PALETTERGB (255,239,213)},
1213 {"blanched almond" , PALETTERGB (255,235,205)},
1214 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
1215 {"bisque" , PALETTERGB (255,228,196)},
1216 {"peach puff" , PALETTERGB (255,218,185)},
1217 {"PeachPuff" , PALETTERGB (255,218,185)},
1218 {"navajo white" , PALETTERGB (255,222,173)},
1219 {"NavajoWhite" , PALETTERGB (255,222,173)},
1220 {"moccasin" , PALETTERGB (255,228,181)},
1221 {"cornsilk" , PALETTERGB (255,248,220)},
1222 {"ivory" , PALETTERGB (255,255,240)},
1223 {"lemon chiffon" , PALETTERGB (255,250,205)},
1224 {"LemonChiffon" , PALETTERGB (255,250,205)},
1225 {"seashell" , PALETTERGB (255,245,238)},
1226 {"honeydew" , PALETTERGB (240,255,240)},
1227 {"mint cream" , PALETTERGB (245,255,250)},
1228 {"MintCream" , PALETTERGB (245,255,250)},
1229 {"azure" , PALETTERGB (240,255,255)},
1230 {"alice blue" , PALETTERGB (240,248,255)},
1231 {"AliceBlue" , PALETTERGB (240,248,255)},
1232 {"lavender" , PALETTERGB (230,230,250)},
1233 {"lavender blush" , PALETTERGB (255,240,245)},
1234 {"LavenderBlush" , PALETTERGB (255,240,245)},
1235 {"misty rose" , PALETTERGB (255,228,225)},
1236 {"MistyRose" , PALETTERGB (255,228,225)},
1237 {"white" , PALETTERGB (255,255,255)},
1238 {"black" , PALETTERGB ( 0, 0, 0)},
1239 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1240 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1241 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1242 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1243 {"dim gray" , PALETTERGB (105,105,105)},
1244 {"DimGray" , PALETTERGB (105,105,105)},
1245 {"dim grey" , PALETTERGB (105,105,105)},
1246 {"DimGrey" , PALETTERGB (105,105,105)},
1247 {"slate gray" , PALETTERGB (112,128,144)},
1248 {"SlateGray" , PALETTERGB (112,128,144)},
1249 {"slate grey" , PALETTERGB (112,128,144)},
1250 {"SlateGrey" , PALETTERGB (112,128,144)},
1251 {"light slate gray" , PALETTERGB (119,136,153)},
1252 {"LightSlateGray" , PALETTERGB (119,136,153)},
1253 {"light slate grey" , PALETTERGB (119,136,153)},
1254 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1255 {"gray" , PALETTERGB (190,190,190)},
1256 {"grey" , PALETTERGB (190,190,190)},
1257 {"light grey" , PALETTERGB (211,211,211)},
1258 {"LightGrey" , PALETTERGB (211,211,211)},
1259 {"light gray" , PALETTERGB (211,211,211)},
1260 {"LightGray" , PALETTERGB (211,211,211)},
1261 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1262 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1263 {"navy" , PALETTERGB ( 0, 0,128)},
1264 {"navy blue" , PALETTERGB ( 0, 0,128)},
1265 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1266 {"cornflower blue" , PALETTERGB (100,149,237)},
1267 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1268 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1269 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1270 {"slate blue" , PALETTERGB (106, 90,205)},
1271 {"SlateBlue" , PALETTERGB (106, 90,205)},
1272 {"medium slate blue" , PALETTERGB (123,104,238)},
1273 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1274 {"light slate blue" , PALETTERGB (132,112,255)},
1275 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1276 {"medium blue" , PALETTERGB ( 0, 0,205)},
1277 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1278 {"royal blue" , PALETTERGB ( 65,105,225)},
1279 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1280 {"blue" , PALETTERGB ( 0, 0,255)},
1281 {"dodger blue" , PALETTERGB ( 30,144,255)},
1282 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1283 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1284 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1285 {"sky blue" , PALETTERGB (135,206,235)},
1286 {"SkyBlue" , PALETTERGB (135,206,235)},
1287 {"light sky blue" , PALETTERGB (135,206,250)},
1288 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1289 {"steel blue" , PALETTERGB ( 70,130,180)},
1290 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1291 {"light steel blue" , PALETTERGB (176,196,222)},
1292 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1293 {"light blue" , PALETTERGB (173,216,230)},
1294 {"LightBlue" , PALETTERGB (173,216,230)},
1295 {"powder blue" , PALETTERGB (176,224,230)},
1296 {"PowderBlue" , PALETTERGB (176,224,230)},
1297 {"pale turquoise" , PALETTERGB (175,238,238)},
1298 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1299 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1300 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1301 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1302 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1303 {"turquoise" , PALETTERGB ( 64,224,208)},
1304 {"cyan" , PALETTERGB ( 0,255,255)},
1305 {"light cyan" , PALETTERGB (224,255,255)},
1306 {"LightCyan" , PALETTERGB (224,255,255)},
1307 {"cadet blue" , PALETTERGB ( 95,158,160)},
1308 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1309 {"medium aquamarine" , PALETTERGB (102,205,170)},
1310 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1311 {"aquamarine" , PALETTERGB (127,255,212)},
1312 {"dark green" , PALETTERGB ( 0,100, 0)},
1313 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1314 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1315 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1316 {"dark sea green" , PALETTERGB (143,188,143)},
1317 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1318 {"sea green" , PALETTERGB ( 46,139, 87)},
1319 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1320 {"medium sea green" , PALETTERGB ( 60,179,113)},
1321 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1322 {"light sea green" , PALETTERGB ( 32,178,170)},
1323 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1324 {"pale green" , PALETTERGB (152,251,152)},
1325 {"PaleGreen" , PALETTERGB (152,251,152)},
1326 {"spring green" , PALETTERGB ( 0,255,127)},
1327 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1328 {"lawn green" , PALETTERGB (124,252, 0)},
1329 {"LawnGreen" , PALETTERGB (124,252, 0)},
1330 {"green" , PALETTERGB ( 0,255, 0)},
1331 {"chartreuse" , PALETTERGB (127,255, 0)},
1332 {"medium spring green" , PALETTERGB ( 0,250,154)},
1333 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1334 {"green yellow" , PALETTERGB (173,255, 47)},
1335 {"GreenYellow" , PALETTERGB (173,255, 47)},
1336 {"lime green" , PALETTERGB ( 50,205, 50)},
1337 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1338 {"yellow green" , PALETTERGB (154,205, 50)},
1339 {"YellowGreen" , PALETTERGB (154,205, 50)},
1340 {"forest green" , PALETTERGB ( 34,139, 34)},
1341 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1342 {"olive drab" , PALETTERGB (107,142, 35)},
1343 {"OliveDrab" , PALETTERGB (107,142, 35)},
1344 {"dark khaki" , PALETTERGB (189,183,107)},
1345 {"DarkKhaki" , PALETTERGB (189,183,107)},
1346 {"khaki" , PALETTERGB (240,230,140)},
1347 {"pale goldenrod" , PALETTERGB (238,232,170)},
1348 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1349 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1350 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1351 {"light yellow" , PALETTERGB (255,255,224)},
1352 {"LightYellow" , PALETTERGB (255,255,224)},
1353 {"yellow" , PALETTERGB (255,255, 0)},
1354 {"gold" , PALETTERGB (255,215, 0)},
1355 {"light goldenrod" , PALETTERGB (238,221,130)},
1356 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1357 {"goldenrod" , PALETTERGB (218,165, 32)},
1358 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1359 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1360 {"rosy brown" , PALETTERGB (188,143,143)},
1361 {"RosyBrown" , PALETTERGB (188,143,143)},
1362 {"indian red" , PALETTERGB (205, 92, 92)},
1363 {"IndianRed" , PALETTERGB (205, 92, 92)},
1364 {"saddle brown" , PALETTERGB (139, 69, 19)},
1365 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1366 {"sienna" , PALETTERGB (160, 82, 45)},
1367 {"peru" , PALETTERGB (205,133, 63)},
1368 {"burlywood" , PALETTERGB (222,184,135)},
1369 {"beige" , PALETTERGB (245,245,220)},
1370 {"wheat" , PALETTERGB (245,222,179)},
1371 {"sandy brown" , PALETTERGB (244,164, 96)},
1372 {"SandyBrown" , PALETTERGB (244,164, 96)},
1373 {"tan" , PALETTERGB (210,180,140)},
1374 {"chocolate" , PALETTERGB (210,105, 30)},
1375 {"firebrick" , PALETTERGB (178,34, 34)},
1376 {"brown" , PALETTERGB (165,42, 42)},
1377 {"dark salmon" , PALETTERGB (233,150,122)},
1378 {"DarkSalmon" , PALETTERGB (233,150,122)},
1379 {"salmon" , PALETTERGB (250,128,114)},
1380 {"light salmon" , PALETTERGB (255,160,122)},
1381 {"LightSalmon" , PALETTERGB (255,160,122)},
1382 {"orange" , PALETTERGB (255,165, 0)},
1383 {"dark orange" , PALETTERGB (255,140, 0)},
1384 {"DarkOrange" , PALETTERGB (255,140, 0)},
1385 {"coral" , PALETTERGB (255,127, 80)},
1386 {"light coral" , PALETTERGB (240,128,128)},
1387 {"LightCoral" , PALETTERGB (240,128,128)},
1388 {"tomato" , PALETTERGB (255, 99, 71)},
1389 {"orange red" , PALETTERGB (255, 69, 0)},
1390 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1391 {"red" , PALETTERGB (255, 0, 0)},
1392 {"hot pink" , PALETTERGB (255,105,180)},
1393 {"HotPink" , PALETTERGB (255,105,180)},
1394 {"deep pink" , PALETTERGB (255, 20,147)},
1395 {"DeepPink" , PALETTERGB (255, 20,147)},
1396 {"pink" , PALETTERGB (255,192,203)},
1397 {"light pink" , PALETTERGB (255,182,193)},
1398 {"LightPink" , PALETTERGB (255,182,193)},
1399 {"pale violet red" , PALETTERGB (219,112,147)},
1400 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1401 {"maroon" , PALETTERGB (176, 48, 96)},
1402 {"medium violet red" , PALETTERGB (199, 21,133)},
1403 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1404 {"violet red" , PALETTERGB (208, 32,144)},
1405 {"VioletRed" , PALETTERGB (208, 32,144)},
1406 {"magenta" , PALETTERGB (255, 0,255)},
1407 {"violet" , PALETTERGB (238,130,238)},
1408 {"plum" , PALETTERGB (221,160,221)},
1409 {"orchid" , PALETTERGB (218,112,214)},
1410 {"medium orchid" , PALETTERGB (186, 85,211)},
1411 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1412 {"dark orchid" , PALETTERGB (153, 50,204)},
1413 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1414 {"dark violet" , PALETTERGB (148, 0,211)},
1415 {"DarkViolet" , PALETTERGB (148, 0,211)},
1416 {"blue violet" , PALETTERGB (138, 43,226)},
1417 {"BlueViolet" , PALETTERGB (138, 43,226)},
1418 {"purple" , PALETTERGB (160, 32,240)},
1419 {"medium purple" , PALETTERGB (147,112,219)},
1420 {"MediumPurple" , PALETTERGB (147,112,219)},
1421 {"thistle" , PALETTERGB (216,191,216)},
1422 {"gray0" , PALETTERGB ( 0, 0, 0)},
1423 {"grey0" , PALETTERGB ( 0, 0, 0)},
1424 {"dark grey" , PALETTERGB (169,169,169)},
1425 {"DarkGrey" , PALETTERGB (169,169,169)},
1426 {"dark gray" , PALETTERGB (169,169,169)},
1427 {"DarkGray" , PALETTERGB (169,169,169)},
1428 {"dark blue" , PALETTERGB ( 0, 0,139)},
1429 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1430 {"dark cyan" , PALETTERGB ( 0,139,139)},
1431 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1432 {"dark magenta" , PALETTERGB (139, 0,139)},
1433 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1434 {"dark red" , PALETTERGB (139, 0, 0)},
1435 {"DarkRed" , PALETTERGB (139, 0, 0)},
1436 {"light green" , PALETTERGB (144,238,144)},
1437 {"LightGreen" , PALETTERGB (144,238,144)},
1438 };
1439
1440 DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
1441 0, 0, 0, doc: /* Return the default color map. */)
1442 ()
1443 {
1444 int i;
1445 colormap_t *pc = w32_color_map;
1446 Lisp_Object cmap;
1447
1448 BLOCK_INPUT;
1449
1450 cmap = Qnil;
1451
1452 for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
1453 pc++, i++)
1454 cmap = Fcons (Fcons (build_string (pc->name),
1455 make_number (pc->colorref)),
1456 cmap);
1457
1458 UNBLOCK_INPUT;
1459
1460 return (cmap);
1461 }
1462
1463 Lisp_Object
1464 w32_to_x_color (rgb)
1465 Lisp_Object rgb;
1466 {
1467 Lisp_Object color;
1468
1469 CHECK_NUMBER (rgb);
1470
1471 BLOCK_INPUT;
1472
1473 color = Frassq (rgb, Vw32_color_map);
1474
1475 UNBLOCK_INPUT;
1476
1477 if (!NILP (color))
1478 return (Fcar (color));
1479 else
1480 return Qnil;
1481 }
1482
1483 COLORREF
1484 w32_color_map_lookup (colorname)
1485 char *colorname;
1486 {
1487 Lisp_Object tail, ret = Qnil;
1488
1489 BLOCK_INPUT;
1490
1491 for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail))
1492 {
1493 register Lisp_Object elt, tem;
1494
1495 elt = Fcar (tail);
1496 if (!CONSP (elt)) continue;
1497
1498 tem = Fcar (elt);
1499
1500 if (lstrcmpi (XSTRING (tem)->data, colorname) == 0)
1501 {
1502 ret = XUINT (Fcdr (elt));
1503 break;
1504 }
1505
1506 QUIT;
1507 }
1508
1509
1510 UNBLOCK_INPUT;
1511
1512 return ret;
1513 }
1514
1515 COLORREF
1516 x_to_w32_color (colorname)
1517 char * colorname;
1518 {
1519 register Lisp_Object ret = Qnil;
1520
1521 BLOCK_INPUT;
1522
1523 if (colorname[0] == '#')
1524 {
1525 /* Could be an old-style RGB Device specification. */
1526 char *color;
1527 int size;
1528 color = colorname + 1;
1529
1530 size = strlen(color);
1531 if (size == 3 || size == 6 || size == 9 || size == 12)
1532 {
1533 UINT colorval;
1534 int i, pos;
1535 pos = 0;
1536 size /= 3;
1537 colorval = 0;
1538
1539 for (i = 0; i < 3; i++)
1540 {
1541 char *end;
1542 char t;
1543 unsigned long value;
1544
1545 /* The check for 'x' in the following conditional takes into
1546 account the fact that strtol allows a "0x" in front of
1547 our numbers, and we don't. */
1548 if (!isxdigit(color[0]) || color[1] == 'x')
1549 break;
1550 t = color[size];
1551 color[size] = '\0';
1552 value = strtoul(color, &end, 16);
1553 color[size] = t;
1554 if (errno == ERANGE || end - color != size)
1555 break;
1556 switch (size)
1557 {
1558 case 1:
1559 value = value * 0x10;
1560 break;
1561 case 2:
1562 break;
1563 case 3:
1564 value /= 0x10;
1565 break;
1566 case 4:
1567 value /= 0x100;
1568 break;
1569 }
1570 colorval |= (value << pos);
1571 pos += 0x8;
1572 if (i == 2)
1573 {
1574 UNBLOCK_INPUT;
1575 return (colorval);
1576 }
1577 color = end;
1578 }
1579 }
1580 }
1581 else if (strnicmp(colorname, "rgb:", 4) == 0)
1582 {
1583 char *color;
1584 UINT colorval;
1585 int i, pos;
1586 pos = 0;
1587
1588 colorval = 0;
1589 color = colorname + 4;
1590 for (i = 0; i < 3; i++)
1591 {
1592 char *end;
1593 unsigned long value;
1594
1595 /* The check for 'x' in the following conditional takes into
1596 account the fact that strtol allows a "0x" in front of
1597 our numbers, and we don't. */
1598 if (!isxdigit(color[0]) || color[1] == 'x')
1599 break;
1600 value = strtoul(color, &end, 16);
1601 if (errno == ERANGE)
1602 break;
1603 switch (end - color)
1604 {
1605 case 1:
1606 value = value * 0x10 + value;
1607 break;
1608 case 2:
1609 break;
1610 case 3:
1611 value /= 0x10;
1612 break;
1613 case 4:
1614 value /= 0x100;
1615 break;
1616 default:
1617 value = ULONG_MAX;
1618 }
1619 if (value == ULONG_MAX)
1620 break;
1621 colorval |= (value << pos);
1622 pos += 0x8;
1623 if (i == 2)
1624 {
1625 if (*end != '\0')
1626 break;
1627 UNBLOCK_INPUT;
1628 return (colorval);
1629 }
1630 if (*end != '/')
1631 break;
1632 color = end + 1;
1633 }
1634 }
1635 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1636 {
1637 /* This is an RGB Intensity specification. */
1638 char *color;
1639 UINT colorval;
1640 int i, pos;
1641 pos = 0;
1642
1643 colorval = 0;
1644 color = colorname + 5;
1645 for (i = 0; i < 3; i++)
1646 {
1647 char *end;
1648 double value;
1649 UINT val;
1650
1651 value = strtod(color, &end);
1652 if (errno == ERANGE)
1653 break;
1654 if (value < 0.0 || value > 1.0)
1655 break;
1656 val = (UINT)(0x100 * value);
1657 /* We used 0x100 instead of 0xFF to give an continuous
1658 range between 0.0 and 1.0 inclusive. The next statement
1659 fixes the 1.0 case. */
1660 if (val == 0x100)
1661 val = 0xFF;
1662 colorval |= (val << pos);
1663 pos += 0x8;
1664 if (i == 2)
1665 {
1666 if (*end != '\0')
1667 break;
1668 UNBLOCK_INPUT;
1669 return (colorval);
1670 }
1671 if (*end != '/')
1672 break;
1673 color = end + 1;
1674 }
1675 }
1676 /* I am not going to attempt to handle any of the CIE color schemes
1677 or TekHVC, since I don't know the algorithms for conversion to
1678 RGB. */
1679
1680 /* If we fail to lookup the color name in w32_color_map, then check the
1681 colorname to see if it can be crudely approximated: If the X color
1682 ends in a number (e.g., "darkseagreen2"), strip the number and
1683 return the result of looking up the base color name. */
1684 ret = w32_color_map_lookup (colorname);
1685 if (NILP (ret))
1686 {
1687 int len = strlen (colorname);
1688
1689 if (isdigit (colorname[len - 1]))
1690 {
1691 char *ptr, *approx = alloca (len + 1);
1692
1693 strcpy (approx, colorname);
1694 ptr = &approx[len - 1];
1695 while (ptr > approx && isdigit (*ptr))
1696 *ptr-- = '\0';
1697
1698 ret = w32_color_map_lookup (approx);
1699 }
1700 }
1701
1702 UNBLOCK_INPUT;
1703 return ret;
1704 }
1705
1706
1707 void
1708 w32_regenerate_palette (FRAME_PTR f)
1709 {
1710 struct w32_palette_entry * list;
1711 LOGPALETTE * log_palette;
1712 HPALETTE new_palette;
1713 int i;
1714
1715 /* don't bother trying to create palette if not supported */
1716 if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
1717 return;
1718
1719 log_palette = (LOGPALETTE *)
1720 alloca (sizeof (LOGPALETTE) +
1721 FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
1722 log_palette->palVersion = 0x300;
1723 log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
1724
1725 list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1726 for (i = 0;
1727 i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
1728 i++, list = list->next)
1729 log_palette->palPalEntry[i] = list->entry;
1730
1731 new_palette = CreatePalette (log_palette);
1732
1733 enter_crit ();
1734
1735 if (FRAME_W32_DISPLAY_INFO (f)->palette)
1736 DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
1737 FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
1738
1739 /* Realize display palette and garbage all frames. */
1740 release_frame_dc (f, get_frame_dc (f));
1741
1742 leave_crit ();
1743 }
1744
1745 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1746 #define SET_W32_COLOR(pe, color) \
1747 do \
1748 { \
1749 pe.peRed = GetRValue (color); \
1750 pe.peGreen = GetGValue (color); \
1751 pe.peBlue = GetBValue (color); \
1752 pe.peFlags = 0; \
1753 } while (0)
1754
1755 #if 0
1756 /* Keep these around in case we ever want to track color usage. */
1757 void
1758 w32_map_color (FRAME_PTR f, COLORREF color)
1759 {
1760 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1761
1762 if (NILP (Vw32_enable_palette))
1763 return;
1764
1765 /* check if color is already mapped */
1766 while (list)
1767 {
1768 if (W32_COLOR (list->entry) == color)
1769 {
1770 ++list->refcount;
1771 return;
1772 }
1773 list = list->next;
1774 }
1775
1776 /* not already mapped, so add to list and recreate Windows palette */
1777 list = (struct w32_palette_entry *)
1778 xmalloc (sizeof (struct w32_palette_entry));
1779 SET_W32_COLOR (list->entry, color);
1780 list->refcount = 1;
1781 list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
1782 FRAME_W32_DISPLAY_INFO (f)->color_list = list;
1783 FRAME_W32_DISPLAY_INFO (f)->num_colors++;
1784
1785 /* set flag that palette must be regenerated */
1786 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1787 }
1788
1789 void
1790 w32_unmap_color (FRAME_PTR f, COLORREF color)
1791 {
1792 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1793 struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
1794
1795 if (NILP (Vw32_enable_palette))
1796 return;
1797
1798 /* check if color is already mapped */
1799 while (list)
1800 {
1801 if (W32_COLOR (list->entry) == color)
1802 {
1803 if (--list->refcount == 0)
1804 {
1805 *prev = list->next;
1806 xfree (list);
1807 FRAME_W32_DISPLAY_INFO (f)->num_colors--;
1808 break;
1809 }
1810 else
1811 return;
1812 }
1813 prev = &list->next;
1814 list = list->next;
1815 }
1816
1817 /* set flag that palette must be regenerated */
1818 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1819 }
1820 #endif
1821
1822
1823 /* Gamma-correct COLOR on frame F. */
1824
1825 void
1826 gamma_correct (f, color)
1827 struct frame *f;
1828 COLORREF *color;
1829 {
1830 if (f->gamma)
1831 {
1832 *color = PALETTERGB (
1833 pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1834 pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1835 pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5);
1836 }
1837 }
1838
1839
1840 /* Decide if color named COLOR is valid for the display associated with
1841 the selected frame; if so, return the rgb values in COLOR_DEF.
1842 If ALLOC is nonzero, allocate a new colormap cell. */
1843
1844 int
1845 w32_defined_color (f, color, color_def, alloc)
1846 FRAME_PTR f;
1847 char *color;
1848 XColor *color_def;
1849 int alloc;
1850 {
1851 register Lisp_Object tem;
1852 COLORREF w32_color_ref;
1853
1854 tem = x_to_w32_color (color);
1855
1856 if (!NILP (tem))
1857 {
1858 if (f)
1859 {
1860 /* Apply gamma correction. */
1861 w32_color_ref = XUINT (tem);
1862 gamma_correct (f, &w32_color_ref);
1863 XSETINT (tem, w32_color_ref);
1864 }
1865
1866 /* Map this color to the palette if it is enabled. */
1867 if (!NILP (Vw32_enable_palette))
1868 {
1869 struct w32_palette_entry * entry =
1870 one_w32_display_info.color_list;
1871 struct w32_palette_entry ** prev =
1872 &one_w32_display_info.color_list;
1873
1874 /* check if color is already mapped */
1875 while (entry)
1876 {
1877 if (W32_COLOR (entry->entry) == XUINT (tem))
1878 break;
1879 prev = &entry->next;
1880 entry = entry->next;
1881 }
1882
1883 if (entry == NULL && alloc)
1884 {
1885 /* not already mapped, so add to list */
1886 entry = (struct w32_palette_entry *)
1887 xmalloc (sizeof (struct w32_palette_entry));
1888 SET_W32_COLOR (entry->entry, XUINT (tem));
1889 entry->next = NULL;
1890 *prev = entry;
1891 one_w32_display_info.num_colors++;
1892
1893 /* set flag that palette must be regenerated */
1894 one_w32_display_info.regen_palette = TRUE;
1895 }
1896 }
1897 /* Ensure COLORREF value is snapped to nearest color in (default)
1898 palette by simulating the PALETTERGB macro. This works whether
1899 or not the display device has a palette. */
1900 w32_color_ref = XUINT (tem) | 0x2000000;
1901
1902 color_def->pixel = w32_color_ref;
1903 color_def->red = GetRValue (w32_color_ref);
1904 color_def->green = GetGValue (w32_color_ref);
1905 color_def->blue = GetBValue (w32_color_ref);
1906
1907 return 1;
1908 }
1909 else
1910 {
1911 return 0;
1912 }
1913 }
1914
1915 /* Given a string ARG naming a color, compute a pixel value from it
1916 suitable for screen F.
1917 If F is not a color screen, return DEF (default) regardless of what
1918 ARG says. */
1919
1920 int
1921 x_decode_color (f, arg, def)
1922 FRAME_PTR f;
1923 Lisp_Object arg;
1924 int def;
1925 {
1926 XColor cdef;
1927
1928 CHECK_STRING (arg);
1929
1930 if (strcmp (XSTRING (arg)->data, "black") == 0)
1931 return BLACK_PIX_DEFAULT (f);
1932 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1933 return WHITE_PIX_DEFAULT (f);
1934
1935 if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
1936 return def;
1937
1938 /* w32_defined_color is responsible for coping with failures
1939 by looking for a near-miss. */
1940 if (w32_defined_color (f, XSTRING (arg)->data, &cdef, 1))
1941 return cdef.pixel;
1942
1943 /* defined_color failed; return an ultimate default. */
1944 return def;
1945 }
1946 \f
1947 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1948 the previous value of that parameter, NEW_VALUE is the new value. */
1949
1950 static void
1951 x_set_line_spacing (f, new_value, old_value)
1952 struct frame *f;
1953 Lisp_Object new_value, old_value;
1954 {
1955 if (NILP (new_value))
1956 f->extra_line_spacing = 0;
1957 else if (NATNUMP (new_value))
1958 f->extra_line_spacing = XFASTINT (new_value);
1959 else
1960 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1961 Fcons (new_value, Qnil)));
1962 if (FRAME_VISIBLE_P (f))
1963 redraw_frame (f);
1964 }
1965
1966
1967 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1968 the previous value of that parameter, NEW_VALUE is the new value. */
1969
1970 static void
1971 x_set_screen_gamma (f, new_value, old_value)
1972 struct frame *f;
1973 Lisp_Object new_value, old_value;
1974 {
1975 if (NILP (new_value))
1976 f->gamma = 0;
1977 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1978 /* The value 0.4545 is the normal viewing gamma. */
1979 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1980 else
1981 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1982 Fcons (new_value, Qnil)));
1983
1984 clear_face_cache (0);
1985 }
1986
1987
1988 /* Functions called only from `x_set_frame_param'
1989 to set individual parameters.
1990
1991 If FRAME_W32_WINDOW (f) is 0,
1992 the frame is being created and its window does not exist yet.
1993 In that case, just record the parameter's new value
1994 in the standard place; do not attempt to change the window. */
1995
1996 void
1997 x_set_foreground_color (f, arg, oldval)
1998 struct frame *f;
1999 Lisp_Object arg, oldval;
2000 {
2001 struct w32_output *x = f->output_data.w32;
2002 PIX_TYPE fg, old_fg;
2003
2004 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2005 old_fg = FRAME_FOREGROUND_PIXEL (f);
2006 FRAME_FOREGROUND_PIXEL (f) = fg;
2007
2008 if (FRAME_W32_WINDOW (f) != 0)
2009 {
2010 if (x->cursor_pixel == old_fg)
2011 x->cursor_pixel = fg;
2012
2013 update_face_from_frame_parameter (f, Qforeground_color, arg);
2014 if (FRAME_VISIBLE_P (f))
2015 redraw_frame (f);
2016 }
2017 }
2018
2019 void
2020 x_set_background_color (f, arg, oldval)
2021 struct frame *f;
2022 Lisp_Object arg, oldval;
2023 {
2024 FRAME_BACKGROUND_PIXEL (f)
2025 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
2026
2027 if (FRAME_W32_WINDOW (f) != 0)
2028 {
2029 SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX,
2030 FRAME_BACKGROUND_PIXEL (f));
2031
2032 update_face_from_frame_parameter (f, Qbackground_color, arg);
2033
2034 if (FRAME_VISIBLE_P (f))
2035 redraw_frame (f);
2036 }
2037 }
2038
2039 void
2040 x_set_mouse_color (f, arg, oldval)
2041 struct frame *f;
2042 Lisp_Object arg, oldval;
2043 {
2044 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
2045 int count;
2046 int mask_color;
2047
2048 if (!EQ (Qnil, arg))
2049 f->output_data.w32->mouse_pixel
2050 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2051 mask_color = FRAME_BACKGROUND_PIXEL (f);
2052
2053 /* Don't let pointers be invisible. */
2054 if (mask_color == f->output_data.w32->mouse_pixel
2055 && mask_color == FRAME_BACKGROUND_PIXEL (f))
2056 f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
2057
2058 #if 0 /* TODO : cursor changes */
2059 BLOCK_INPUT;
2060
2061 /* It's not okay to crash if the user selects a screwy cursor. */
2062 count = x_catch_errors (FRAME_W32_DISPLAY (f));
2063
2064 if (!EQ (Qnil, Vx_pointer_shape))
2065 {
2066 CHECK_NUMBER (Vx_pointer_shape);
2067 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
2068 }
2069 else
2070 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2071 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
2072
2073 if (!EQ (Qnil, Vx_nontext_pointer_shape))
2074 {
2075 CHECK_NUMBER (Vx_nontext_pointer_shape);
2076 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2077 XINT (Vx_nontext_pointer_shape));
2078 }
2079 else
2080 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
2081 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2082
2083 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
2084 {
2085 CHECK_NUMBER (Vx_hourglass_pointer_shape);
2086 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2087 XINT (Vx_hourglass_pointer_shape));
2088 }
2089 else
2090 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
2091 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
2092
2093 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2094 if (!EQ (Qnil, Vx_mode_pointer_shape))
2095 {
2096 CHECK_NUMBER (Vx_mode_pointer_shape);
2097 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2098 XINT (Vx_mode_pointer_shape));
2099 }
2100 else
2101 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2102 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
2103
2104 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
2105 {
2106 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
2107 cross_cursor
2108 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2109 XINT (Vx_sensitive_text_pointer_shape));
2110 }
2111 else
2112 cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
2113
2114 if (!NILP (Vx_window_horizontal_drag_shape))
2115 {
2116 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
2117 horizontal_drag_cursor
2118 = XCreateFontCursor (FRAME_X_DISPLAY (f),
2119 XINT (Vx_window_horizontal_drag_shape));
2120 }
2121 else
2122 horizontal_drag_cursor
2123 = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
2124
2125 /* Check and report errors with the above calls. */
2126 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
2127 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
2128
2129 {
2130 XColor fore_color, back_color;
2131
2132 fore_color.pixel = f->output_data.w32->mouse_pixel;
2133 back_color.pixel = mask_color;
2134 XQueryColor (FRAME_W32_DISPLAY (f),
2135 DefaultColormap (FRAME_W32_DISPLAY (f),
2136 DefaultScreen (FRAME_W32_DISPLAY (f))),
2137 &fore_color);
2138 XQueryColor (FRAME_W32_DISPLAY (f),
2139 DefaultColormap (FRAME_W32_DISPLAY (f),
2140 DefaultScreen (FRAME_W32_DISPLAY (f))),
2141 &back_color);
2142 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
2143 &fore_color, &back_color);
2144 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
2145 &fore_color, &back_color);
2146 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
2147 &fore_color, &back_color);
2148 XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
2149 &fore_color, &back_color);
2150 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
2151 &fore_color, &back_color);
2152 }
2153
2154 if (FRAME_W32_WINDOW (f) != 0)
2155 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
2156
2157 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
2158 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
2159 f->output_data.w32->text_cursor = cursor;
2160
2161 if (nontext_cursor != f->output_data.w32->nontext_cursor
2162 && f->output_data.w32->nontext_cursor != 0)
2163 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
2164 f->output_data.w32->nontext_cursor = nontext_cursor;
2165
2166 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
2167 && f->output_data.w32->hourglass_cursor != 0)
2168 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
2169 f->output_data.w32->hourglass_cursor = hourglass_cursor;
2170
2171 if (mode_cursor != f->output_data.w32->modeline_cursor
2172 && f->output_data.w32->modeline_cursor != 0)
2173 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
2174 f->output_data.w32->modeline_cursor = mode_cursor;
2175
2176 if (cross_cursor != f->output_data.w32->cross_cursor
2177 && f->output_data.w32->cross_cursor != 0)
2178 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
2179 f->output_data.w32->cross_cursor = cross_cursor;
2180
2181 XFlush (FRAME_W32_DISPLAY (f));
2182 UNBLOCK_INPUT;
2183
2184 update_face_from_frame_parameter (f, Qmouse_color, arg);
2185 #endif /* TODO */
2186 }
2187
2188 /* Defined in w32term.c. */
2189 void x_update_cursor (struct frame *f, int on_p);
2190
2191 void
2192 x_set_cursor_color (f, arg, oldval)
2193 struct frame *f;
2194 Lisp_Object arg, oldval;
2195 {
2196 unsigned long fore_pixel, pixel;
2197
2198 if (!NILP (Vx_cursor_fore_pixel))
2199 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
2200 WHITE_PIX_DEFAULT (f));
2201 else
2202 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2203
2204 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2205
2206 /* Make sure that the cursor color differs from the background color. */
2207 if (pixel == FRAME_BACKGROUND_PIXEL (f))
2208 {
2209 pixel = f->output_data.w32->mouse_pixel;
2210 if (pixel == fore_pixel)
2211 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2212 }
2213
2214 FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
2215 f->output_data.w32->cursor_pixel = pixel;
2216
2217 if (FRAME_W32_WINDOW (f) != 0)
2218 {
2219 if (FRAME_VISIBLE_P (f))
2220 {
2221 x_update_cursor (f, 0);
2222 x_update_cursor (f, 1);
2223 }
2224 }
2225
2226 update_face_from_frame_parameter (f, Qcursor_color, arg);
2227 }
2228
2229 /* Set the border-color of frame F to pixel value PIX.
2230 Note that this does not fully take effect if done before
2231 F has an window. */
2232 void
2233 x_set_border_pixel (f, pix)
2234 struct frame *f;
2235 int pix;
2236 {
2237 f->output_data.w32->border_pixel = pix;
2238
2239 if (FRAME_W32_WINDOW (f) != 0 && f->output_data.w32->border_width > 0)
2240 {
2241 if (FRAME_VISIBLE_P (f))
2242 redraw_frame (f);
2243 }
2244 }
2245
2246 /* Set the border-color of frame F to value described by ARG.
2247 ARG can be a string naming a color.
2248 The border-color is used for the border that is drawn by the server.
2249 Note that this does not fully take effect if done before
2250 F has a window; it must be redone when the window is created. */
2251
2252 void
2253 x_set_border_color (f, arg, oldval)
2254 struct frame *f;
2255 Lisp_Object arg, oldval;
2256 {
2257 int pix;
2258
2259 CHECK_STRING (arg);
2260 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2261 x_set_border_pixel (f, pix);
2262 update_face_from_frame_parameter (f, Qborder_color, arg);
2263 }
2264
2265 /* Value is the internal representation of the specified cursor type
2266 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
2267 of the bar cursor. */
2268
2269 enum text_cursor_kinds
2270 x_specified_cursor_type (arg, width)
2271 Lisp_Object arg;
2272 int *width;
2273 {
2274 enum text_cursor_kinds type;
2275
2276 if (EQ (arg, Qbar))
2277 {
2278 type = BAR_CURSOR;
2279 *width = 2;
2280 }
2281 else if (CONSP (arg)
2282 && EQ (XCAR (arg), Qbar)
2283 && INTEGERP (XCDR (arg))
2284 && XINT (XCDR (arg)) >= 0)
2285 {
2286 type = BAR_CURSOR;
2287 *width = XINT (XCDR (arg));
2288 }
2289 else if (NILP (arg))
2290 type = NO_CURSOR;
2291 else
2292 /* Treat anything unknown as "box cursor".
2293 It was bad to signal an error; people have trouble fixing
2294 .Xdefaults with Emacs, when it has something bad in it. */
2295 type = FILLED_BOX_CURSOR;
2296
2297 return type;
2298 }
2299
2300 void
2301 x_set_cursor_type (f, arg, oldval)
2302 FRAME_PTR f;
2303 Lisp_Object arg, oldval;
2304 {
2305 int width;
2306
2307 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
2308 f->output_data.w32->cursor_width = width;
2309
2310 /* Make sure the cursor gets redrawn. This is overkill, but how
2311 often do people change cursor types? */
2312 update_mode_lines++;
2313 }
2314 \f
2315 void
2316 x_set_icon_type (f, arg, oldval)
2317 struct frame *f;
2318 Lisp_Object arg, oldval;
2319 {
2320 int result;
2321
2322 if (NILP (arg) && NILP (oldval))
2323 return;
2324
2325 if (STRINGP (arg) && STRINGP (oldval)
2326 && EQ (Fstring_equal (oldval, arg), Qt))
2327 return;
2328
2329 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
2330 return;
2331
2332 BLOCK_INPUT;
2333
2334 result = x_bitmap_icon (f, arg);
2335 if (result)
2336 {
2337 UNBLOCK_INPUT;
2338 error ("No icon window available");
2339 }
2340
2341 UNBLOCK_INPUT;
2342 }
2343
2344 /* Return non-nil if frame F wants a bitmap icon. */
2345
2346 Lisp_Object
2347 x_icon_type (f)
2348 FRAME_PTR f;
2349 {
2350 Lisp_Object tem;
2351
2352 tem = assq_no_quit (Qicon_type, f->param_alist);
2353 if (CONSP (tem))
2354 return XCDR (tem);
2355 else
2356 return Qnil;
2357 }
2358
2359 void
2360 x_set_icon_name (f, arg, oldval)
2361 struct frame *f;
2362 Lisp_Object arg, oldval;
2363 {
2364 if (STRINGP (arg))
2365 {
2366 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
2367 return;
2368 }
2369 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
2370 return;
2371
2372 f->icon_name = arg;
2373
2374 #if 0
2375 if (f->output_data.w32->icon_bitmap != 0)
2376 return;
2377
2378 BLOCK_INPUT;
2379
2380 result = x_text_icon (f,
2381 (char *) XSTRING ((!NILP (f->icon_name)
2382 ? f->icon_name
2383 : !NILP (f->title)
2384 ? f->title
2385 : f->name))->data);
2386
2387 if (result)
2388 {
2389 UNBLOCK_INPUT;
2390 error ("No icon window available");
2391 }
2392
2393 /* If the window was unmapped (and its icon was mapped),
2394 the new icon is not mapped, so map the window in its stead. */
2395 if (FRAME_VISIBLE_P (f))
2396 {
2397 #ifdef USE_X_TOOLKIT
2398 XtPopup (f->output_data.w32->widget, XtGrabNone);
2399 #endif
2400 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
2401 }
2402
2403 XFlush (FRAME_W32_DISPLAY (f));
2404 UNBLOCK_INPUT;
2405 #endif
2406 }
2407
2408 extern Lisp_Object x_new_font ();
2409 extern Lisp_Object x_new_fontset();
2410
2411 void
2412 x_set_font (f, arg, oldval)
2413 struct frame *f;
2414 Lisp_Object arg, oldval;
2415 {
2416 Lisp_Object result;
2417 Lisp_Object fontset_name;
2418 Lisp_Object frame;
2419 int old_fontset = FRAME_FONTSET(f);
2420
2421 CHECK_STRING (arg);
2422
2423 fontset_name = Fquery_fontset (arg, Qnil);
2424
2425 BLOCK_INPUT;
2426 result = (STRINGP (fontset_name)
2427 ? x_new_fontset (f, XSTRING (fontset_name)->data)
2428 : x_new_font (f, XSTRING (arg)->data));
2429 UNBLOCK_INPUT;
2430
2431 if (EQ (result, Qnil))
2432 error ("Font `%s' is not defined", XSTRING (arg)->data);
2433 else if (EQ (result, Qt))
2434 error ("The characters of the given font have varying widths");
2435 else if (STRINGP (result))
2436 {
2437 if (STRINGP (fontset_name))
2438 {
2439 /* Fontset names are built from ASCII font names, so the
2440 names may be equal despite there was a change. */
2441 if (old_fontset == FRAME_FONTSET (f))
2442 return;
2443 }
2444 else if (!NILP (Fequal (result, oldval)))
2445 return;
2446
2447 store_frame_param (f, Qfont, result);
2448 recompute_basic_faces (f);
2449 }
2450 else
2451 abort ();
2452
2453 do_pending_window_change (0);
2454
2455 /* Don't call `face-set-after-frame-default' when faces haven't been
2456 initialized yet. This is the case when called from
2457 Fx_create_frame. In that case, the X widget or window doesn't
2458 exist either, and we can end up in x_report_frame_params with a
2459 null widget which gives a segfault. */
2460 if (FRAME_FACE_CACHE (f))
2461 {
2462 XSETFRAME (frame, f);
2463 call1 (Qface_set_after_frame_default, frame);
2464 }
2465 }
2466
2467 static void
2468 x_set_fringe_width (f, new_value, old_value)
2469 struct frame *f;
2470 Lisp_Object new_value, old_value;
2471 {
2472 x_compute_fringe_widths (f, 1);
2473 }
2474
2475 void
2476 x_set_border_width (f, arg, oldval)
2477 struct frame *f;
2478 Lisp_Object arg, oldval;
2479 {
2480 CHECK_NUMBER (arg);
2481
2482 if (XINT (arg) == f->output_data.w32->border_width)
2483 return;
2484
2485 if (FRAME_W32_WINDOW (f) != 0)
2486 error ("Cannot change the border width of a window");
2487
2488 f->output_data.w32->border_width = XINT (arg);
2489 }
2490
2491 void
2492 x_set_internal_border_width (f, arg, oldval)
2493 struct frame *f;
2494 Lisp_Object arg, oldval;
2495 {
2496 int old = f->output_data.w32->internal_border_width;
2497
2498 CHECK_NUMBER (arg);
2499 f->output_data.w32->internal_border_width = XINT (arg);
2500 if (f->output_data.w32->internal_border_width < 0)
2501 f->output_data.w32->internal_border_width = 0;
2502
2503 if (f->output_data.w32->internal_border_width == old)
2504 return;
2505
2506 if (FRAME_W32_WINDOW (f) != 0)
2507 {
2508 x_set_window_size (f, 0, f->width, f->height);
2509 SET_FRAME_GARBAGED (f);
2510 do_pending_window_change (0);
2511 }
2512 else
2513 SET_FRAME_GARBAGED (f);
2514 }
2515
2516 void
2517 x_set_visibility (f, value, oldval)
2518 struct frame *f;
2519 Lisp_Object value, oldval;
2520 {
2521 Lisp_Object frame;
2522 XSETFRAME (frame, f);
2523
2524 if (NILP (value))
2525 Fmake_frame_invisible (frame, Qt);
2526 else if (EQ (value, Qicon))
2527 Ficonify_frame (frame);
2528 else
2529 Fmake_frame_visible (frame);
2530 }
2531
2532 \f
2533 /* Change window heights in windows rooted in WINDOW by N lines. */
2534
2535 static void
2536 x_change_window_heights (window, n)
2537 Lisp_Object window;
2538 int n;
2539 {
2540 struct window *w = XWINDOW (window);
2541
2542 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2543 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2544
2545 if (INTEGERP (w->orig_top))
2546 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2547 if (INTEGERP (w->orig_height))
2548 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2549
2550 /* Handle just the top child in a vertical split. */
2551 if (!NILP (w->vchild))
2552 x_change_window_heights (w->vchild, n);
2553
2554 /* Adjust all children in a horizontal split. */
2555 for (window = w->hchild; !NILP (window); window = w->next)
2556 {
2557 w = XWINDOW (window);
2558 x_change_window_heights (window, n);
2559 }
2560 }
2561
2562 void
2563 x_set_menu_bar_lines (f, value, oldval)
2564 struct frame *f;
2565 Lisp_Object value, oldval;
2566 {
2567 int nlines;
2568 int olines = FRAME_MENU_BAR_LINES (f);
2569
2570 /* Right now, menu bars don't work properly in minibuf-only frames;
2571 most of the commands try to apply themselves to the minibuffer
2572 frame itself, and get an error because you can't switch buffers
2573 in or split the minibuffer window. */
2574 if (FRAME_MINIBUF_ONLY_P (f))
2575 return;
2576
2577 if (INTEGERP (value))
2578 nlines = XINT (value);
2579 else
2580 nlines = 0;
2581
2582 FRAME_MENU_BAR_LINES (f) = 0;
2583 if (nlines)
2584 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2585 else
2586 {
2587 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2588 free_frame_menubar (f);
2589 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2590
2591 /* Adjust the frame size so that the client (text) dimensions
2592 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2593 set correctly. */
2594 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2595 do_pending_window_change (0);
2596 }
2597 adjust_glyphs (f);
2598 }
2599
2600
2601 /* Set the number of lines used for the tool bar of frame F to VALUE.
2602 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2603 is the old number of tool bar lines. This function changes the
2604 height of all windows on frame F to match the new tool bar height.
2605 The frame's height doesn't change. */
2606
2607 void
2608 x_set_tool_bar_lines (f, value, oldval)
2609 struct frame *f;
2610 Lisp_Object value, oldval;
2611 {
2612 int delta, nlines, root_height;
2613 Lisp_Object root_window;
2614
2615 /* Treat tool bars like menu bars. */
2616 if (FRAME_MINIBUF_ONLY_P (f))
2617 return;
2618
2619 /* Use VALUE only if an integer >= 0. */
2620 if (INTEGERP (value) && XINT (value) >= 0)
2621 nlines = XFASTINT (value);
2622 else
2623 nlines = 0;
2624
2625 /* Make sure we redisplay all windows in this frame. */
2626 ++windows_or_buffers_changed;
2627
2628 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2629
2630 /* Don't resize the tool-bar to more than we have room for. */
2631 root_window = FRAME_ROOT_WINDOW (f);
2632 root_height = XINT (XWINDOW (root_window)->height);
2633 if (root_height - delta < 1)
2634 {
2635 delta = root_height - 1;
2636 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2637 }
2638
2639 FRAME_TOOL_BAR_LINES (f) = nlines;
2640 x_change_window_heights (root_window, delta);
2641 adjust_glyphs (f);
2642
2643 /* We also have to make sure that the internal border at the top of
2644 the frame, below the menu bar or tool bar, is redrawn when the
2645 tool bar disappears. This is so because the internal border is
2646 below the tool bar if one is displayed, but is below the menu bar
2647 if there isn't a tool bar. The tool bar draws into the area
2648 below the menu bar. */
2649 if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2650 {
2651 updating_frame = f;
2652 clear_frame ();
2653 clear_current_matrices (f);
2654 updating_frame = NULL;
2655 }
2656
2657 /* If the tool bar gets smaller, the internal border below it
2658 has to be cleared. It was formerly part of the display
2659 of the larger tool bar, and updating windows won't clear it. */
2660 if (delta < 0)
2661 {
2662 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2663 int width = PIXEL_WIDTH (f);
2664 int y = nlines * CANON_Y_UNIT (f);
2665
2666 BLOCK_INPUT;
2667 {
2668 HDC hdc = get_frame_dc (f);
2669 w32_clear_area (f, hdc, 0, y, width, height);
2670 release_frame_dc (f, hdc);
2671 }
2672 UNBLOCK_INPUT;
2673
2674 if (WINDOWP (f->tool_bar_window))
2675 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2676 }
2677 }
2678
2679
2680 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2681 w32_id_name.
2682
2683 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2684 name; if NAME is a string, set F's name to NAME and set
2685 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2686
2687 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2688 suggesting a new name, which lisp code should override; if
2689 F->explicit_name is set, ignore the new name; otherwise, set it. */
2690
2691 void
2692 x_set_name (f, name, explicit)
2693 struct frame *f;
2694 Lisp_Object name;
2695 int explicit;
2696 {
2697 /* Make sure that requests from lisp code override requests from
2698 Emacs redisplay code. */
2699 if (explicit)
2700 {
2701 /* If we're switching from explicit to implicit, we had better
2702 update the mode lines and thereby update the title. */
2703 if (f->explicit_name && NILP (name))
2704 update_mode_lines = 1;
2705
2706 f->explicit_name = ! NILP (name);
2707 }
2708 else if (f->explicit_name)
2709 return;
2710
2711 /* If NAME is nil, set the name to the w32_id_name. */
2712 if (NILP (name))
2713 {
2714 /* Check for no change needed in this very common case
2715 before we do any consing. */
2716 if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
2717 XSTRING (f->name)->data))
2718 return;
2719 name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
2720 }
2721 else
2722 CHECK_STRING (name);
2723
2724 /* Don't change the name if it's already NAME. */
2725 if (! NILP (Fstring_equal (name, f->name)))
2726 return;
2727
2728 f->name = name;
2729
2730 /* For setting the frame title, the title parameter should override
2731 the name parameter. */
2732 if (! NILP (f->title))
2733 name = f->title;
2734
2735 if (FRAME_W32_WINDOW (f))
2736 {
2737 if (STRING_MULTIBYTE (name))
2738 name = ENCODE_SYSTEM (name);
2739
2740 BLOCK_INPUT;
2741 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
2742 UNBLOCK_INPUT;
2743 }
2744 }
2745
2746 /* This function should be called when the user's lisp code has
2747 specified a name for the frame; the name will override any set by the
2748 redisplay code. */
2749 void
2750 x_explicitly_set_name (f, arg, oldval)
2751 FRAME_PTR f;
2752 Lisp_Object arg, oldval;
2753 {
2754 x_set_name (f, arg, 1);
2755 }
2756
2757 /* This function should be called by Emacs redisplay code to set the
2758 name; names set this way will never override names set by the user's
2759 lisp code. */
2760 void
2761 x_implicitly_set_name (f, arg, oldval)
2762 FRAME_PTR f;
2763 Lisp_Object arg, oldval;
2764 {
2765 x_set_name (f, arg, 0);
2766 }
2767 \f
2768 /* Change the title of frame F to NAME.
2769 If NAME is nil, use the frame name as the title.
2770
2771 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2772 name; if NAME is a string, set F's name to NAME and set
2773 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2774
2775 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2776 suggesting a new name, which lisp code should override; if
2777 F->explicit_name is set, ignore the new name; otherwise, set it. */
2778
2779 void
2780 x_set_title (f, name, old_name)
2781 struct frame *f;
2782 Lisp_Object name, old_name;
2783 {
2784 /* Don't change the title if it's already NAME. */
2785 if (EQ (name, f->title))
2786 return;
2787
2788 update_mode_lines = 1;
2789
2790 f->title = name;
2791
2792 if (NILP (name))
2793 name = f->name;
2794
2795 if (FRAME_W32_WINDOW (f))
2796 {
2797 if (STRING_MULTIBYTE (name))
2798 name = ENCODE_SYSTEM (name);
2799
2800 BLOCK_INPUT;
2801 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
2802 UNBLOCK_INPUT;
2803 }
2804 }
2805 \f
2806 void
2807 x_set_autoraise (f, arg, oldval)
2808 struct frame *f;
2809 Lisp_Object arg, oldval;
2810 {
2811 f->auto_raise = !EQ (Qnil, arg);
2812 }
2813
2814 void
2815 x_set_autolower (f, arg, oldval)
2816 struct frame *f;
2817 Lisp_Object arg, oldval;
2818 {
2819 f->auto_lower = !EQ (Qnil, arg);
2820 }
2821
2822 void
2823 x_set_unsplittable (f, arg, oldval)
2824 struct frame *f;
2825 Lisp_Object arg, oldval;
2826 {
2827 f->no_split = !NILP (arg);
2828 }
2829
2830 void
2831 x_set_vertical_scroll_bars (f, arg, oldval)
2832 struct frame *f;
2833 Lisp_Object arg, oldval;
2834 {
2835 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2836 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2837 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2838 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2839 {
2840 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = NILP (arg) ?
2841 vertical_scroll_bar_none :
2842 /* Put scroll bars on the right by default, as is conventional
2843 on MS-Windows. */
2844 EQ (Qleft, arg)
2845 ? vertical_scroll_bar_left
2846 : vertical_scroll_bar_right;
2847
2848 /* We set this parameter before creating the window for the
2849 frame, so we can get the geometry right from the start.
2850 However, if the window hasn't been created yet, we shouldn't
2851 call x_set_window_size. */
2852 if (FRAME_W32_WINDOW (f))
2853 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2854 do_pending_window_change (0);
2855 }
2856 }
2857
2858 void
2859 x_set_scroll_bar_width (f, arg, oldval)
2860 struct frame *f;
2861 Lisp_Object arg, oldval;
2862 {
2863 int wid = FONT_WIDTH (f->output_data.w32->font);
2864
2865 if (NILP (arg))
2866 {
2867 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
2868 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) +
2869 wid - 1) / wid;
2870 if (FRAME_W32_WINDOW (f))
2871 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2872 do_pending_window_change (0);
2873 }
2874 else if (INTEGERP (arg) && XINT (arg) > 0
2875 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2876 {
2877 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2878 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2879 + wid-1) / wid;
2880 if (FRAME_W32_WINDOW (f))
2881 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2882 do_pending_window_change (0);
2883 }
2884 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2885 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2886 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2887 }
2888 \f
2889 /* Subroutines of creating an frame. */
2890
2891 /* Make sure that Vx_resource_name is set to a reasonable value.
2892 Fix it up, or set it to `emacs' if it is too hopeless. */
2893
2894 static void
2895 validate_x_resource_name ()
2896 {
2897 int len = 0;
2898 /* Number of valid characters in the resource name. */
2899 int good_count = 0;
2900 /* Number of invalid characters in the resource name. */
2901 int bad_count = 0;
2902 Lisp_Object new;
2903 int i;
2904
2905 if (STRINGP (Vx_resource_name))
2906 {
2907 unsigned char *p = XSTRING (Vx_resource_name)->data;
2908 int i;
2909
2910 len = STRING_BYTES (XSTRING (Vx_resource_name));
2911
2912 /* Only letters, digits, - and _ are valid in resource names.
2913 Count the valid characters and count the invalid ones. */
2914 for (i = 0; i < len; i++)
2915 {
2916 int c = p[i];
2917 if (! ((c >= 'a' && c <= 'z')
2918 || (c >= 'A' && c <= 'Z')
2919 || (c >= '0' && c <= '9')
2920 || c == '-' || c == '_'))
2921 bad_count++;
2922 else
2923 good_count++;
2924 }
2925 }
2926 else
2927 /* Not a string => completely invalid. */
2928 bad_count = 5, good_count = 0;
2929
2930 /* If name is valid already, return. */
2931 if (bad_count == 0)
2932 return;
2933
2934 /* If name is entirely invalid, or nearly so, use `emacs'. */
2935 if (good_count == 0
2936 || (good_count == 1 && bad_count > 0))
2937 {
2938 Vx_resource_name = build_string ("emacs");
2939 return;
2940 }
2941
2942 /* Name is partly valid. Copy it and replace the invalid characters
2943 with underscores. */
2944
2945 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2946
2947 for (i = 0; i < len; i++)
2948 {
2949 int c = XSTRING (new)->data[i];
2950 if (! ((c >= 'a' && c <= 'z')
2951 || (c >= 'A' && c <= 'Z')
2952 || (c >= '0' && c <= '9')
2953 || c == '-' || c == '_'))
2954 XSTRING (new)->data[i] = '_';
2955 }
2956 }
2957
2958
2959 extern char *x_get_string_resource ();
2960
2961 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2962 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2963 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2964 class, where INSTANCE is the name under which Emacs was invoked, or
2965 the name specified by the `-name' or `-rn' command-line arguments.
2966
2967 The optional arguments COMPONENT and SUBCLASS add to the key and the
2968 class, respectively. You must specify both of them or neither.
2969 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2970 and the class is `Emacs.CLASS.SUBCLASS'. */)
2971 (attribute, class, component, subclass)
2972 Lisp_Object attribute, class, component, subclass;
2973 {
2974 register char *value;
2975 char *name_key;
2976 char *class_key;
2977
2978 CHECK_STRING (attribute);
2979 CHECK_STRING (class);
2980
2981 if (!NILP (component))
2982 CHECK_STRING (component);
2983 if (!NILP (subclass))
2984 CHECK_STRING (subclass);
2985 if (NILP (component) != NILP (subclass))
2986 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2987
2988 validate_x_resource_name ();
2989
2990 /* Allocate space for the components, the dots which separate them,
2991 and the final '\0'. Make them big enough for the worst case. */
2992 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2993 + (STRINGP (component)
2994 ? STRING_BYTES (XSTRING (component)) : 0)
2995 + STRING_BYTES (XSTRING (attribute))
2996 + 3);
2997
2998 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2999 + STRING_BYTES (XSTRING (class))
3000 + (STRINGP (subclass)
3001 ? STRING_BYTES (XSTRING (subclass)) : 0)
3002 + 3);
3003
3004 /* Start with emacs.FRAMENAME for the name (the specific one)
3005 and with `Emacs' for the class key (the general one). */
3006 strcpy (name_key, XSTRING (Vx_resource_name)->data);
3007 strcpy (class_key, EMACS_CLASS);
3008
3009 strcat (class_key, ".");
3010 strcat (class_key, XSTRING (class)->data);
3011
3012 if (!NILP (component))
3013 {
3014 strcat (class_key, ".");
3015 strcat (class_key, XSTRING (subclass)->data);
3016
3017 strcat (name_key, ".");
3018 strcat (name_key, XSTRING (component)->data);
3019 }
3020
3021 strcat (name_key, ".");
3022 strcat (name_key, XSTRING (attribute)->data);
3023
3024 value = x_get_string_resource (Qnil,
3025 name_key, class_key);
3026
3027 if (value != (char *) 0)
3028 return build_string (value);
3029 else
3030 return Qnil;
3031 }
3032
3033 /* Used when C code wants a resource value. */
3034
3035 char *
3036 x_get_resource_string (attribute, class)
3037 char *attribute, *class;
3038 {
3039 char *name_key;
3040 char *class_key;
3041 struct frame *sf = SELECTED_FRAME ();
3042
3043 /* Allocate space for the components, the dots which separate them,
3044 and the final '\0'. */
3045 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
3046 + strlen (attribute) + 2);
3047 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3048 + strlen (class) + 2);
3049
3050 sprintf (name_key, "%s.%s",
3051 XSTRING (Vinvocation_name)->data,
3052 attribute);
3053 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3054
3055 return x_get_string_resource (sf, name_key, class_key);
3056 }
3057
3058 /* Types we might convert a resource string into. */
3059 enum resource_types
3060 {
3061 RES_TYPE_NUMBER,
3062 RES_TYPE_FLOAT,
3063 RES_TYPE_BOOLEAN,
3064 RES_TYPE_STRING,
3065 RES_TYPE_SYMBOL
3066 };
3067
3068 /* Return the value of parameter PARAM.
3069
3070 First search ALIST, then Vdefault_frame_alist, then the X defaults
3071 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3072
3073 Convert the resource to the type specified by desired_type.
3074
3075 If no default is specified, return Qunbound. If you call
3076 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
3077 and don't let it get stored in any Lisp-visible variables! */
3078
3079 static Lisp_Object
3080 w32_get_arg (alist, param, attribute, class, type)
3081 Lisp_Object alist, param;
3082 char *attribute;
3083 char *class;
3084 enum resource_types type;
3085 {
3086 register Lisp_Object tem;
3087
3088 tem = Fassq (param, alist);
3089 if (EQ (tem, Qnil))
3090 tem = Fassq (param, Vdefault_frame_alist);
3091 if (EQ (tem, Qnil))
3092 {
3093
3094 if (attribute)
3095 {
3096 tem = Fx_get_resource (build_string (attribute),
3097 build_string (class),
3098 Qnil, Qnil);
3099
3100 if (NILP (tem))
3101 return Qunbound;
3102
3103 switch (type)
3104 {
3105 case RES_TYPE_NUMBER:
3106 return make_number (atoi (XSTRING (tem)->data));
3107
3108 case RES_TYPE_FLOAT:
3109 return make_float (atof (XSTRING (tem)->data));
3110
3111 case RES_TYPE_BOOLEAN:
3112 tem = Fdowncase (tem);
3113 if (!strcmp (XSTRING (tem)->data, "on")
3114 || !strcmp (XSTRING (tem)->data, "true"))
3115 return Qt;
3116 else
3117 return Qnil;
3118
3119 case RES_TYPE_STRING:
3120 return tem;
3121
3122 case RES_TYPE_SYMBOL:
3123 /* As a special case, we map the values `true' and `on'
3124 to Qt, and `false' and `off' to Qnil. */
3125 {
3126 Lisp_Object lower;
3127 lower = Fdowncase (tem);
3128 if (!strcmp (XSTRING (lower)->data, "on")
3129 || !strcmp (XSTRING (lower)->data, "true"))
3130 return Qt;
3131 else if (!strcmp (XSTRING (lower)->data, "off")
3132 || !strcmp (XSTRING (lower)->data, "false"))
3133 return Qnil;
3134 else
3135 return Fintern (tem, Qnil);
3136 }
3137
3138 default:
3139 abort ();
3140 }
3141 }
3142 else
3143 return Qunbound;
3144 }
3145 return Fcdr (tem);
3146 }
3147
3148 /* Record in frame F the specified or default value according to ALIST
3149 of the parameter named PROP (a Lisp symbol).
3150 If no value is specified for PROP, look for an X default for XPROP
3151 on the frame named NAME.
3152 If that is not found either, use the value DEFLT. */
3153
3154 static Lisp_Object
3155 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3156 struct frame *f;
3157 Lisp_Object alist;
3158 Lisp_Object prop;
3159 Lisp_Object deflt;
3160 char *xprop;
3161 char *xclass;
3162 enum resource_types type;
3163 {
3164 Lisp_Object tem;
3165
3166 tem = w32_get_arg (alist, prop, xprop, xclass, type);
3167 if (EQ (tem, Qunbound))
3168 tem = deflt;
3169 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3170 return tem;
3171 }
3172 \f
3173 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3174 doc: /* Parse an X-style geometry string STRING.
3175 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3176 The properties returned may include `top', `left', `height', and `width'.
3177 The value of `left' or `top' may be an integer,
3178 or a list (+ N) meaning N pixels relative to top/left corner,
3179 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3180 (string)
3181 Lisp_Object string;
3182 {
3183 int geometry, x, y;
3184 unsigned int width, height;
3185 Lisp_Object result;
3186
3187 CHECK_STRING (string);
3188
3189 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3190 &x, &y, &width, &height);
3191
3192 result = Qnil;
3193 if (geometry & XValue)
3194 {
3195 Lisp_Object element;
3196
3197 if (x >= 0 && (geometry & XNegative))
3198 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3199 else if (x < 0 && ! (geometry & XNegative))
3200 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3201 else
3202 element = Fcons (Qleft, make_number (x));
3203 result = Fcons (element, result);
3204 }
3205
3206 if (geometry & YValue)
3207 {
3208 Lisp_Object element;
3209
3210 if (y >= 0 && (geometry & YNegative))
3211 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3212 else if (y < 0 && ! (geometry & YNegative))
3213 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3214 else
3215 element = Fcons (Qtop, make_number (y));
3216 result = Fcons (element, result);
3217 }
3218
3219 if (geometry & WidthValue)
3220 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3221 if (geometry & HeightValue)
3222 result = Fcons (Fcons (Qheight, make_number (height)), result);
3223
3224 return result;
3225 }
3226
3227 /* Calculate the desired size and position of this window,
3228 and return the flags saying which aspects were specified.
3229
3230 This function does not make the coordinates positive. */
3231
3232 #define DEFAULT_ROWS 40
3233 #define DEFAULT_COLS 80
3234
3235 static int
3236 x_figure_window_size (f, parms)
3237 struct frame *f;
3238 Lisp_Object parms;
3239 {
3240 register Lisp_Object tem0, tem1, tem2;
3241 long window_prompting = 0;
3242
3243 /* Default values if we fall through.
3244 Actually, if that happens we should get
3245 window manager prompting. */
3246 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3247 f->height = DEFAULT_ROWS;
3248 /* Window managers expect that if program-specified
3249 positions are not (0,0), they're intentional, not defaults. */
3250 f->output_data.w32->top_pos = 0;
3251 f->output_data.w32->left_pos = 0;
3252
3253 /* Ensure that old new_width and new_height will not override the
3254 values set here. */
3255 FRAME_NEW_WIDTH (f) = 0;
3256 FRAME_NEW_HEIGHT (f) = 0;
3257
3258 tem0 = w32_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3259 tem1 = w32_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3260 tem2 = w32_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3261 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3262 {
3263 if (!EQ (tem0, Qunbound))
3264 {
3265 CHECK_NUMBER (tem0);
3266 f->height = XINT (tem0);
3267 }
3268 if (!EQ (tem1, Qunbound))
3269 {
3270 CHECK_NUMBER (tem1);
3271 SET_FRAME_WIDTH (f, XINT (tem1));
3272 }
3273 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3274 window_prompting |= USSize;
3275 else
3276 window_prompting |= PSize;
3277 }
3278
3279 f->output_data.w32->vertical_scroll_bar_extra
3280 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3281 ? 0
3282 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3283 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3284 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
3285 x_compute_fringe_widths (f, 0);
3286 f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3287 f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3288
3289 tem0 = w32_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3290 tem1 = w32_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3291 tem2 = w32_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3292 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3293 {
3294 if (EQ (tem0, Qminus))
3295 {
3296 f->output_data.w32->top_pos = 0;
3297 window_prompting |= YNegative;
3298 }
3299 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3300 && CONSP (XCDR (tem0))
3301 && INTEGERP (XCAR (XCDR (tem0))))
3302 {
3303 f->output_data.w32->top_pos = - XINT (XCAR (XCDR (tem0)));
3304 window_prompting |= YNegative;
3305 }
3306 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3307 && CONSP (XCDR (tem0))
3308 && INTEGERP (XCAR (XCDR (tem0))))
3309 {
3310 f->output_data.w32->top_pos = XINT (XCAR (XCDR (tem0)));
3311 }
3312 else if (EQ (tem0, Qunbound))
3313 f->output_data.w32->top_pos = 0;
3314 else
3315 {
3316 CHECK_NUMBER (tem0);
3317 f->output_data.w32->top_pos = XINT (tem0);
3318 if (f->output_data.w32->top_pos < 0)
3319 window_prompting |= YNegative;
3320 }
3321
3322 if (EQ (tem1, Qminus))
3323 {
3324 f->output_data.w32->left_pos = 0;
3325 window_prompting |= XNegative;
3326 }
3327 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3328 && CONSP (XCDR (tem1))
3329 && INTEGERP (XCAR (XCDR (tem1))))
3330 {
3331 f->output_data.w32->left_pos = - XINT (XCAR (XCDR (tem1)));
3332 window_prompting |= XNegative;
3333 }
3334 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3335 && CONSP (XCDR (tem1))
3336 && INTEGERP (XCAR (XCDR (tem1))))
3337 {
3338 f->output_data.w32->left_pos = XINT (XCAR (XCDR (tem1)));
3339 }
3340 else if (EQ (tem1, Qunbound))
3341 f->output_data.w32->left_pos = 0;
3342 else
3343 {
3344 CHECK_NUMBER (tem1);
3345 f->output_data.w32->left_pos = XINT (tem1);
3346 if (f->output_data.w32->left_pos < 0)
3347 window_prompting |= XNegative;
3348 }
3349
3350 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3351 window_prompting |= USPosition;
3352 else
3353 window_prompting |= PPosition;
3354 }
3355
3356 return window_prompting;
3357 }
3358
3359 \f
3360
3361 extern LRESULT CALLBACK w32_wnd_proc ();
3362
3363 BOOL
3364 w32_init_class (hinst)
3365 HINSTANCE hinst;
3366 {
3367 WNDCLASS wc;
3368
3369 wc.style = CS_HREDRAW | CS_VREDRAW;
3370 wc.lpfnWndProc = (WNDPROC) w32_wnd_proc;
3371 wc.cbClsExtra = 0;
3372 wc.cbWndExtra = WND_EXTRA_BYTES;
3373 wc.hInstance = hinst;
3374 wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
3375 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
3376 wc.hbrBackground = NULL; /* GetStockObject (WHITE_BRUSH); */
3377 wc.lpszMenuName = NULL;
3378 wc.lpszClassName = EMACS_CLASS;
3379
3380 return (RegisterClass (&wc));
3381 }
3382
3383 HWND
3384 w32_createscrollbar (f, bar)
3385 struct frame *f;
3386 struct scroll_bar * bar;
3387 {
3388 return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
3389 /* Position and size of scroll bar. */
3390 XINT(bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3391 XINT(bar->top),
3392 XINT(bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3393 XINT(bar->height),
3394 FRAME_W32_WINDOW (f),
3395 NULL,
3396 hinst,
3397 NULL));
3398 }
3399
3400 void
3401 w32_createwindow (f)
3402 struct frame *f;
3403 {
3404 HWND hwnd;
3405 RECT rect;
3406
3407 rect.left = rect.top = 0;
3408 rect.right = PIXEL_WIDTH (f);
3409 rect.bottom = PIXEL_HEIGHT (f);
3410
3411 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
3412 FRAME_EXTERNAL_MENU_BAR (f));
3413
3414 /* Do first time app init */
3415
3416 if (!hprevinst)
3417 {
3418 w32_init_class (hinst);
3419 }
3420
3421 FRAME_W32_WINDOW (f) = hwnd
3422 = CreateWindow (EMACS_CLASS,
3423 f->namebuf,
3424 f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
3425 f->output_data.w32->left_pos,
3426 f->output_data.w32->top_pos,
3427 rect.right - rect.left,
3428 rect.bottom - rect.top,
3429 NULL,
3430 NULL,
3431 hinst,
3432 NULL);
3433
3434 if (hwnd)
3435 {
3436 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
3437 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
3438 SetWindowLong (hwnd, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
3439 SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
3440 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
3441
3442 /* Enable drag-n-drop. */
3443 DragAcceptFiles (hwnd, TRUE);
3444
3445 /* Do this to discard the default setting specified by our parent. */
3446 ShowWindow (hwnd, SW_HIDE);
3447 }
3448 }
3449
3450 void
3451 my_post_msg (wmsg, hwnd, msg, wParam, lParam)
3452 W32Msg * wmsg;
3453 HWND hwnd;
3454 UINT msg;
3455 WPARAM wParam;
3456 LPARAM lParam;
3457 {
3458 wmsg->msg.hwnd = hwnd;
3459 wmsg->msg.message = msg;
3460 wmsg->msg.wParam = wParam;
3461 wmsg->msg.lParam = lParam;
3462 wmsg->msg.time = GetMessageTime ();
3463
3464 post_msg (wmsg);
3465 }
3466
3467 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
3468 between left and right keys as advertised. We test for this
3469 support dynamically, and set a flag when the support is absent. If
3470 absent, we keep track of the left and right control and alt keys
3471 ourselves. This is particularly necessary on keyboards that rely
3472 upon the AltGr key, which is represented as having the left control
3473 and right alt keys pressed. For these keyboards, we need to know
3474 when the left alt key has been pressed in addition to the AltGr key
3475 so that we can properly support M-AltGr-key sequences (such as M-@
3476 on Swedish keyboards). */
3477
3478 #define EMACS_LCONTROL 0
3479 #define EMACS_RCONTROL 1
3480 #define EMACS_LMENU 2
3481 #define EMACS_RMENU 3
3482
3483 static int modifiers[4];
3484 static int modifiers_recorded;
3485 static int modifier_key_support_tested;
3486
3487 static void
3488 test_modifier_support (unsigned int wparam)
3489 {
3490 unsigned int l, r;
3491
3492 if (wparam != VK_CONTROL && wparam != VK_MENU)
3493 return;
3494 if (wparam == VK_CONTROL)
3495 {
3496 l = VK_LCONTROL;
3497 r = VK_RCONTROL;
3498 }
3499 else
3500 {
3501 l = VK_LMENU;
3502 r = VK_RMENU;
3503 }
3504 if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
3505 modifiers_recorded = 1;
3506 else
3507 modifiers_recorded = 0;
3508 modifier_key_support_tested = 1;
3509 }
3510
3511 static void
3512 record_keydown (unsigned int wparam, unsigned int lparam)
3513 {
3514 int i;
3515
3516 if (!modifier_key_support_tested)
3517 test_modifier_support (wparam);
3518
3519 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
3520 return;
3521
3522 if (wparam == VK_CONTROL)
3523 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
3524 else
3525 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
3526
3527 modifiers[i] = 1;
3528 }
3529
3530 static void
3531 record_keyup (unsigned int wparam, unsigned int lparam)
3532 {
3533 int i;
3534
3535 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
3536 return;
3537
3538 if (wparam == VK_CONTROL)
3539 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
3540 else
3541 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
3542
3543 modifiers[i] = 0;
3544 }
3545
3546 /* Emacs can lose focus while a modifier key has been pressed. When
3547 it regains focus, be conservative and clear all modifiers since
3548 we cannot reconstruct the left and right modifier state. */
3549 static void
3550 reset_modifiers ()
3551 {
3552 SHORT ctrl, alt;
3553
3554 if (GetFocus () == NULL)
3555 /* Emacs doesn't have keyboard focus. Do nothing. */
3556 return;
3557
3558 ctrl = GetAsyncKeyState (VK_CONTROL);
3559 alt = GetAsyncKeyState (VK_MENU);
3560
3561 if (!(ctrl & 0x08000))
3562 /* Clear any recorded control modifier state. */
3563 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3564
3565 if (!(alt & 0x08000))
3566 /* Clear any recorded alt modifier state. */
3567 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3568
3569 /* Update the state of all modifier keys, because modifiers used in
3570 hot-key combinations can get stuck on if Emacs loses focus as a
3571 result of a hot-key being pressed. */
3572 {
3573 BYTE keystate[256];
3574
3575 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
3576
3577 GetKeyboardState (keystate);
3578 keystate[VK_SHIFT] = CURRENT_STATE (VK_SHIFT);
3579 keystate[VK_CONTROL] = CURRENT_STATE (VK_CONTROL);
3580 keystate[VK_LCONTROL] = CURRENT_STATE (VK_LCONTROL);
3581 keystate[VK_RCONTROL] = CURRENT_STATE (VK_RCONTROL);
3582 keystate[VK_MENU] = CURRENT_STATE (VK_MENU);
3583 keystate[VK_LMENU] = CURRENT_STATE (VK_LMENU);
3584 keystate[VK_RMENU] = CURRENT_STATE (VK_RMENU);
3585 keystate[VK_LWIN] = CURRENT_STATE (VK_LWIN);
3586 keystate[VK_RWIN] = CURRENT_STATE (VK_RWIN);
3587 keystate[VK_APPS] = CURRENT_STATE (VK_APPS);
3588 SetKeyboardState (keystate);
3589 }
3590 }
3591
3592 /* Synchronize modifier state with what is reported with the current
3593 keystroke. Even if we cannot distinguish between left and right
3594 modifier keys, we know that, if no modifiers are set, then neither
3595 the left or right modifier should be set. */
3596 static void
3597 sync_modifiers ()
3598 {
3599 if (!modifiers_recorded)
3600 return;
3601
3602 if (!(GetKeyState (VK_CONTROL) & 0x8000))
3603 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3604
3605 if (!(GetKeyState (VK_MENU) & 0x8000))
3606 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3607 }
3608
3609 static int
3610 modifier_set (int vkey)
3611 {
3612 if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
3613 return (GetKeyState (vkey) & 0x1);
3614 if (!modifiers_recorded)
3615 return (GetKeyState (vkey) & 0x8000);
3616
3617 switch (vkey)
3618 {
3619 case VK_LCONTROL:
3620 return modifiers[EMACS_LCONTROL];
3621 case VK_RCONTROL:
3622 return modifiers[EMACS_RCONTROL];
3623 case VK_LMENU:
3624 return modifiers[EMACS_LMENU];
3625 case VK_RMENU:
3626 return modifiers[EMACS_RMENU];
3627 }
3628 return (GetKeyState (vkey) & 0x8000);
3629 }
3630
3631 /* Convert between the modifier bits W32 uses and the modifier bits
3632 Emacs uses. */
3633
3634 unsigned int
3635 w32_key_to_modifier (int key)
3636 {
3637 Lisp_Object key_mapping;
3638
3639 switch (key)
3640 {
3641 case VK_LWIN:
3642 key_mapping = Vw32_lwindow_modifier;
3643 break;
3644 case VK_RWIN:
3645 key_mapping = Vw32_rwindow_modifier;
3646 break;
3647 case VK_APPS:
3648 key_mapping = Vw32_apps_modifier;
3649 break;
3650 case VK_SCROLL:
3651 key_mapping = Vw32_scroll_lock_modifier;
3652 break;
3653 default:
3654 key_mapping = Qnil;
3655 }
3656
3657 /* NB. This code runs in the input thread, asychronously to the lisp
3658 thread, so we must be careful to ensure access to lisp data is
3659 thread-safe. The following code is safe because the modifier
3660 variable values are updated atomically from lisp and symbols are
3661 not relocated by GC. Also, we don't have to worry about seeing GC
3662 markbits here. */
3663 if (EQ (key_mapping, Qhyper))
3664 return hyper_modifier;
3665 if (EQ (key_mapping, Qsuper))
3666 return super_modifier;
3667 if (EQ (key_mapping, Qmeta))
3668 return meta_modifier;
3669 if (EQ (key_mapping, Qalt))
3670 return alt_modifier;
3671 if (EQ (key_mapping, Qctrl))
3672 return ctrl_modifier;
3673 if (EQ (key_mapping, Qcontrol)) /* synonym for ctrl */
3674 return ctrl_modifier;
3675 if (EQ (key_mapping, Qshift))
3676 return shift_modifier;
3677
3678 /* Don't generate any modifier if not explicitly requested. */
3679 return 0;
3680 }
3681
3682 unsigned int
3683 w32_get_modifiers ()
3684 {
3685 return ((modifier_set (VK_SHIFT) ? shift_modifier : 0) |
3686 (modifier_set (VK_CONTROL) ? ctrl_modifier : 0) |
3687 (modifier_set (VK_LWIN) ? w32_key_to_modifier (VK_LWIN) : 0) |
3688 (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) |
3689 (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) |
3690 (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) |
3691 (modifier_set (VK_MENU) ?
3692 ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
3693 }
3694
3695 /* We map the VK_* modifiers into console modifier constants
3696 so that we can use the same routines to handle both console
3697 and window input. */
3698
3699 static int
3700 construct_console_modifiers ()
3701 {
3702 int mods;
3703
3704 mods = 0;
3705 mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
3706 mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
3707 mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0;
3708 mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0;
3709 mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
3710 mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
3711 mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
3712 mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
3713 mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0;
3714 mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0;
3715 mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0;
3716
3717 return mods;
3718 }
3719
3720 static int
3721 w32_get_key_modifiers (unsigned int wparam, unsigned int lparam)
3722 {
3723 int mods;
3724
3725 /* Convert to emacs modifiers. */
3726 mods = w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam);
3727
3728 return mods;
3729 }
3730
3731 unsigned int
3732 map_keypad_keys (unsigned int virt_key, unsigned int extended)
3733 {
3734 if (virt_key < VK_CLEAR || virt_key > VK_DELETE)
3735 return virt_key;
3736
3737 if (virt_key == VK_RETURN)
3738 return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
3739
3740 if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN)
3741 return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key);
3742
3743 if (virt_key == VK_INSERT || virt_key == VK_DELETE)
3744 return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key);
3745
3746 if (virt_key == VK_CLEAR)
3747 return (!extended ? VK_NUMPAD_CLEAR : virt_key);
3748
3749 return virt_key;
3750 }
3751
3752 /* List of special key combinations which w32 would normally capture,
3753 but emacs should grab instead. Not directly visible to lisp, to
3754 simplify synchronization. Each item is an integer encoding a virtual
3755 key code and modifier combination to capture. */
3756 Lisp_Object w32_grabbed_keys;
3757
3758 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
3759 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
3760 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
3761 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
3762
3763 /* Register hot-keys for reserved key combinations when Emacs has
3764 keyboard focus, since this is the only way Emacs can receive key
3765 combinations like Alt-Tab which are used by the system. */
3766
3767 static void
3768 register_hot_keys (hwnd)
3769 HWND hwnd;
3770 {
3771 Lisp_Object keylist;
3772
3773 /* Use GC_CONSP, since we are called asynchronously. */
3774 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3775 {
3776 Lisp_Object key = XCAR (keylist);
3777
3778 /* Deleted entries get set to nil. */
3779 if (!INTEGERP (key))
3780 continue;
3781
3782 RegisterHotKey (hwnd, HOTKEY_ID (key),
3783 HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
3784 }
3785 }
3786
3787 static void
3788 unregister_hot_keys (hwnd)
3789 HWND hwnd;
3790 {
3791 Lisp_Object keylist;
3792
3793 /* Use GC_CONSP, since we are called asynchronously. */
3794 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3795 {
3796 Lisp_Object key = XCAR (keylist);
3797
3798 if (!INTEGERP (key))
3799 continue;
3800
3801 UnregisterHotKey (hwnd, HOTKEY_ID (key));
3802 }
3803 }
3804
3805 /* Main message dispatch loop. */
3806
3807 static void
3808 w32_msg_pump (deferred_msg * msg_buf)
3809 {
3810 MSG msg;
3811 int result;
3812 HWND focus_window;
3813
3814 msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
3815
3816 while (GetMessage (&msg, NULL, 0, 0))
3817 {
3818 if (msg.hwnd == NULL)
3819 {
3820 switch (msg.message)
3821 {
3822 case WM_NULL:
3823 /* Produced by complete_deferred_msg; just ignore. */
3824 break;
3825 case WM_EMACS_CREATEWINDOW:
3826 w32_createwindow ((struct frame *) msg.wParam);
3827 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3828 abort ();
3829 break;
3830 case WM_EMACS_SETLOCALE:
3831 SetThreadLocale (msg.wParam);
3832 /* Reply is not expected. */
3833 break;
3834 case WM_EMACS_SETKEYBOARDLAYOUT:
3835 result = (int) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
3836 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
3837 result, 0))
3838 abort ();
3839 break;
3840 case WM_EMACS_REGISTER_HOT_KEY:
3841 focus_window = GetFocus ();
3842 if (focus_window != NULL)
3843 RegisterHotKey (focus_window,
3844 HOTKEY_ID (msg.wParam),
3845 HOTKEY_MODIFIERS (msg.wParam),
3846 HOTKEY_VK_CODE (msg.wParam));
3847 /* Reply is not expected. */
3848 break;
3849 case WM_EMACS_UNREGISTER_HOT_KEY:
3850 focus_window = GetFocus ();
3851 if (focus_window != NULL)
3852 UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam));
3853 /* Mark item as erased. NB: this code must be
3854 thread-safe. The next line is okay because the cons
3855 cell is never made into garbage and is not relocated by
3856 GC. */
3857 XSETCAR ((Lisp_Object) msg.lParam, Qnil);
3858 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3859 abort ();
3860 break;
3861 case WM_EMACS_TOGGLE_LOCK_KEY:
3862 {
3863 int vk_code = (int) msg.wParam;
3864 int cur_state = (GetKeyState (vk_code) & 1);
3865 Lisp_Object new_state = (Lisp_Object) msg.lParam;
3866
3867 /* NB: This code must be thread-safe. It is safe to
3868 call NILP because symbols are not relocated by GC,
3869 and pointer here is not touched by GC (so the markbit
3870 can't be set). Numbers are safe because they are
3871 immediate values. */
3872 if (NILP (new_state)
3873 || (NUMBERP (new_state)
3874 && ((XUINT (new_state)) & 1) != cur_state))
3875 {
3876 one_w32_display_info.faked_key = vk_code;
3877
3878 keybd_event ((BYTE) vk_code,
3879 (BYTE) MapVirtualKey (vk_code, 0),
3880 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3881 keybd_event ((BYTE) vk_code,
3882 (BYTE) MapVirtualKey (vk_code, 0),
3883 KEYEVENTF_EXTENDEDKEY | 0, 0);
3884 keybd_event ((BYTE) vk_code,
3885 (BYTE) MapVirtualKey (vk_code, 0),
3886 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3887 cur_state = !cur_state;
3888 }
3889 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
3890 cur_state, 0))
3891 abort ();
3892 }
3893 break;
3894 default:
3895 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
3896 }
3897 }
3898 else
3899 {
3900 DispatchMessage (&msg);
3901 }
3902
3903 /* Exit nested loop when our deferred message has completed. */
3904 if (msg_buf->completed)
3905 break;
3906 }
3907 }
3908
3909 deferred_msg * deferred_msg_head;
3910
3911 static deferred_msg *
3912 find_deferred_msg (HWND hwnd, UINT msg)
3913 {
3914 deferred_msg * item;
3915
3916 /* Don't actually need synchronization for read access, since
3917 modification of single pointer is always atomic. */
3918 /* enter_crit (); */
3919
3920 for (item = deferred_msg_head; item != NULL; item = item->next)
3921 if (item->w32msg.msg.hwnd == hwnd
3922 && item->w32msg.msg.message == msg)
3923 break;
3924
3925 /* leave_crit (); */
3926
3927 return item;
3928 }
3929
3930 static LRESULT
3931 send_deferred_msg (deferred_msg * msg_buf,
3932 HWND hwnd,
3933 UINT msg,
3934 WPARAM wParam,
3935 LPARAM lParam)
3936 {
3937 /* Only input thread can send deferred messages. */
3938 if (GetCurrentThreadId () != dwWindowsThreadId)
3939 abort ();
3940
3941 /* It is an error to send a message that is already deferred. */
3942 if (find_deferred_msg (hwnd, msg) != NULL)
3943 abort ();
3944
3945 /* Enforced synchronization is not needed because this is the only
3946 function that alters deferred_msg_head, and the following critical
3947 section is guaranteed to only be serially reentered (since only the
3948 input thread can call us). */
3949
3950 /* enter_crit (); */
3951
3952 msg_buf->completed = 0;
3953 msg_buf->next = deferred_msg_head;
3954 deferred_msg_head = msg_buf;
3955 my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam);
3956
3957 /* leave_crit (); */
3958
3959 /* Start a new nested message loop to process other messages until
3960 this one is completed. */
3961 w32_msg_pump (msg_buf);
3962
3963 deferred_msg_head = msg_buf->next;
3964
3965 return msg_buf->result;
3966 }
3967
3968 void
3969 complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
3970 {
3971 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
3972
3973 if (msg_buf == NULL)
3974 /* Message may have been cancelled, so don't abort(). */
3975 return;
3976
3977 msg_buf->result = result;
3978 msg_buf->completed = 1;
3979
3980 /* Ensure input thread is woken so it notices the completion. */
3981 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
3982 }
3983
3984 void
3985 cancel_all_deferred_msgs ()
3986 {
3987 deferred_msg * item;
3988
3989 /* Don't actually need synchronization for read access, since
3990 modification of single pointer is always atomic. */
3991 /* enter_crit (); */
3992
3993 for (item = deferred_msg_head; item != NULL; item = item->next)
3994 {
3995 item->result = 0;
3996 item->completed = 1;
3997 }
3998
3999 /* leave_crit (); */
4000
4001 /* Ensure input thread is woken so it notices the completion. */
4002 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
4003 }
4004
4005 DWORD
4006 w32_msg_worker (dw)
4007 DWORD dw;
4008 {
4009 MSG msg;
4010 deferred_msg dummy_buf;
4011
4012 /* Ensure our message queue is created */
4013
4014 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
4015
4016 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
4017 abort ();
4018
4019 memset (&dummy_buf, 0, sizeof (dummy_buf));
4020 dummy_buf.w32msg.msg.hwnd = NULL;
4021 dummy_buf.w32msg.msg.message = WM_NULL;
4022
4023 /* This is the inital message loop which should only exit when the
4024 application quits. */
4025 w32_msg_pump (&dummy_buf);
4026
4027 return 0;
4028 }
4029
4030 static void
4031 post_character_message (hwnd, msg, wParam, lParam, modifiers)
4032 HWND hwnd;
4033 UINT msg;
4034 WPARAM wParam;
4035 LPARAM lParam;
4036 DWORD modifiers;
4037
4038 {
4039 W32Msg wmsg;
4040
4041 wmsg.dwModifiers = modifiers;
4042
4043 /* Detect quit_char and set quit-flag directly. Note that we
4044 still need to post a message to ensure the main thread will be
4045 woken up if blocked in sys_select(), but we do NOT want to post
4046 the quit_char message itself (because it will usually be as if
4047 the user had typed quit_char twice). Instead, we post a dummy
4048 message that has no particular effect. */
4049 {
4050 int c = wParam;
4051 if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
4052 c = make_ctrl_char (c) & 0377;
4053 if (c == quit_char
4054 || (wmsg.dwModifiers == 0 &&
4055 XFASTINT (Vw32_quit_key) && wParam == XFASTINT (Vw32_quit_key)))
4056 {
4057 Vquit_flag = Qt;
4058
4059 /* The choice of message is somewhat arbitrary, as long as
4060 the main thread handler just ignores it. */
4061 msg = WM_NULL;
4062
4063 /* Interrupt any blocking system calls. */
4064 signal_quit ();
4065
4066 /* As a safety precaution, forcibly complete any deferred
4067 messages. This is a kludge, but I don't see any particularly
4068 clean way to handle the situation where a deferred message is
4069 "dropped" in the lisp thread, and will thus never be
4070 completed, eg. by the user trying to activate the menubar
4071 when the lisp thread is busy, and then typing C-g when the
4072 menubar doesn't open promptly (with the result that the
4073 menubar never responds at all because the deferred
4074 WM_INITMENU message is never completed). Another problem
4075 situation is when the lisp thread calls SendMessage (to send
4076 a window manager command) when a message has been deferred;
4077 the lisp thread gets blocked indefinitely waiting for the
4078 deferred message to be completed, which itself is waiting for
4079 the lisp thread to respond.
4080
4081 Note that we don't want to block the input thread waiting for
4082 a reponse from the lisp thread (although that would at least
4083 solve the deadlock problem above), because we want to be able
4084 to receive C-g to interrupt the lisp thread. */
4085 cancel_all_deferred_msgs ();
4086 }
4087 }
4088
4089 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4090 }
4091
4092 /* Main window procedure */
4093
4094 LRESULT CALLBACK
4095 w32_wnd_proc (hwnd, msg, wParam, lParam)
4096 HWND hwnd;
4097 UINT msg;
4098 WPARAM wParam;
4099 LPARAM lParam;
4100 {
4101 struct frame *f;
4102 struct w32_display_info *dpyinfo = &one_w32_display_info;
4103 W32Msg wmsg;
4104 int windows_translate;
4105 int key;
4106
4107 /* Note that it is okay to call x_window_to_frame, even though we are
4108 not running in the main lisp thread, because frame deletion
4109 requires the lisp thread to synchronize with this thread. Thus, if
4110 a frame struct is returned, it can be used without concern that the
4111 lisp thread might make it disappear while we are using it.
4112
4113 NB. Walking the frame list in this thread is safe (as long as
4114 writes of Lisp_Object slots are atomic, which they are on Windows).
4115 Although delete-frame can destructively modify the frame list while
4116 we are walking it, a garbage collection cannot occur until after
4117 delete-frame has synchronized with this thread.
4118
4119 It is also safe to use functions that make GDI calls, such as
4120 w32_clear_rect, because these functions must obtain a DC handle
4121 from the frame struct using get_frame_dc which is thread-aware. */
4122
4123 switch (msg)
4124 {
4125 case WM_ERASEBKGND:
4126 f = x_window_to_frame (dpyinfo, hwnd);
4127 if (f)
4128 {
4129 HDC hdc = get_frame_dc (f);
4130 GetUpdateRect (hwnd, &wmsg.rect, FALSE);
4131 w32_clear_rect (f, hdc, &wmsg.rect);
4132 release_frame_dc (f, hdc);
4133
4134 #if defined (W32_DEBUG_DISPLAY)
4135 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
4136 f,
4137 wmsg.rect.left, wmsg.rect.top,
4138 wmsg.rect.right, wmsg.rect.bottom));
4139 #endif /* W32_DEBUG_DISPLAY */
4140 }
4141 return 1;
4142 case WM_PALETTECHANGED:
4143 /* ignore our own changes */
4144 if ((HWND)wParam != hwnd)
4145 {
4146 f = x_window_to_frame (dpyinfo, hwnd);
4147 if (f)
4148 /* get_frame_dc will realize our palette and force all
4149 frames to be redrawn if needed. */
4150 release_frame_dc (f, get_frame_dc (f));
4151 }
4152 return 0;
4153 case WM_PAINT:
4154 {
4155 PAINTSTRUCT paintStruct;
4156 RECT update_rect;
4157
4158 f = x_window_to_frame (dpyinfo, hwnd);
4159 if (f == 0)
4160 {
4161 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd));
4162 return 0;
4163 }
4164
4165 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
4166 fails. Apparently this can happen under some
4167 circumstances. */
4168 if (!w32_strict_painting || GetUpdateRect (hwnd, &update_rect, FALSE))
4169 {
4170 enter_crit ();
4171 BeginPaint (hwnd, &paintStruct);
4172
4173 if (w32_strict_painting)
4174 /* The rectangles returned by GetUpdateRect and BeginPaint
4175 do not always match. GetUpdateRect seems to be the
4176 more reliable of the two. */
4177 wmsg.rect = update_rect;
4178 else
4179 wmsg.rect = paintStruct.rcPaint;
4180
4181 #if defined (W32_DEBUG_DISPLAY)
4182 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
4183 f,
4184 wmsg.rect.left, wmsg.rect.top,
4185 wmsg.rect.right, wmsg.rect.bottom));
4186 DebPrint ((" [update region is %d,%d-%d,%d]\n",
4187 update_rect.left, update_rect.top,
4188 update_rect.right, update_rect.bottom));
4189 #endif
4190 EndPaint (hwnd, &paintStruct);
4191 leave_crit ();
4192
4193 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4194
4195 return 0;
4196 }
4197
4198 /* If GetUpdateRect returns 0 (meaning there is no update
4199 region), assume the whole window needs to be repainted. */
4200 GetClientRect(hwnd, &wmsg.rect);
4201 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4202 return 0;
4203 }
4204
4205 case WM_INPUTLANGCHANGE:
4206 /* Inform lisp thread of keyboard layout changes. */
4207 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4208
4209 /* Clear dead keys in the keyboard state; for simplicity only
4210 preserve modifier key states. */
4211 {
4212 int i;
4213 BYTE keystate[256];
4214
4215 GetKeyboardState (keystate);
4216 for (i = 0; i < 256; i++)
4217 if (1
4218 && i != VK_SHIFT
4219 && i != VK_LSHIFT
4220 && i != VK_RSHIFT
4221 && i != VK_CAPITAL
4222 && i != VK_NUMLOCK
4223 && i != VK_SCROLL
4224 && i != VK_CONTROL
4225 && i != VK_LCONTROL
4226 && i != VK_RCONTROL
4227 && i != VK_MENU
4228 && i != VK_LMENU
4229 && i != VK_RMENU
4230 && i != VK_LWIN
4231 && i != VK_RWIN)
4232 keystate[i] = 0;
4233 SetKeyboardState (keystate);
4234 }
4235 goto dflt;
4236
4237 case WM_HOTKEY:
4238 /* Synchronize hot keys with normal input. */
4239 PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
4240 return (0);
4241
4242 case WM_KEYUP:
4243 case WM_SYSKEYUP:
4244 record_keyup (wParam, lParam);
4245 goto dflt;
4246
4247 case WM_KEYDOWN:
4248 case WM_SYSKEYDOWN:
4249 /* Ignore keystrokes we fake ourself; see below. */
4250 if (dpyinfo->faked_key == wParam)
4251 {
4252 dpyinfo->faked_key = 0;
4253 /* Make sure TranslateMessage sees them though (as long as
4254 they don't produce WM_CHAR messages). This ensures that
4255 indicator lights are toggled promptly on Windows 9x, for
4256 example. */
4257 if (lispy_function_keys[wParam] != 0)
4258 {
4259 windows_translate = 1;
4260 goto translate;
4261 }
4262 return 0;
4263 }
4264
4265 /* Synchronize modifiers with current keystroke. */
4266 sync_modifiers ();
4267 record_keydown (wParam, lParam);
4268 wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
4269
4270 windows_translate = 0;
4271
4272 switch (wParam)
4273 {
4274 case VK_LWIN:
4275 if (NILP (Vw32_pass_lwindow_to_system))
4276 {
4277 /* Prevent system from acting on keyup (which opens the
4278 Start menu if no other key was pressed) by simulating a
4279 press of Space which we will ignore. */
4280 if (GetAsyncKeyState (wParam) & 1)
4281 {
4282 if (NUMBERP (Vw32_phantom_key_code))
4283 key = XUINT (Vw32_phantom_key_code) & 255;
4284 else
4285 key = VK_SPACE;
4286 dpyinfo->faked_key = key;
4287 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
4288 }
4289 }
4290 if (!NILP (Vw32_lwindow_modifier))
4291 return 0;
4292 break;
4293 case VK_RWIN:
4294 if (NILP (Vw32_pass_rwindow_to_system))
4295 {
4296 if (GetAsyncKeyState (wParam) & 1)
4297 {
4298 if (NUMBERP (Vw32_phantom_key_code))
4299 key = XUINT (Vw32_phantom_key_code) & 255;
4300 else
4301 key = VK_SPACE;
4302 dpyinfo->faked_key = key;
4303 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
4304 }
4305 }
4306 if (!NILP (Vw32_rwindow_modifier))
4307 return 0;
4308 break;
4309 case VK_APPS:
4310 if (!NILP (Vw32_apps_modifier))
4311 return 0;
4312 break;
4313 case VK_MENU:
4314 if (NILP (Vw32_pass_alt_to_system))
4315 /* Prevent DefWindowProc from activating the menu bar if an
4316 Alt key is pressed and released by itself. */
4317 return 0;
4318 windows_translate = 1;
4319 break;
4320 case VK_CAPITAL:
4321 /* Decide whether to treat as modifier or function key. */
4322 if (NILP (Vw32_enable_caps_lock))
4323 goto disable_lock_key;
4324 windows_translate = 1;
4325 break;
4326 case VK_NUMLOCK:
4327 /* Decide whether to treat as modifier or function key. */
4328 if (NILP (Vw32_enable_num_lock))
4329 goto disable_lock_key;
4330 windows_translate = 1;
4331 break;
4332 case VK_SCROLL:
4333 /* Decide whether to treat as modifier or function key. */
4334 if (NILP (Vw32_scroll_lock_modifier))
4335 goto disable_lock_key;
4336 windows_translate = 1;
4337 break;
4338 disable_lock_key:
4339 /* Ensure the appropriate lock key state (and indicator light)
4340 remains in the same state. We do this by faking another
4341 press of the relevant key. Apparently, this really is the
4342 only way to toggle the state of the indicator lights. */
4343 dpyinfo->faked_key = wParam;
4344 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4345 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
4346 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4347 KEYEVENTF_EXTENDEDKEY | 0, 0);
4348 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
4349 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
4350 /* Ensure indicator lights are updated promptly on Windows 9x
4351 (TranslateMessage apparently does this), after forwarding
4352 input event. */
4353 post_character_message (hwnd, msg, wParam, lParam,
4354 w32_get_key_modifiers (wParam, lParam));
4355 windows_translate = 1;
4356 break;
4357 case VK_CONTROL:
4358 case VK_SHIFT:
4359 case VK_PROCESSKEY: /* Generated by IME. */
4360 windows_translate = 1;
4361 break;
4362 case VK_CANCEL:
4363 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
4364 which is confusing for purposes of key binding; convert
4365 VK_CANCEL events into VK_PAUSE events. */
4366 wParam = VK_PAUSE;
4367 break;
4368 case VK_PAUSE:
4369 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
4370 for purposes of key binding; convert these back into
4371 VK_NUMLOCK events, at least when we want to see NumLock key
4372 presses. (Note that there is never any possibility that
4373 VK_PAUSE with Ctrl really is C-Pause as per above.) */
4374 if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL))
4375 wParam = VK_NUMLOCK;
4376 break;
4377 default:
4378 /* If not defined as a function key, change it to a WM_CHAR message. */
4379 if (lispy_function_keys[wParam] == 0)
4380 {
4381 DWORD modifiers = construct_console_modifiers ();
4382
4383 if (!NILP (Vw32_recognize_altgr)
4384 && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))
4385 {
4386 /* Always let TranslateMessage handle AltGr key chords;
4387 for some reason, ToAscii doesn't always process AltGr
4388 chords correctly. */
4389 windows_translate = 1;
4390 }
4391 else if ((modifiers & (~SHIFT_PRESSED & ~CAPSLOCK_ON)) != 0)
4392 {
4393 /* Handle key chords including any modifiers other
4394 than shift directly, in order to preserve as much
4395 modifier information as possible. */
4396 if ('A' <= wParam && wParam <= 'Z')
4397 {
4398 /* Don't translate modified alphabetic keystrokes,
4399 so the user doesn't need to constantly switch
4400 layout to type control or meta keystrokes when
4401 the normal layout translates alphabetic
4402 characters to non-ascii characters. */
4403 if (!modifier_set (VK_SHIFT))
4404 wParam += ('a' - 'A');
4405 msg = WM_CHAR;
4406 }
4407 else
4408 {
4409 /* Try to handle other keystrokes by determining the
4410 base character (ie. translating the base key plus
4411 shift modifier). */
4412 int add;
4413 int isdead = 0;
4414 KEY_EVENT_RECORD key;
4415
4416 key.bKeyDown = TRUE;
4417 key.wRepeatCount = 1;
4418 key.wVirtualKeyCode = wParam;
4419 key.wVirtualScanCode = (lParam & 0xFF0000) >> 16;
4420 key.uChar.AsciiChar = 0;
4421 key.dwControlKeyState = modifiers;
4422
4423 add = w32_kbd_patch_key (&key);
4424 /* 0 means an unrecognised keycode, negative means
4425 dead key. Ignore both. */
4426 while (--add >= 0)
4427 {
4428 /* Forward asciified character sequence. */
4429 post_character_message
4430 (hwnd, WM_CHAR, key.uChar.AsciiChar, lParam,
4431 w32_get_key_modifiers (wParam, lParam));
4432 w32_kbd_patch_key (&key);
4433 }
4434 return 0;
4435 }
4436 }
4437 else
4438 {
4439 /* Let TranslateMessage handle everything else. */
4440 windows_translate = 1;
4441 }
4442 }
4443 }
4444
4445 translate:
4446 if (windows_translate)
4447 {
4448 MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
4449
4450 windows_msg.time = GetMessageTime ();
4451 TranslateMessage (&windows_msg);
4452 goto dflt;
4453 }
4454
4455 /* Fall through */
4456
4457 case WM_SYSCHAR:
4458 case WM_CHAR:
4459 post_character_message (hwnd, msg, wParam, lParam,
4460 w32_get_key_modifiers (wParam, lParam));
4461 break;
4462
4463 /* Simulate middle mouse button events when left and right buttons
4464 are used together, but only if user has two button mouse. */
4465 case WM_LBUTTONDOWN:
4466 case WM_RBUTTONDOWN:
4467 if (XINT (Vw32_num_mouse_buttons) > 2)
4468 goto handle_plain_button;
4469
4470 {
4471 int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
4472 int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
4473
4474 if (button_state & this)
4475 return 0;
4476
4477 if (button_state == 0)
4478 SetCapture (hwnd);
4479
4480 button_state |= this;
4481
4482 if (button_state & other)
4483 {
4484 if (mouse_button_timer)
4485 {
4486 KillTimer (hwnd, mouse_button_timer);
4487 mouse_button_timer = 0;
4488
4489 /* Generate middle mouse event instead. */
4490 msg = WM_MBUTTONDOWN;
4491 button_state |= MMOUSE;
4492 }
4493 else if (button_state & MMOUSE)
4494 {
4495 /* Ignore button event if we've already generated a
4496 middle mouse down event. This happens if the
4497 user releases and press one of the two buttons
4498 after we've faked a middle mouse event. */
4499 return 0;
4500 }
4501 else
4502 {
4503 /* Flush out saved message. */
4504 post_msg (&saved_mouse_button_msg);
4505 }
4506 wmsg.dwModifiers = w32_get_modifiers ();
4507 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4508
4509 /* Clear message buffer. */
4510 saved_mouse_button_msg.msg.hwnd = 0;
4511 }
4512 else
4513 {
4514 /* Hold onto message for now. */
4515 mouse_button_timer =
4516 SetTimer (hwnd, MOUSE_BUTTON_ID,
4517 XINT (Vw32_mouse_button_tolerance), NULL);
4518 saved_mouse_button_msg.msg.hwnd = hwnd;
4519 saved_mouse_button_msg.msg.message = msg;
4520 saved_mouse_button_msg.msg.wParam = wParam;
4521 saved_mouse_button_msg.msg.lParam = lParam;
4522 saved_mouse_button_msg.msg.time = GetMessageTime ();
4523 saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
4524 }
4525 }
4526 return 0;
4527
4528 case WM_LBUTTONUP:
4529 case WM_RBUTTONUP:
4530 if (XINT (Vw32_num_mouse_buttons) > 2)
4531 goto handle_plain_button;
4532
4533 {
4534 int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
4535 int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
4536
4537 if ((button_state & this) == 0)
4538 return 0;
4539
4540 button_state &= ~this;
4541
4542 if (button_state & MMOUSE)
4543 {
4544 /* Only generate event when second button is released. */
4545 if ((button_state & other) == 0)
4546 {
4547 msg = WM_MBUTTONUP;
4548 button_state &= ~MMOUSE;
4549
4550 if (button_state) abort ();
4551 }
4552 else
4553 return 0;
4554 }
4555 else
4556 {
4557 /* Flush out saved message if necessary. */
4558 if (saved_mouse_button_msg.msg.hwnd)
4559 {
4560 post_msg (&saved_mouse_button_msg);
4561 }
4562 }
4563 wmsg.dwModifiers = w32_get_modifiers ();
4564 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4565
4566 /* Always clear message buffer and cancel timer. */
4567 saved_mouse_button_msg.msg.hwnd = 0;
4568 KillTimer (hwnd, mouse_button_timer);
4569 mouse_button_timer = 0;
4570
4571 if (button_state == 0)
4572 ReleaseCapture ();
4573 }
4574 return 0;
4575
4576 case WM_XBUTTONDOWN:
4577 case WM_XBUTTONUP:
4578 if (w32_pass_extra_mouse_buttons_to_system)
4579 goto dflt;
4580 /* else fall through and process them. */
4581 case WM_MBUTTONDOWN:
4582 case WM_MBUTTONUP:
4583 handle_plain_button:
4584 {
4585 BOOL up;
4586 int button;
4587
4588 if (parse_button (msg, HIWORD (wParam), &button, &up))
4589 {
4590 if (up) ReleaseCapture ();
4591 else SetCapture (hwnd);
4592 button = (button == 0) ? LMOUSE :
4593 ((button == 1) ? MMOUSE : RMOUSE);
4594 if (up)
4595 button_state &= ~button;
4596 else
4597 button_state |= button;
4598 }
4599 }
4600
4601 wmsg.dwModifiers = w32_get_modifiers ();
4602 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4603
4604 /* Need to return true for XBUTTON messages, false for others,
4605 to indicate that we processed the message. */
4606 return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
4607
4608 case WM_MOUSEMOVE:
4609 /* If the mouse has just moved into the frame, start tracking
4610 it, so we will be notified when it leaves the frame. Mouse
4611 tracking only works under W98 and NT4 and later. On earlier
4612 versions, there is no way of telling when the mouse leaves the
4613 frame, so we just have to put up with help-echo and mouse
4614 highlighting remaining while the frame is not active. */
4615 if (track_mouse_event_fn && !track_mouse_window)
4616 {
4617 TRACKMOUSEEVENT tme;
4618 tme.cbSize = sizeof (tme);
4619 tme.dwFlags = TME_LEAVE;
4620 tme.hwndTrack = hwnd;
4621
4622 track_mouse_event_fn (&tme);
4623 track_mouse_window = hwnd;
4624 }
4625 case WM_VSCROLL:
4626 if (XINT (Vw32_mouse_move_interval) <= 0
4627 || (msg == WM_MOUSEMOVE && button_state == 0))
4628 {
4629 wmsg.dwModifiers = w32_get_modifiers ();
4630 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4631 return 0;
4632 }
4633
4634 /* Hang onto mouse move and scroll messages for a bit, to avoid
4635 sending such events to Emacs faster than it can process them.
4636 If we get more events before the timer from the first message
4637 expires, we just replace the first message. */
4638
4639 if (saved_mouse_move_msg.msg.hwnd == 0)
4640 mouse_move_timer =
4641 SetTimer (hwnd, MOUSE_MOVE_ID,
4642 XINT (Vw32_mouse_move_interval), NULL);
4643
4644 /* Hold onto message for now. */
4645 saved_mouse_move_msg.msg.hwnd = hwnd;
4646 saved_mouse_move_msg.msg.message = msg;
4647 saved_mouse_move_msg.msg.wParam = wParam;
4648 saved_mouse_move_msg.msg.lParam = lParam;
4649 saved_mouse_move_msg.msg.time = GetMessageTime ();
4650 saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
4651
4652 return 0;
4653
4654 case WM_MOUSEWHEEL:
4655 wmsg.dwModifiers = w32_get_modifiers ();
4656 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4657 return 0;
4658
4659 case WM_DROPFILES:
4660 wmsg.dwModifiers = w32_get_modifiers ();
4661 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4662 return 0;
4663
4664 case WM_TIMER:
4665 /* Flush out saved messages if necessary. */
4666 if (wParam == mouse_button_timer)
4667 {
4668 if (saved_mouse_button_msg.msg.hwnd)
4669 {
4670 post_msg (&saved_mouse_button_msg);
4671 saved_mouse_button_msg.msg.hwnd = 0;
4672 }
4673 KillTimer (hwnd, mouse_button_timer);
4674 mouse_button_timer = 0;
4675 }
4676 else if (wParam == mouse_move_timer)
4677 {
4678 if (saved_mouse_move_msg.msg.hwnd)
4679 {
4680 post_msg (&saved_mouse_move_msg);
4681 saved_mouse_move_msg.msg.hwnd = 0;
4682 }
4683 KillTimer (hwnd, mouse_move_timer);
4684 mouse_move_timer = 0;
4685 }
4686 return 0;
4687
4688 case WM_NCACTIVATE:
4689 /* Windows doesn't send us focus messages when putting up and
4690 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
4691 The only indication we get that something happened is receiving
4692 this message afterwards. So this is a good time to reset our
4693 keyboard modifiers' state. */
4694 reset_modifiers ();
4695 goto dflt;
4696
4697 case WM_INITMENU:
4698 button_state = 0;
4699 ReleaseCapture ();
4700 /* We must ensure menu bar is fully constructed and up to date
4701 before allowing user interaction with it. To achieve this
4702 we send this message to the lisp thread and wait for a
4703 reply (whose value is not actually needed) to indicate that
4704 the menu bar is now ready for use, so we can now return.
4705
4706 To remain responsive in the meantime, we enter a nested message
4707 loop that can process all other messages.
4708
4709 However, we skip all this if the message results from calling
4710 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
4711 thread a message because it is blocked on us at this point. We
4712 set menubar_active before calling TrackPopupMenu to indicate
4713 this (there is no possibility of confusion with real menubar
4714 being active). */
4715
4716 f = x_window_to_frame (dpyinfo, hwnd);
4717 if (f
4718 && (f->output_data.w32->menubar_active
4719 /* We can receive this message even in the absence of a
4720 menubar (ie. when the system menu is activated) - in this
4721 case we do NOT want to forward the message, otherwise it
4722 will cause the menubar to suddenly appear when the user
4723 had requested it to be turned off! */
4724 || f->output_data.w32->menubar_widget == NULL))
4725 return 0;
4726
4727 {
4728 deferred_msg msg_buf;
4729
4730 /* Detect if message has already been deferred; in this case
4731 we cannot return any sensible value to ignore this. */
4732 if (find_deferred_msg (hwnd, msg) != NULL)
4733 abort ();
4734
4735 return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
4736 }
4737
4738 case WM_EXITMENULOOP:
4739 f = x_window_to_frame (dpyinfo, hwnd);
4740
4741 /* Free memory used by owner-drawn and help-echo strings. */
4742 w32_free_menu_strings (hwnd);
4743
4744 /* Indicate that menubar can be modified again. */
4745 if (f)
4746 f->output_data.w32->menubar_active = 0;
4747 goto dflt;
4748
4749 case WM_MENUSELECT:
4750 /* Direct handling of help_echo in menus. Should be safe now
4751 that we generate the help_echo by placing a help event in the
4752 keyboard buffer. */
4753 {
4754 HMENU menu = (HMENU) lParam;
4755 UINT menu_item = (UINT) LOWORD (wParam);
4756 UINT flags = (UINT) HIWORD (wParam);
4757
4758 w32_menu_display_help (hwnd, menu, menu_item, flags);
4759 }
4760 return 0;
4761
4762 case WM_MEASUREITEM:
4763 f = x_window_to_frame (dpyinfo, hwnd);
4764 if (f)
4765 {
4766 MEASUREITEMSTRUCT * pMis = (MEASUREITEMSTRUCT *) lParam;
4767
4768 if (pMis->CtlType == ODT_MENU)
4769 {
4770 /* Work out dimensions for popup menu titles. */
4771 char * title = (char *) pMis->itemData;
4772 HDC hdc = GetDC (hwnd);
4773 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
4774 LOGFONT menu_logfont;
4775 HFONT old_font;
4776 SIZE size;
4777
4778 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
4779 menu_logfont.lfWeight = FW_BOLD;
4780 menu_font = CreateFontIndirect (&menu_logfont);
4781 old_font = SelectObject (hdc, menu_font);
4782
4783 pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE);
4784 if (title)
4785 {
4786 GetTextExtentPoint32 (hdc, title, strlen (title), &size);
4787 pMis->itemWidth = size.cx;
4788 if (pMis->itemHeight < size.cy)
4789 pMis->itemHeight = size.cy;
4790 }
4791 else
4792 pMis->itemWidth = 0;
4793
4794 SelectObject (hdc, old_font);
4795 DeleteObject (menu_font);
4796 ReleaseDC (hwnd, hdc);
4797 return TRUE;
4798 }
4799 }
4800 return 0;
4801
4802 case WM_DRAWITEM:
4803 f = x_window_to_frame (dpyinfo, hwnd);
4804 if (f)
4805 {
4806 DRAWITEMSTRUCT * pDis = (DRAWITEMSTRUCT *) lParam;
4807
4808 if (pDis->CtlType == ODT_MENU)
4809 {
4810 /* Draw popup menu title. */
4811 char * title = (char *) pDis->itemData;
4812 if (title)
4813 {
4814 HDC hdc = pDis->hDC;
4815 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
4816 LOGFONT menu_logfont;
4817 HFONT old_font;
4818
4819 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
4820 menu_logfont.lfWeight = FW_BOLD;
4821 menu_font = CreateFontIndirect (&menu_logfont);
4822 old_font = SelectObject (hdc, menu_font);
4823
4824 /* Always draw title as if not selected. */
4825 ExtTextOut (hdc,
4826 pDis->rcItem.left
4827 + GetSystemMetrics (SM_CXMENUCHECK),
4828 pDis->rcItem.top,
4829 ETO_OPAQUE, &pDis->rcItem,
4830 title, strlen (title), NULL);
4831
4832 SelectObject (hdc, old_font);
4833 DeleteObject (menu_font);
4834 }
4835 return TRUE;
4836 }
4837 }
4838 return 0;
4839
4840 #if 0
4841 /* Still not right - can't distinguish between clicks in the
4842 client area of the frame from clicks forwarded from the scroll
4843 bars - may have to hook WM_NCHITTEST to remember the mouse
4844 position and then check if it is in the client area ourselves. */
4845 case WM_MOUSEACTIVATE:
4846 /* Discard the mouse click that activates a frame, allowing the
4847 user to click anywhere without changing point (or worse!).
4848 Don't eat mouse clicks on scrollbars though!! */
4849 if (LOWORD (lParam) == HTCLIENT )
4850 return MA_ACTIVATEANDEAT;
4851 goto dflt;
4852 #endif
4853
4854 case WM_MOUSELEAVE:
4855 /* No longer tracking mouse. */
4856 track_mouse_window = NULL;
4857
4858 case WM_ACTIVATEAPP:
4859 case WM_ACTIVATE:
4860 case WM_WINDOWPOSCHANGED:
4861 case WM_SHOWWINDOW:
4862 /* Inform lisp thread that a frame might have just been obscured
4863 or exposed, so should recheck visibility of all frames. */
4864 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4865 goto dflt;
4866
4867 case WM_SETFOCUS:
4868 dpyinfo->faked_key = 0;
4869 reset_modifiers ();
4870 register_hot_keys (hwnd);
4871 goto command;
4872 case WM_KILLFOCUS:
4873 unregister_hot_keys (hwnd);
4874 button_state = 0;
4875 ReleaseCapture ();
4876 /* Relinquish the system caret. */
4877 if (w32_system_caret_hwnd)
4878 {
4879 DestroyCaret ();
4880 w32_system_caret_hwnd = NULL;
4881 }
4882 case WM_MOVE:
4883 case WM_SIZE:
4884 case WM_COMMAND:
4885 command:
4886 wmsg.dwModifiers = w32_get_modifiers ();
4887 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4888 goto dflt;
4889
4890 case WM_CLOSE:
4891 wmsg.dwModifiers = w32_get_modifiers ();
4892 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4893 return 0;
4894
4895 case WM_WINDOWPOSCHANGING:
4896 /* Don't restrict the sizing of tip frames. */
4897 if (hwnd == tip_window)
4898 return 0;
4899 {
4900 WINDOWPLACEMENT wp;
4901 LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
4902
4903 wp.length = sizeof (WINDOWPLACEMENT);
4904 GetWindowPlacement (hwnd, &wp);
4905
4906 if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0)
4907 {
4908 RECT rect;
4909 int wdiff;
4910 int hdiff;
4911 DWORD font_width;
4912 DWORD line_height;
4913 DWORD internal_border;
4914 DWORD scrollbar_extra;
4915 RECT wr;
4916
4917 wp.length = sizeof(wp);
4918 GetWindowRect (hwnd, &wr);
4919
4920 enter_crit ();
4921
4922 font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
4923 line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
4924 internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
4925 scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
4926
4927 leave_crit ();
4928
4929 memset (&rect, 0, sizeof (rect));
4930 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
4931 GetMenu (hwnd) != NULL);
4932
4933 /* Force width and height of client area to be exact
4934 multiples of the character cell dimensions. */
4935 wdiff = (lppos->cx - (rect.right - rect.left)
4936 - 2 * internal_border - scrollbar_extra)
4937 % font_width;
4938 hdiff = (lppos->cy - (rect.bottom - rect.top)
4939 - 2 * internal_border)
4940 % line_height;
4941
4942 if (wdiff || hdiff)
4943 {
4944 /* For right/bottom sizing we can just fix the sizes.
4945 However for top/left sizing we will need to fix the X
4946 and Y positions as well. */
4947
4948 lppos->cx -= wdiff;
4949 lppos->cy -= hdiff;
4950
4951 if (wp.showCmd != SW_SHOWMAXIMIZED
4952 && (lppos->flags & SWP_NOMOVE) == 0)
4953 {
4954 if (lppos->x != wr.left || lppos->y != wr.top)
4955 {
4956 lppos->x += wdiff;
4957 lppos->y += hdiff;
4958 }
4959 else
4960 {
4961 lppos->flags |= SWP_NOMOVE;
4962 }
4963 }
4964
4965 return 0;
4966 }
4967 }
4968 }
4969
4970 goto dflt;
4971
4972 case WM_GETMINMAXINFO:
4973 /* Hack to correct bug that allows Emacs frames to be resized
4974 below the Minimum Tracking Size. */
4975 ((LPMINMAXINFO) lParam)->ptMinTrackSize.y++;
4976 /* Hack to allow resizing the Emacs frame above the screen size.
4977 Note that Windows 9x limits coordinates to 16-bits. */
4978 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767;
4979 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767;
4980 return 0;
4981
4982 case WM_EMACS_CREATESCROLLBAR:
4983 return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
4984 (struct scroll_bar *) lParam);
4985
4986 case WM_EMACS_SHOWWINDOW:
4987 return ShowWindow ((HWND) wParam, (WPARAM) lParam);
4988
4989 case WM_EMACS_SETFOREGROUND:
4990 {
4991 HWND foreground_window;
4992 DWORD foreground_thread, retval;
4993
4994 /* On NT 5.0, and apparently Windows 98, it is necessary to
4995 attach to the thread that currently has focus in order to
4996 pull the focus away from it. */
4997 foreground_window = GetForegroundWindow ();
4998 foreground_thread = GetWindowThreadProcessId (foreground_window, NULL);
4999 if (!foreground_window
5000 || foreground_thread == GetCurrentThreadId ()
5001 || !AttachThreadInput (GetCurrentThreadId (),
5002 foreground_thread, TRUE))
5003 foreground_thread = 0;
5004
5005 retval = SetForegroundWindow ((HWND) wParam);
5006
5007 /* Detach from the previous foreground thread. */
5008 if (foreground_thread)
5009 AttachThreadInput (GetCurrentThreadId (),
5010 foreground_thread, FALSE);
5011
5012 return retval;
5013 }
5014
5015 case WM_EMACS_SETWINDOWPOS:
5016 {
5017 WINDOWPOS * pos = (WINDOWPOS *) wParam;
5018 return SetWindowPos (hwnd, pos->hwndInsertAfter,
5019 pos->x, pos->y, pos->cx, pos->cy, pos->flags);
5020 }
5021
5022 case WM_EMACS_DESTROYWINDOW:
5023 DragAcceptFiles ((HWND) wParam, FALSE);
5024 return DestroyWindow ((HWND) wParam);
5025
5026 case WM_EMACS_DESTROY_CARET:
5027 w32_system_caret_hwnd = NULL;
5028 return DestroyCaret ();
5029
5030 case WM_EMACS_TRACK_CARET:
5031 /* If there is currently no system caret, create one. */
5032 if (w32_system_caret_hwnd == NULL)
5033 {
5034 w32_system_caret_hwnd = hwnd;
5035 CreateCaret (hwnd, NULL, w32_system_caret_width,
5036 w32_system_caret_height);
5037 }
5038 return SetCaretPos (w32_system_caret_x, w32_system_caret_y);
5039
5040 case WM_EMACS_TRACKPOPUPMENU:
5041 {
5042 UINT flags;
5043 POINT *pos;
5044 int retval;
5045 pos = (POINT *)lParam;
5046 flags = TPM_CENTERALIGN;
5047 if (button_state & LMOUSE)
5048 flags |= TPM_LEFTBUTTON;
5049 else if (button_state & RMOUSE)
5050 flags |= TPM_RIGHTBUTTON;
5051
5052 /* Remember we did a SetCapture on the initial mouse down event,
5053 so for safety, we make sure the capture is cancelled now. */
5054 ReleaseCapture ();
5055 button_state = 0;
5056
5057 /* Use menubar_active to indicate that WM_INITMENU is from
5058 TrackPopupMenu below, and should be ignored. */
5059 f = x_window_to_frame (dpyinfo, hwnd);
5060 if (f)
5061 f->output_data.w32->menubar_active = 1;
5062
5063 if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
5064 0, hwnd, NULL))
5065 {
5066 MSG amsg;
5067 /* Eat any mouse messages during popupmenu */
5068 while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
5069 PM_REMOVE));
5070 /* Get the menu selection, if any */
5071 if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE))
5072 {
5073 retval = LOWORD (amsg.wParam);
5074 }
5075 else
5076 {
5077 retval = 0;
5078 }
5079 }
5080 else
5081 {
5082 retval = -1;
5083 }
5084
5085 return retval;
5086 }
5087
5088 default:
5089 /* Check for messages registered at runtime. */
5090 if (msg == msh_mousewheel)
5091 {
5092 wmsg.dwModifiers = w32_get_modifiers ();
5093 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
5094 return 0;
5095 }
5096
5097 dflt:
5098 return DefWindowProc (hwnd, msg, wParam, lParam);
5099 }
5100
5101
5102 /* The most common default return code for handled messages is 0. */
5103 return 0;
5104 }
5105
5106 void
5107 my_create_window (f)
5108 struct frame * f;
5109 {
5110 MSG msg;
5111
5112 if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
5113 abort ();
5114 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
5115 }
5116
5117
5118 /* Create a tooltip window. Unlike my_create_window, we do not do this
5119 indirectly via the Window thread, as we do not need to process Window
5120 messages for the tooltip. Creating tooltips indirectly also creates
5121 deadlocks when tooltips are created for menu items. */
5122 void
5123 my_create_tip_window (f)
5124 struct frame *f;
5125 {
5126 RECT rect;
5127
5128 rect.left = rect.top = 0;
5129 rect.right = PIXEL_WIDTH (f);
5130 rect.bottom = PIXEL_HEIGHT (f);
5131
5132 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
5133 FRAME_EXTERNAL_MENU_BAR (f));
5134
5135 tip_window = FRAME_W32_WINDOW (f)
5136 = CreateWindow (EMACS_CLASS,
5137 f->namebuf,
5138 f->output_data.w32->dwStyle,
5139 f->output_data.w32->left_pos,
5140 f->output_data.w32->top_pos,
5141 rect.right - rect.left,
5142 rect.bottom - rect.top,
5143 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
5144 NULL,
5145 hinst,
5146 NULL);
5147
5148 if (tip_window)
5149 {
5150 SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
5151 SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
5152 SetWindowLong (tip_window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
5153 SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
5154
5155 /* Tip frames have no scrollbars. */
5156 SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
5157
5158 /* Do this to discard the default setting specified by our parent. */
5159 ShowWindow (tip_window, SW_HIDE);
5160 }
5161 }
5162
5163
5164 /* Create and set up the w32 window for frame F. */
5165
5166 static void
5167 w32_window (f, window_prompting, minibuffer_only)
5168 struct frame *f;
5169 long window_prompting;
5170 int minibuffer_only;
5171 {
5172 BLOCK_INPUT;
5173
5174 /* Use the resource name as the top-level window name
5175 for looking up resources. Make a non-Lisp copy
5176 for the window manager, so GC relocation won't bother it.
5177
5178 Elsewhere we specify the window name for the window manager. */
5179
5180 {
5181 char *str = (char *) XSTRING (Vx_resource_name)->data;
5182 f->namebuf = (char *) xmalloc (strlen (str) + 1);
5183 strcpy (f->namebuf, str);
5184 }
5185
5186 my_create_window (f);
5187
5188 validate_x_resource_name ();
5189
5190 /* x_set_name normally ignores requests to set the name if the
5191 requested name is the same as the current name. This is the one
5192 place where that assumption isn't correct; f->name is set, but
5193 the server hasn't been told. */
5194 {
5195 Lisp_Object name;
5196 int explicit = f->explicit_name;
5197
5198 f->explicit_name = 0;
5199 name = f->name;
5200 f->name = Qnil;
5201 x_set_name (f, name, explicit);
5202 }
5203
5204 UNBLOCK_INPUT;
5205
5206 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
5207 initialize_frame_menubar (f);
5208
5209 if (FRAME_W32_WINDOW (f) == 0)
5210 error ("Unable to create window");
5211 }
5212
5213 /* Handle the icon stuff for this window. Perhaps later we might
5214 want an x_set_icon_position which can be called interactively as
5215 well. */
5216
5217 static void
5218 x_icon (f, parms)
5219 struct frame *f;
5220 Lisp_Object parms;
5221 {
5222 Lisp_Object icon_x, icon_y;
5223
5224 /* Set the position of the icon. Note that Windows 95 groups all
5225 icons in the tray. */
5226 icon_x = w32_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
5227 icon_y = w32_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
5228 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
5229 {
5230 CHECK_NUMBER (icon_x);
5231 CHECK_NUMBER (icon_y);
5232 }
5233 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
5234 error ("Both left and top icon corners of icon must be specified");
5235
5236 BLOCK_INPUT;
5237
5238 if (! EQ (icon_x, Qunbound))
5239 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
5240
5241 #if 0 /* TODO */
5242 /* Start up iconic or window? */
5243 x_wm_set_window_state
5244 (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
5245 ? IconicState
5246 : NormalState));
5247
5248 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
5249 ? f->icon_name
5250 : f->name))->data);
5251 #endif
5252
5253 UNBLOCK_INPUT;
5254 }
5255
5256
5257 static void
5258 x_make_gc (f)
5259 struct frame *f;
5260 {
5261 XGCValues gc_values;
5262
5263 BLOCK_INPUT;
5264
5265 /* Create the GC's of this frame.
5266 Note that many default values are used. */
5267
5268 /* Normal video */
5269 gc_values.font = f->output_data.w32->font;
5270
5271 /* Cursor has cursor-color background, background-color foreground. */
5272 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
5273 gc_values.background = f->output_data.w32->cursor_pixel;
5274 f->output_data.w32->cursor_gc
5275 = XCreateGC (NULL, FRAME_W32_WINDOW (f),
5276 (GCFont | GCForeground | GCBackground),
5277 &gc_values);
5278
5279 /* Reliefs. */
5280 f->output_data.w32->white_relief.gc = 0;
5281 f->output_data.w32->black_relief.gc = 0;
5282
5283 UNBLOCK_INPUT;
5284 }
5285
5286
5287 /* Handler for signals raised during x_create_frame and
5288 x_create_top_frame. FRAME is the frame which is partially
5289 constructed. */
5290
5291 static Lisp_Object
5292 unwind_create_frame (frame)
5293 Lisp_Object frame;
5294 {
5295 struct frame *f = XFRAME (frame);
5296
5297 /* If frame is ``official'', nothing to do. */
5298 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
5299 {
5300 #ifdef GLYPH_DEBUG
5301 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5302 #endif
5303
5304 x_free_frame_resources (f);
5305
5306 /* Check that reference counts are indeed correct. */
5307 xassert (dpyinfo->reference_count == dpyinfo_refcount);
5308 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
5309
5310 return Qt;
5311 }
5312
5313 return Qnil;
5314 }
5315
5316
5317 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
5318 1, 1, 0,
5319 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
5320 Returns an Emacs frame object.
5321 ALIST is an alist of frame parameters.
5322 If the parameters specify that the frame should not have a minibuffer,
5323 and do not specify a specific minibuffer window to use,
5324 then `default-minibuffer-frame' must be a frame whose minibuffer can
5325 be shared by the new frame.
5326
5327 This function is an internal primitive--use `make-frame' instead. */)
5328 (parms)
5329 Lisp_Object parms;
5330 {
5331 struct frame *f;
5332 Lisp_Object frame, tem;
5333 Lisp_Object name;
5334 int minibuffer_only = 0;
5335 long window_prompting = 0;
5336 int width, height;
5337 int count = BINDING_STACK_SIZE ();
5338 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5339 Lisp_Object display;
5340 struct w32_display_info *dpyinfo = NULL;
5341 Lisp_Object parent;
5342 struct kboard *kb;
5343
5344 check_w32 ();
5345
5346 /* Use this general default value to start with
5347 until we know if this frame has a specified name. */
5348 Vx_resource_name = Vinvocation_name;
5349
5350 display = w32_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
5351 if (EQ (display, Qunbound))
5352 display = Qnil;
5353 dpyinfo = check_x_display_info (display);
5354 #ifdef MULTI_KBOARD
5355 kb = dpyinfo->kboard;
5356 #else
5357 kb = &the_only_kboard;
5358 #endif
5359
5360 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
5361 if (!STRINGP (name)
5362 && ! EQ (name, Qunbound)
5363 && ! NILP (name))
5364 error ("Invalid frame name--not a string or nil");
5365
5366 if (STRINGP (name))
5367 Vx_resource_name = name;
5368
5369 /* See if parent window is specified. */
5370 parent = w32_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
5371 if (EQ (parent, Qunbound))
5372 parent = Qnil;
5373 if (! NILP (parent))
5374 CHECK_NUMBER (parent);
5375
5376 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
5377 /* No need to protect DISPLAY because that's not used after passing
5378 it to make_frame_without_minibuffer. */
5379 frame = Qnil;
5380 GCPRO4 (parms, parent, name, frame);
5381 tem = w32_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
5382 RES_TYPE_SYMBOL);
5383 if (EQ (tem, Qnone) || NILP (tem))
5384 f = make_frame_without_minibuffer (Qnil, kb, display);
5385 else if (EQ (tem, Qonly))
5386 {
5387 f = make_minibuffer_frame ();
5388 minibuffer_only = 1;
5389 }
5390 else if (WINDOWP (tem))
5391 f = make_frame_without_minibuffer (tem, kb, display);
5392 else
5393 f = make_frame (1);
5394
5395 XSETFRAME (frame, f);
5396
5397 /* Note that Windows does support scroll bars. */
5398 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
5399 /* By default, make scrollbars the system standard width. */
5400 f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL);
5401
5402 f->output_method = output_w32;
5403 f->output_data.w32 =
5404 (struct w32_output *) xmalloc (sizeof (struct w32_output));
5405 bzero (f->output_data.w32, sizeof (struct w32_output));
5406 FRAME_FONTSET (f) = -1;
5407 record_unwind_protect (unwind_create_frame, frame);
5408
5409 f->icon_name
5410 = w32_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
5411 if (! STRINGP (f->icon_name))
5412 f->icon_name = Qnil;
5413
5414 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
5415 #ifdef MULTI_KBOARD
5416 FRAME_KBOARD (f) = kb;
5417 #endif
5418
5419 /* Specify the parent under which to make this window. */
5420
5421 if (!NILP (parent))
5422 {
5423 f->output_data.w32->parent_desc = (Window) XFASTINT (parent);
5424 f->output_data.w32->explicit_parent = 1;
5425 }
5426 else
5427 {
5428 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5429 f->output_data.w32->explicit_parent = 0;
5430 }
5431
5432 /* Set the name; the functions to which we pass f expect the name to
5433 be set. */
5434 if (EQ (name, Qunbound) || NILP (name))
5435 {
5436 f->name = build_string (dpyinfo->w32_id_name);
5437 f->explicit_name = 0;
5438 }
5439 else
5440 {
5441 f->name = name;
5442 f->explicit_name = 1;
5443 /* use the frame's title when getting resources for this frame. */
5444 specbind (Qx_resource_name, name);
5445 }
5446
5447 /* Extract the window parameters from the supplied values
5448 that are needed to determine window geometry. */
5449 {
5450 Lisp_Object font;
5451
5452 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
5453
5454 BLOCK_INPUT;
5455 /* First, try whatever font the caller has specified. */
5456 if (STRINGP (font))
5457 {
5458 tem = Fquery_fontset (font, Qnil);
5459 if (STRINGP (tem))
5460 font = x_new_fontset (f, XSTRING (tem)->data);
5461 else
5462 font = x_new_font (f, XSTRING (font)->data);
5463 }
5464 /* Try out a font which we hope has bold and italic variations. */
5465 if (!STRINGP (font))
5466 font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
5467 if (! STRINGP (font))
5468 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
5469 /* If those didn't work, look for something which will at least work. */
5470 if (! STRINGP (font))
5471 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
5472 UNBLOCK_INPUT;
5473 if (! STRINGP (font))
5474 font = build_string ("Fixedsys");
5475
5476 x_default_parameter (f, parms, Qfont, font,
5477 "font", "Font", RES_TYPE_STRING);
5478 }
5479
5480 x_default_parameter (f, parms, Qborder_width, make_number (2),
5481 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
5482 /* This defaults to 2 in order to match xterm. We recognize either
5483 internalBorderWidth or internalBorder (which is what xterm calls
5484 it). */
5485 if (NILP (Fassq (Qinternal_border_width, parms)))
5486 {
5487 Lisp_Object value;
5488
5489 value = w32_get_arg (parms, Qinternal_border_width,
5490 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
5491 if (! EQ (value, Qunbound))
5492 parms = Fcons (Fcons (Qinternal_border_width, value),
5493 parms);
5494 }
5495 /* Default internalBorderWidth to 0 on Windows to match other programs. */
5496 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
5497 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
5498 x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
5499 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
5500
5501 /* Also do the stuff which must be set before the window exists. */
5502 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5503 "foreground", "Foreground", RES_TYPE_STRING);
5504 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5505 "background", "Background", RES_TYPE_STRING);
5506 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5507 "pointerColor", "Foreground", RES_TYPE_STRING);
5508 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
5509 "cursorColor", "Foreground", RES_TYPE_STRING);
5510 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5511 "borderColor", "BorderColor", RES_TYPE_STRING);
5512 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
5513 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
5514 x_default_parameter (f, parms, Qline_spacing, Qnil,
5515 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
5516 x_default_parameter (f, parms, Qleft_fringe, Qnil,
5517 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
5518 x_default_parameter (f, parms, Qright_fringe, Qnil,
5519 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
5520
5521
5522 /* Init faces before x_default_parameter is called for scroll-bar
5523 parameters because that function calls x_set_scroll_bar_width,
5524 which calls change_frame_size, which calls Fset_window_buffer,
5525 which runs hooks, which call Fvertical_motion. At the end, we
5526 end up in init_iterator with a null face cache, which should not
5527 happen. */
5528 init_frame_faces (f);
5529
5530 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
5531 "menuBar", "MenuBar", RES_TYPE_NUMBER);
5532 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
5533 "toolBar", "ToolBar", RES_TYPE_NUMBER);
5534 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
5535 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
5536 x_default_parameter (f, parms, Qtitle, Qnil,
5537 "title", "Title", RES_TYPE_STRING);
5538
5539 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
5540 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5541
5542 /* Add the tool-bar height to the initial frame height so that the
5543 user gets a text display area of the size he specified with -g or
5544 via .Xdefaults. Later changes of the tool-bar height don't
5545 change the frame size. This is done so that users can create
5546 tall Emacs frames without having to guess how tall the tool-bar
5547 will get. */
5548 if (FRAME_TOOL_BAR_LINES (f))
5549 {
5550 int margin, relief, bar_height;
5551
5552 relief = (tool_bar_button_relief >= 0
5553 ? tool_bar_button_relief
5554 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
5555
5556 if (INTEGERP (Vtool_bar_button_margin)
5557 && XINT (Vtool_bar_button_margin) > 0)
5558 margin = XFASTINT (Vtool_bar_button_margin);
5559 else if (CONSP (Vtool_bar_button_margin)
5560 && INTEGERP (XCDR (Vtool_bar_button_margin))
5561 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
5562 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
5563 else
5564 margin = 0;
5565
5566 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5567 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
5568 }
5569
5570 window_prompting = x_figure_window_size (f, parms);
5571
5572 if (window_prompting & XNegative)
5573 {
5574 if (window_prompting & YNegative)
5575 f->output_data.w32->win_gravity = SouthEastGravity;
5576 else
5577 f->output_data.w32->win_gravity = NorthEastGravity;
5578 }
5579 else
5580 {
5581 if (window_prompting & YNegative)
5582 f->output_data.w32->win_gravity = SouthWestGravity;
5583 else
5584 f->output_data.w32->win_gravity = NorthWestGravity;
5585 }
5586
5587 f->output_data.w32->size_hint_flags = window_prompting;
5588
5589 tem = w32_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
5590 f->no_split = minibuffer_only || EQ (tem, Qt);
5591
5592 w32_window (f, window_prompting, minibuffer_only);
5593 x_icon (f, parms);
5594
5595 x_make_gc (f);
5596
5597 /* Now consider the frame official. */
5598 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
5599 Vframe_list = Fcons (frame, Vframe_list);
5600
5601 /* We need to do this after creating the window, so that the
5602 icon-creation functions can say whose icon they're describing. */
5603 x_default_parameter (f, parms, Qicon_type, Qnil,
5604 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
5605
5606 x_default_parameter (f, parms, Qauto_raise, Qnil,
5607 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5608 x_default_parameter (f, parms, Qauto_lower, Qnil,
5609 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5610 x_default_parameter (f, parms, Qcursor_type, Qbox,
5611 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5612 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
5613 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
5614
5615 /* Dimensions, especially f->height, must be done via change_frame_size.
5616 Change will not be effected unless different from the current
5617 f->height. */
5618 width = f->width;
5619 height = f->height;
5620
5621 f->height = 0;
5622 SET_FRAME_WIDTH (f, 0);
5623 change_frame_size (f, height, width, 1, 0, 0);
5624
5625 /* Tell the server what size and position, etc, we want, and how
5626 badly we want them. This should be done after we have the menu
5627 bar so that its size can be taken into account. */
5628 BLOCK_INPUT;
5629 x_wm_set_size_hint (f, window_prompting, 0);
5630 UNBLOCK_INPUT;
5631
5632 /* Set up faces after all frame parameters are known. This call
5633 also merges in face attributes specified for new frames. If we
5634 don't do this, the `menu' face for instance won't have the right
5635 colors, and the menu bar won't appear in the specified colors for
5636 new frames. */
5637 call1 (Qface_set_after_frame_default, frame);
5638
5639 /* Make the window appear on the frame and enable display, unless
5640 the caller says not to. However, with explicit parent, Emacs
5641 cannot control visibility, so don't try. */
5642 if (! f->output_data.w32->explicit_parent)
5643 {
5644 Lisp_Object visibility;
5645
5646 visibility = w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
5647 if (EQ (visibility, Qunbound))
5648 visibility = Qt;
5649
5650 if (EQ (visibility, Qicon))
5651 x_iconify_frame (f);
5652 else if (! NILP (visibility))
5653 x_make_frame_visible (f);
5654 else
5655 /* Must have been Qnil. */
5656 ;
5657 }
5658 UNGCPRO;
5659
5660 /* Make sure windows on this frame appear in calls to next-window
5661 and similar functions. */
5662 Vwindow_list = Qnil;
5663
5664 return unbind_to (count, frame);
5665 }
5666
5667 /* FRAME is used only to get a handle on the X display. We don't pass the
5668 display info directly because we're called from frame.c, which doesn't
5669 know about that structure. */
5670 Lisp_Object
5671 x_get_focus_frame (frame)
5672 struct frame *frame;
5673 {
5674 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
5675 Lisp_Object xfocus;
5676 if (! dpyinfo->w32_focus_frame)
5677 return Qnil;
5678
5679 XSETFRAME (xfocus, dpyinfo->w32_focus_frame);
5680 return xfocus;
5681 }
5682
5683 DEFUN ("w32-focus-frame", Fw32_focus_frame, Sw32_focus_frame, 1, 1, 0,
5684 doc: /* Give FRAME input focus, raising to foreground if necessary. */)
5685 (frame)
5686 Lisp_Object frame;
5687 {
5688 x_focus_on_frame (check_x_frame (frame));
5689 return Qnil;
5690 }
5691
5692 \f
5693 /* Return the charset portion of a font name. */
5694 char * xlfd_charset_of_font (char * fontname)
5695 {
5696 char *charset, *encoding;
5697
5698 encoding = strrchr(fontname, '-');
5699 if (!encoding || encoding == fontname)
5700 return NULL;
5701
5702 for (charset = encoding - 1; charset >= fontname; charset--)
5703 if (*charset == '-')
5704 break;
5705
5706 if (charset == fontname || strcmp(charset, "-*-*") == 0)
5707 return NULL;
5708
5709 return charset + 1;
5710 }
5711
5712 struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
5713 int size, char* filename);
5714 static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names);
5715 static BOOL w32_to_x_font (LOGFONT * lplf, char * lpxstr, int len,
5716 char * charset);
5717 static BOOL x_to_w32_font (char *lpxstr, LOGFONT *lplogfont);
5718
5719 static struct font_info *
5720 w32_load_system_font (f,fontname,size)
5721 struct frame *f;
5722 char * fontname;
5723 int size;
5724 {
5725 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5726 Lisp_Object font_names;
5727
5728 /* Get a list of all the fonts that match this name. Once we
5729 have a list of matching fonts, we compare them against the fonts
5730 we already have loaded by comparing names. */
5731 font_names = w32_list_fonts (f, build_string (fontname), size, 100);
5732
5733 if (!NILP (font_names))
5734 {
5735 Lisp_Object tail;
5736 int i;
5737
5738 /* First check if any are already loaded, as that is cheaper
5739 than loading another one. */
5740 for (i = 0; i < dpyinfo->n_fonts; i++)
5741 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
5742 if (dpyinfo->font_table[i].name
5743 && (!strcmp (dpyinfo->font_table[i].name,
5744 XSTRING (XCAR (tail))->data)
5745 || !strcmp (dpyinfo->font_table[i].full_name,
5746 XSTRING (XCAR (tail))->data)))
5747 return (dpyinfo->font_table + i);
5748
5749 fontname = (char *) XSTRING (XCAR (font_names))->data;
5750 }
5751 else if (w32_strict_fontnames)
5752 {
5753 /* If EnumFontFamiliesEx was available, we got a full list of
5754 fonts back so stop now to avoid the possibility of loading a
5755 random font. If we had to fall back to EnumFontFamilies, the
5756 list is incomplete, so continue whether the font we want was
5757 listed or not. */
5758 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
5759 FARPROC enum_font_families_ex
5760 = GetProcAddress (gdi32, "EnumFontFamiliesExA");
5761 if (enum_font_families_ex)
5762 return NULL;
5763 }
5764
5765 /* Load the font and add it to the table. */
5766 {
5767 char *full_name, *encoding, *charset;
5768 XFontStruct *font;
5769 struct font_info *fontp;
5770 LOGFONT lf;
5771 BOOL ok;
5772 int codepage;
5773 int i;
5774
5775 if (!fontname || !x_to_w32_font (fontname, &lf))
5776 return (NULL);
5777
5778 if (!*lf.lfFaceName)
5779 /* If no name was specified for the font, we get a random font
5780 from CreateFontIndirect - this is not particularly
5781 desirable, especially since CreateFontIndirect does not
5782 fill out the missing name in lf, so we never know what we
5783 ended up with. */
5784 return NULL;
5785
5786 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
5787 bzero (font, sizeof (*font));
5788
5789 /* Set bdf to NULL to indicate that this is a Windows font. */
5790 font->bdf = NULL;
5791
5792 BLOCK_INPUT;
5793
5794 font->hfont = CreateFontIndirect (&lf);
5795
5796 if (font->hfont == NULL)
5797 {
5798 ok = FALSE;
5799 }
5800 else
5801 {
5802 HDC hdc;
5803 HANDLE oldobj;
5804
5805 codepage = w32_codepage_for_font (fontname);
5806
5807 hdc = GetDC (dpyinfo->root_window);
5808 oldobj = SelectObject (hdc, font->hfont);
5809
5810 ok = GetTextMetrics (hdc, &font->tm);
5811 if (codepage == CP_UNICODE)
5812 font->double_byte_p = 1;
5813 else
5814 {
5815 /* Unfortunately, some fonts (eg. MingLiU, a big5 ttf font)
5816 don't report themselves as double byte fonts, when
5817 patently they are. So instead of trusting
5818 GetFontLanguageInfo, we check the properties of the
5819 codepage directly, since that is ultimately what we are
5820 working from anyway. */
5821 /* font->double_byte_p = GetFontLanguageInfo(hdc) & GCP_DBCS; */
5822 CPINFO cpi = {0};
5823 GetCPInfo (codepage, &cpi);
5824 font->double_byte_p = cpi.MaxCharSize > 1;
5825 }
5826
5827 SelectObject (hdc, oldobj);
5828 ReleaseDC (dpyinfo->root_window, hdc);
5829 /* Fill out details in lf according to the font that was
5830 actually loaded. */
5831 lf.lfHeight = font->tm.tmInternalLeading - font->tm.tmHeight;
5832 lf.lfWidth = font->tm.tmAveCharWidth;
5833 lf.lfWeight = font->tm.tmWeight;
5834 lf.lfItalic = font->tm.tmItalic;
5835 lf.lfCharSet = font->tm.tmCharSet;
5836 lf.lfPitchAndFamily = ((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
5837 ? VARIABLE_PITCH : FIXED_PITCH);
5838 lf.lfOutPrecision = ((font->tm.tmPitchAndFamily & TMPF_VECTOR)
5839 ? OUT_STROKE_PRECIS : OUT_STRING_PRECIS);
5840
5841 w32_cache_char_metrics (font);
5842 }
5843
5844 UNBLOCK_INPUT;
5845
5846 if (!ok)
5847 {
5848 w32_unload_font (dpyinfo, font);
5849 return (NULL);
5850 }
5851
5852 /* Find a free slot in the font table. */
5853 for (i = 0; i < dpyinfo->n_fonts; ++i)
5854 if (dpyinfo->font_table[i].name == NULL)
5855 break;
5856
5857 /* If no free slot found, maybe enlarge the font table. */
5858 if (i == dpyinfo->n_fonts
5859 && dpyinfo->n_fonts == dpyinfo->font_table_size)
5860 {
5861 int sz;
5862 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
5863 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
5864 dpyinfo->font_table
5865 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
5866 }
5867
5868 fontp = dpyinfo->font_table + i;
5869 if (i == dpyinfo->n_fonts)
5870 ++dpyinfo->n_fonts;
5871
5872 /* Now fill in the slots of *FONTP. */
5873 BLOCK_INPUT;
5874 fontp->font = font;
5875 fontp->font_idx = i;
5876 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
5877 bcopy (fontname, fontp->name, strlen (fontname) + 1);
5878
5879 charset = xlfd_charset_of_font (fontname);
5880
5881 /* Cache the W32 codepage for a font. This makes w32_encode_char
5882 (called for every glyph during redisplay) much faster. */
5883 fontp->codepage = codepage;
5884
5885 /* Work out the font's full name. */
5886 full_name = (char *)xmalloc (100);
5887 if (full_name && w32_to_x_font (&lf, full_name, 100, charset))
5888 fontp->full_name = full_name;
5889 else
5890 {
5891 /* If all else fails - just use the name we used to load it. */
5892 xfree (full_name);
5893 fontp->full_name = fontp->name;
5894 }
5895
5896 fontp->size = FONT_WIDTH (font);
5897 fontp->height = FONT_HEIGHT (font);
5898
5899 /* The slot `encoding' specifies how to map a character
5900 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
5901 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
5902 (0:0x20..0x7F, 1:0xA0..0xFF,
5903 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
5904 2:0xA020..0xFF7F). For the moment, we don't know which charset
5905 uses this font. So, we set information in fontp->encoding[1]
5906 which is never used by any charset. If mapping can't be
5907 decided, set FONT_ENCODING_NOT_DECIDED. */
5908
5909 /* SJIS fonts need to be set to type 4, all others seem to work as
5910 type FONT_ENCODING_NOT_DECIDED. */
5911 encoding = strrchr (fontp->name, '-');
5912 if (encoding && stricmp (encoding+1, "sjis") == 0)
5913 fontp->encoding[1] = 4;
5914 else
5915 fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
5916
5917 /* The following three values are set to 0 under W32, which is
5918 what they get set to if XGetFontProperty fails under X. */
5919 fontp->baseline_offset = 0;
5920 fontp->relative_compose = 0;
5921 fontp->default_ascent = 0;
5922
5923 /* Set global flag fonts_changed_p to non-zero if the font loaded
5924 has a character with a smaller width than any other character
5925 before, or if the font loaded has a smalle>r height than any
5926 other font loaded before. If this happens, it will make a
5927 glyph matrix reallocation necessary. */
5928 fonts_changed_p = x_compute_min_glyph_bounds (f);
5929 UNBLOCK_INPUT;
5930 return fontp;
5931 }
5932 }
5933
5934 /* Load font named FONTNAME of size SIZE for frame F, and return a
5935 pointer to the structure font_info while allocating it dynamically.
5936 If loading fails, return NULL. */
5937 struct font_info *
5938 w32_load_font (f,fontname,size)
5939 struct frame *f;
5940 char * fontname;
5941 int size;
5942 {
5943 Lisp_Object bdf_fonts;
5944 struct font_info *retval = NULL;
5945
5946 bdf_fonts = w32_list_bdf_fonts (build_string (fontname), 1);
5947
5948 while (!retval && CONSP (bdf_fonts))
5949 {
5950 char *bdf_name, *bdf_file;
5951 Lisp_Object bdf_pair;
5952
5953 bdf_name = XSTRING (XCAR (bdf_fonts))->data;
5954 bdf_pair = Fassoc (XCAR (bdf_fonts), Vw32_bdf_filename_alist);
5955 bdf_file = XSTRING (XCDR (bdf_pair))->data;
5956
5957 retval = w32_load_bdf_font (f, bdf_name, size, bdf_file);
5958
5959 bdf_fonts = XCDR (bdf_fonts);
5960 }
5961
5962 if (retval)
5963 return retval;
5964
5965 return w32_load_system_font(f, fontname, size);
5966 }
5967
5968
5969 void
5970 w32_unload_font (dpyinfo, font)
5971 struct w32_display_info *dpyinfo;
5972 XFontStruct * font;
5973 {
5974 if (font)
5975 {
5976 if (font->per_char) xfree (font->per_char);
5977 if (font->bdf) w32_free_bdf_font (font->bdf);
5978
5979 if (font->hfont) DeleteObject(font->hfont);
5980 xfree (font);
5981 }
5982 }
5983
5984 /* The font conversion stuff between x and w32 */
5985
5986 /* X font string is as follows (from faces.el)
5987 * (let ((- "[-?]")
5988 * (foundry "[^-]+")
5989 * (family "[^-]+")
5990 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
5991 * (weight\? "\\([^-]*\\)") ; 1
5992 * (slant "\\([ior]\\)") ; 2
5993 * (slant\? "\\([^-]?\\)") ; 2
5994 * (swidth "\\([^-]*\\)") ; 3
5995 * (adstyle "[^-]*") ; 4
5996 * (pixelsize "[0-9]+")
5997 * (pointsize "[0-9][0-9]+")
5998 * (resx "[0-9][0-9]+")
5999 * (resy "[0-9][0-9]+")
6000 * (spacing "[cmp?*]")
6001 * (avgwidth "[0-9]+")
6002 * (registry "[^-]+")
6003 * (encoding "[^-]+")
6004 * )
6005 */
6006
6007 static LONG
6008 x_to_w32_weight (lpw)
6009 char * lpw;
6010 {
6011 if (!lpw) return (FW_DONTCARE);
6012
6013 if (stricmp (lpw,"heavy") == 0) return FW_HEAVY;
6014 else if (stricmp (lpw,"extrabold") == 0) return FW_EXTRABOLD;
6015 else if (stricmp (lpw,"bold") == 0) return FW_BOLD;
6016 else if (stricmp (lpw,"demibold") == 0) return FW_SEMIBOLD;
6017 else if (stricmp (lpw,"semibold") == 0) return FW_SEMIBOLD;
6018 else if (stricmp (lpw,"medium") == 0) return FW_MEDIUM;
6019 else if (stricmp (lpw,"normal") == 0) return FW_NORMAL;
6020 else if (stricmp (lpw,"light") == 0) return FW_LIGHT;
6021 else if (stricmp (lpw,"extralight") == 0) return FW_EXTRALIGHT;
6022 else if (stricmp (lpw,"thin") == 0) return FW_THIN;
6023 else
6024 return FW_DONTCARE;
6025 }
6026
6027
6028 static char *
6029 w32_to_x_weight (fnweight)
6030 int fnweight;
6031 {
6032 if (fnweight >= FW_HEAVY) return "heavy";
6033 if (fnweight >= FW_EXTRABOLD) return "extrabold";
6034 if (fnweight >= FW_BOLD) return "bold";
6035 if (fnweight >= FW_SEMIBOLD) return "demibold";
6036 if (fnweight >= FW_MEDIUM) return "medium";
6037 if (fnweight >= FW_NORMAL) return "normal";
6038 if (fnweight >= FW_LIGHT) return "light";
6039 if (fnweight >= FW_EXTRALIGHT) return "extralight";
6040 if (fnweight >= FW_THIN) return "thin";
6041 else
6042 return "*";
6043 }
6044
6045 static LONG
6046 x_to_w32_charset (lpcs)
6047 char * lpcs;
6048 {
6049 Lisp_Object this_entry, w32_charset;
6050 char *charset;
6051 int len = strlen (lpcs);
6052
6053 /* Support "*-#nnn" format for unknown charsets. */
6054 if (strncmp (lpcs, "*-#", 3) == 0)
6055 return atoi (lpcs + 3);
6056
6057 /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5". */
6058 charset = alloca (len + 1);
6059 strcpy (charset, lpcs);
6060 lpcs = strchr (charset, '*');
6061 if (lpcs)
6062 *lpcs = 0;
6063
6064 /* Look through w32-charset-info-alist for the character set.
6065 Format of each entry is
6066 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
6067 */
6068 this_entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
6069
6070 if (NILP(this_entry))
6071 {
6072 /* At startup, we want iso8859-1 fonts to come up properly. */
6073 if (stricmp(charset, "iso8859-1") == 0)
6074 return ANSI_CHARSET;
6075 else
6076 return DEFAULT_CHARSET;
6077 }
6078
6079 w32_charset = Fcar (Fcdr (this_entry));
6080
6081 // Translate Lisp symbol to number.
6082 if (w32_charset == Qw32_charset_ansi)
6083 return ANSI_CHARSET;
6084 if (w32_charset == Qw32_charset_symbol)
6085 return SYMBOL_CHARSET;
6086 if (w32_charset == Qw32_charset_shiftjis)
6087 return SHIFTJIS_CHARSET;
6088 if (w32_charset == Qw32_charset_hangeul)
6089 return HANGEUL_CHARSET;
6090 if (w32_charset == Qw32_charset_chinesebig5)
6091 return CHINESEBIG5_CHARSET;
6092 if (w32_charset == Qw32_charset_gb2312)
6093 return GB2312_CHARSET;
6094 if (w32_charset == Qw32_charset_oem)
6095 return OEM_CHARSET;
6096 #ifdef JOHAB_CHARSET
6097 if (w32_charset == Qw32_charset_johab)
6098 return JOHAB_CHARSET;
6099 if (w32_charset == Qw32_charset_easteurope)
6100 return EASTEUROPE_CHARSET;
6101 if (w32_charset == Qw32_charset_turkish)
6102 return TURKISH_CHARSET;
6103 if (w32_charset == Qw32_charset_baltic)
6104 return BALTIC_CHARSET;
6105 if (w32_charset == Qw32_charset_russian)
6106 return RUSSIAN_CHARSET;
6107 if (w32_charset == Qw32_charset_arabic)
6108 return ARABIC_CHARSET;
6109 if (w32_charset == Qw32_charset_greek)
6110 return GREEK_CHARSET;
6111 if (w32_charset == Qw32_charset_hebrew)
6112 return HEBREW_CHARSET;
6113 if (w32_charset == Qw32_charset_vietnamese)
6114 return VIETNAMESE_CHARSET;
6115 if (w32_charset == Qw32_charset_thai)
6116 return THAI_CHARSET;
6117 if (w32_charset == Qw32_charset_mac)
6118 return MAC_CHARSET;
6119 #endif /* JOHAB_CHARSET */
6120 #ifdef UNICODE_CHARSET
6121 if (w32_charset == Qw32_charset_unicode)
6122 return UNICODE_CHARSET;
6123 #endif
6124
6125 return DEFAULT_CHARSET;
6126 }
6127
6128
6129 static char *
6130 w32_to_x_charset (fncharset)
6131 int fncharset;
6132 {
6133 static char buf[32];
6134 Lisp_Object charset_type;
6135
6136 switch (fncharset)
6137 {
6138 case ANSI_CHARSET:
6139 /* Handle startup case of w32-charset-info-alist not
6140 being set up yet. */
6141 if (NILP(Vw32_charset_info_alist))
6142 return "iso8859-1";
6143 charset_type = Qw32_charset_ansi;
6144 break;
6145 case DEFAULT_CHARSET:
6146 charset_type = Qw32_charset_default;
6147 break;
6148 case SYMBOL_CHARSET:
6149 charset_type = Qw32_charset_symbol;
6150 break;
6151 case SHIFTJIS_CHARSET:
6152 charset_type = Qw32_charset_shiftjis;
6153 break;
6154 case HANGEUL_CHARSET:
6155 charset_type = Qw32_charset_hangeul;
6156 break;
6157 case GB2312_CHARSET:
6158 charset_type = Qw32_charset_gb2312;
6159 break;
6160 case CHINESEBIG5_CHARSET:
6161 charset_type = Qw32_charset_chinesebig5;
6162 break;
6163 case OEM_CHARSET:
6164 charset_type = Qw32_charset_oem;
6165 break;
6166
6167 /* More recent versions of Windows (95 and NT4.0) define more
6168 character sets. */
6169 #ifdef EASTEUROPE_CHARSET
6170 case EASTEUROPE_CHARSET:
6171 charset_type = Qw32_charset_easteurope;
6172 break;
6173 case TURKISH_CHARSET:
6174 charset_type = Qw32_charset_turkish;
6175 break;
6176 case BALTIC_CHARSET:
6177 charset_type = Qw32_charset_baltic;
6178 break;
6179 case RUSSIAN_CHARSET:
6180 charset_type = Qw32_charset_russian;
6181 break;
6182 case ARABIC_CHARSET:
6183 charset_type = Qw32_charset_arabic;
6184 break;
6185 case GREEK_CHARSET:
6186 charset_type = Qw32_charset_greek;
6187 break;
6188 case HEBREW_CHARSET:
6189 charset_type = Qw32_charset_hebrew;
6190 break;
6191 case VIETNAMESE_CHARSET:
6192 charset_type = Qw32_charset_vietnamese;
6193 break;
6194 case THAI_CHARSET:
6195 charset_type = Qw32_charset_thai;
6196 break;
6197 case MAC_CHARSET:
6198 charset_type = Qw32_charset_mac;
6199 break;
6200 case JOHAB_CHARSET:
6201 charset_type = Qw32_charset_johab;
6202 break;
6203 #endif
6204
6205 #ifdef UNICODE_CHARSET
6206 case UNICODE_CHARSET:
6207 charset_type = Qw32_charset_unicode;
6208 break;
6209 #endif
6210 default:
6211 /* Encode numerical value of unknown charset. */
6212 sprintf (buf, "*-#%u", fncharset);
6213 return buf;
6214 }
6215
6216 {
6217 Lisp_Object rest;
6218 char * best_match = NULL;
6219
6220 /* Look through w32-charset-info-alist for the character set.
6221 Prefer ISO codepages, and prefer lower numbers in the ISO
6222 range. Only return charsets for codepages which are installed.
6223
6224 Format of each entry is
6225 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
6226 */
6227 for (rest = Vw32_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6228 {
6229 char * x_charset;
6230 Lisp_Object w32_charset;
6231 Lisp_Object codepage;
6232
6233 Lisp_Object this_entry = XCAR (rest);
6234
6235 /* Skip invalid entries in alist. */
6236 if (!CONSP (this_entry) || !STRINGP (XCAR (this_entry))
6237 || !CONSP (XCDR (this_entry))
6238 || !SYMBOLP (XCAR (XCDR (this_entry))))
6239 continue;
6240
6241 x_charset = XSTRING (XCAR (this_entry))->data;
6242 w32_charset = XCAR (XCDR (this_entry));
6243 codepage = XCDR (XCDR (this_entry));
6244
6245 /* Look for Same charset and a valid codepage (or non-int
6246 which means ignore). */
6247 if (w32_charset == charset_type
6248 && (!INTEGERP (codepage) || codepage == CP_DEFAULT
6249 || IsValidCodePage (XINT (codepage))))
6250 {
6251 /* If we don't have a match already, then this is the
6252 best. */
6253 if (!best_match)
6254 best_match = x_charset;
6255 /* If this is an ISO codepage, and the best so far isn't,
6256 then this is better. */
6257 else if (stricmp (best_match, "iso") != 0
6258 && stricmp (x_charset, "iso") == 0)
6259 best_match = x_charset;
6260 /* If both are ISO8859 codepages, choose the one with the
6261 lowest number in the encoding field. */
6262 else if (stricmp (best_match, "iso8859-") == 0
6263 && stricmp (x_charset, "iso8859-") == 0)
6264 {
6265 int best_enc = atoi (best_match + 8);
6266 int this_enc = atoi (x_charset + 8);
6267 if (this_enc > 0 && this_enc < best_enc)
6268 best_match = x_charset;
6269 }
6270 }
6271 }
6272
6273 /* If no match, encode the numeric value. */
6274 if (!best_match)
6275 {
6276 sprintf (buf, "*-#%u", fncharset);
6277 return buf;
6278 }
6279
6280 strncpy(buf, best_match, 31);
6281 buf[31] = '\0';
6282 return buf;
6283 }
6284 }
6285
6286
6287 /* Get the Windows codepage corresponding to the specified font. The
6288 charset info in the font name is used to look up
6289 w32-charset-to-codepage-alist. */
6290 int
6291 w32_codepage_for_font (char *fontname)
6292 {
6293 Lisp_Object codepage, entry;
6294 char *charset_str, *charset, *end;
6295
6296 if (NILP (Vw32_charset_info_alist))
6297 return CP_DEFAULT;
6298
6299 /* Extract charset part of font string. */
6300 charset = xlfd_charset_of_font (fontname);
6301
6302 if (!charset)
6303 return CP_UNKNOWN;
6304
6305 charset_str = (char *) alloca (strlen (charset) + 1);
6306 strcpy (charset_str, charset);
6307
6308 #if 0
6309 /* Remove leading "*-". */
6310 if (strncmp ("*-", charset_str, 2) == 0)
6311 charset = charset_str + 2;
6312 else
6313 #endif
6314 charset = charset_str;
6315
6316 /* Stop match at wildcard (including preceding '-'). */
6317 if (end = strchr (charset, '*'))
6318 {
6319 if (end > charset && *(end-1) == '-')
6320 end--;
6321 *end = '\0';
6322 }
6323
6324 entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
6325 if (NILP (entry))
6326 return CP_UNKNOWN;
6327
6328 codepage = Fcdr (Fcdr (entry));
6329
6330 if (NILP (codepage))
6331 return CP_8BIT;
6332 else if (XFASTINT (codepage) == XFASTINT (Qt))
6333 return CP_UNICODE;
6334 else if (INTEGERP (codepage))
6335 return XINT (codepage);
6336 else
6337 return CP_UNKNOWN;
6338 }
6339
6340
6341 static BOOL
6342 w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
6343 LOGFONT * lplogfont;
6344 char * lpxstr;
6345 int len;
6346 char * specific_charset;
6347 {
6348 char* fonttype;
6349 char *fontname;
6350 char height_pixels[8];
6351 char height_dpi[8];
6352 char width_pixels[8];
6353 char *fontname_dash;
6354 int display_resy = one_w32_display_info.resy;
6355 int display_resx = one_w32_display_info.resx;
6356 int bufsz;
6357 struct coding_system coding;
6358
6359 if (!lpxstr) abort ();
6360
6361 if (!lplogfont)
6362 return FALSE;
6363
6364 if (lplogfont->lfOutPrecision == OUT_STRING_PRECIS)
6365 fonttype = "raster";
6366 else if (lplogfont->lfOutPrecision == OUT_STROKE_PRECIS)
6367 fonttype = "outline";
6368 else
6369 fonttype = "unknown";
6370
6371 setup_coding_system (Fcheck_coding_system (Vlocale_coding_system),
6372 &coding);
6373 coding.src_multibyte = 0;
6374 coding.dst_multibyte = 1;
6375 coding.mode |= CODING_MODE_LAST_BLOCK;
6376 bufsz = decoding_buffer_size (&coding, LF_FACESIZE);
6377
6378 fontname = alloca(sizeof(*fontname) * bufsz);
6379 decode_coding (&coding, lplogfont->lfFaceName, fontname,
6380 strlen(lplogfont->lfFaceName), bufsz - 1);
6381 *(fontname + coding.produced) = '\0';
6382
6383 /* Replace dashes with underscores so the dashes are not
6384 misinterpreted. */
6385 fontname_dash = fontname;
6386 while (fontname_dash = strchr (fontname_dash, '-'))
6387 *fontname_dash = '_';
6388
6389 if (lplogfont->lfHeight)
6390 {
6391 sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
6392 sprintf (height_dpi, "%u",
6393 abs (lplogfont->lfHeight) * 720 / display_resy);
6394 }
6395 else
6396 {
6397 strcpy (height_pixels, "*");
6398 strcpy (height_dpi, "*");
6399 }
6400 if (lplogfont->lfWidth)
6401 sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
6402 else
6403 strcpy (width_pixels, "*");
6404
6405 _snprintf (lpxstr, len - 1,
6406 "-%s-%s-%s-%c-normal-normal-%s-%s-%d-%d-%c-%s-%s",
6407 fonttype, /* foundry */
6408 fontname, /* family */
6409 w32_to_x_weight (lplogfont->lfWeight), /* weight */
6410 lplogfont->lfItalic?'i':'r', /* slant */
6411 /* setwidth name */
6412 /* add style name */
6413 height_pixels, /* pixel size */
6414 height_dpi, /* point size */
6415 display_resx, /* resx */
6416 display_resy, /* resy */
6417 ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH)
6418 ? 'p' : 'c', /* spacing */
6419 width_pixels, /* avg width */
6420 specific_charset ? specific_charset
6421 : w32_to_x_charset (lplogfont->lfCharSet)
6422 /* charset registry and encoding */
6423 );
6424
6425 lpxstr[len - 1] = 0; /* just to be sure */
6426 return (TRUE);
6427 }
6428
6429 static BOOL
6430 x_to_w32_font (lpxstr, lplogfont)
6431 char * lpxstr;
6432 LOGFONT * lplogfont;
6433 {
6434 struct coding_system coding;
6435
6436 if (!lplogfont) return (FALSE);
6437
6438 memset (lplogfont, 0, sizeof (*lplogfont));
6439
6440 /* Set default value for each field. */
6441 #if 1
6442 lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
6443 lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
6444 lplogfont->lfQuality = DEFAULT_QUALITY;
6445 #else
6446 /* go for maximum quality */
6447 lplogfont->lfOutPrecision = OUT_STROKE_PRECIS;
6448 lplogfont->lfClipPrecision = CLIP_STROKE_PRECIS;
6449 lplogfont->lfQuality = PROOF_QUALITY;
6450 #endif
6451
6452 lplogfont->lfCharSet = DEFAULT_CHARSET;
6453 lplogfont->lfWeight = FW_DONTCARE;
6454 lplogfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
6455
6456 if (!lpxstr)
6457 return FALSE;
6458
6459 /* Provide a simple escape mechanism for specifying Windows font names
6460 * directly -- if font spec does not beginning with '-', assume this
6461 * format:
6462 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
6463 */
6464
6465 if (*lpxstr == '-')
6466 {
6467 int fields, tem;
6468 char name[50], weight[20], slant, pitch, pixels[10], height[10],
6469 width[10], resy[10], remainder[50];
6470 char * encoding;
6471 int dpi = one_w32_display_info.resy;
6472
6473 fields = sscanf (lpxstr,
6474 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
6475 name, weight, &slant, pixels, height, resy, &pitch, width, remainder);
6476 if (fields == EOF)
6477 return (FALSE);
6478
6479 /* In the general case when wildcards cover more than one field,
6480 we don't know which field is which, so don't fill any in.
6481 However, we need to cope with this particular form, which is
6482 generated by font_list_1 (invoked by try_font_list):
6483 "-raster-6x10-*-gb2312*-*"
6484 and make sure to correctly parse the charset field. */
6485 if (fields == 3)
6486 {
6487 fields = sscanf (lpxstr,
6488 "-%*[^-]-%49[^-]-*-%49s",
6489 name, remainder);
6490 }
6491 else if (fields < 9)
6492 {
6493 fields = 0;
6494 remainder[0] = 0;
6495 }
6496
6497 if (fields > 0 && name[0] != '*')
6498 {
6499 int bufsize;
6500 unsigned char *buf;
6501
6502 setup_coding_system
6503 (Fcheck_coding_system (Vlocale_coding_system), &coding);
6504 coding.src_multibyte = 1;
6505 coding.dst_multibyte = 1;
6506 bufsize = encoding_buffer_size (&coding, strlen (name));
6507 buf = (unsigned char *) alloca (bufsize);
6508 coding.mode |= CODING_MODE_LAST_BLOCK;
6509 encode_coding (&coding, name, buf, strlen (name), bufsize);
6510 if (coding.produced >= LF_FACESIZE)
6511 coding.produced = LF_FACESIZE - 1;
6512 buf[coding.produced] = 0;
6513 strcpy (lplogfont->lfFaceName, buf);
6514 }
6515 else
6516 {
6517 lplogfont->lfFaceName[0] = '\0';
6518 }
6519
6520 fields--;
6521
6522 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
6523
6524 fields--;
6525
6526 lplogfont->lfItalic = (fields > 0 && slant == 'i');
6527
6528 fields--;
6529
6530 if (fields > 0 && pixels[0] != '*')
6531 lplogfont->lfHeight = atoi (pixels);
6532
6533 fields--;
6534 fields--;
6535 if (fields > 0 && resy[0] != '*')
6536 {
6537 tem = atoi (resy);
6538 if (tem > 0) dpi = tem;
6539 }
6540
6541 if (fields > -1 && lplogfont->lfHeight == 0 && height[0] != '*')
6542 lplogfont->lfHeight = atoi (height) * dpi / 720;
6543
6544 if (fields > 0)
6545 lplogfont->lfPitchAndFamily =
6546 (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
6547
6548 fields--;
6549
6550 if (fields > 0 && width[0] != '*')
6551 lplogfont->lfWidth = atoi (width) / 10;
6552
6553 fields--;
6554
6555 /* Strip the trailing '-' if present. (it shouldn't be, as it
6556 fails the test against xlfd-tight-regexp in fontset.el). */
6557 {
6558 int len = strlen (remainder);
6559 if (len > 0 && remainder[len-1] == '-')
6560 remainder[len-1] = 0;
6561 }
6562 encoding = remainder;
6563 #if 0
6564 if (strncmp (encoding, "*-", 2) == 0)
6565 encoding += 2;
6566 #endif
6567 lplogfont->lfCharSet = x_to_w32_charset (encoding);
6568 }
6569 else
6570 {
6571 int fields;
6572 char name[100], height[10], width[10], weight[20];
6573
6574 fields = sscanf (lpxstr,
6575 "%99[^:]:%9[^:]:%9[^:]:%19s",
6576 name, height, width, weight);
6577
6578 if (fields == EOF) return (FALSE);
6579
6580 if (fields > 0)
6581 {
6582 strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
6583 lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
6584 }
6585 else
6586 {
6587 lplogfont->lfFaceName[0] = 0;
6588 }
6589
6590 fields--;
6591
6592 if (fields > 0)
6593 lplogfont->lfHeight = atoi (height);
6594
6595 fields--;
6596
6597 if (fields > 0)
6598 lplogfont->lfWidth = atoi (width);
6599
6600 fields--;
6601
6602 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
6603 }
6604
6605 /* This makes TrueType fonts work better. */
6606 lplogfont->lfHeight = - abs (lplogfont->lfHeight);
6607
6608 return (TRUE);
6609 }
6610
6611 /* Strip the pixel height and point height from the given xlfd, and
6612 return the pixel height. If no pixel height is specified, calculate
6613 one from the point height, or if that isn't defined either, return
6614 0 (which usually signifies a scalable font).
6615 */
6616 static int
6617 xlfd_strip_height (char *fontname)
6618 {
6619 int pixel_height, field_number;
6620 char *read_from, *write_to;
6621
6622 xassert (fontname);
6623
6624 pixel_height = field_number = 0;
6625 write_to = NULL;
6626
6627 /* Look for height fields. */
6628 for (read_from = fontname; *read_from; read_from++)
6629 {
6630 if (*read_from == '-')
6631 {
6632 field_number++;
6633 if (field_number == 7) /* Pixel height. */
6634 {
6635 read_from++;
6636 write_to = read_from;
6637
6638 /* Find end of field. */
6639 for (;*read_from && *read_from != '-'; read_from++)
6640 ;
6641
6642 /* Split the fontname at end of field. */
6643 if (*read_from)
6644 {
6645 *read_from = '\0';
6646 read_from++;
6647 }
6648 pixel_height = atoi (write_to);
6649 /* Blank out field. */
6650 if (read_from > write_to)
6651 {
6652 *write_to = '-';
6653 write_to++;
6654 }
6655 /* If the pixel height field is at the end (partial xlfd),
6656 return now. */
6657 else
6658 return pixel_height;
6659
6660 /* If we got a pixel height, the point height can be
6661 ignored. Just blank it out and break now. */
6662 if (pixel_height)
6663 {
6664 /* Find end of point size field. */
6665 for (; *read_from && *read_from != '-'; read_from++)
6666 ;
6667
6668 if (*read_from)
6669 read_from++;
6670
6671 /* Blank out the point size field. */
6672 if (read_from > write_to)
6673 {
6674 *write_to = '-';
6675 write_to++;
6676 }
6677 else
6678 return pixel_height;
6679
6680 break;
6681 }
6682 /* If the point height is already blank, break now. */
6683 if (*read_from == '-')
6684 {
6685 read_from++;
6686 break;
6687 }
6688 }
6689 else if (field_number == 8)
6690 {
6691 /* If we didn't get a pixel height, try to get the point
6692 height and convert that. */
6693 int point_size;
6694 char *point_size_start = read_from++;
6695
6696 /* Find end of field. */
6697 for (; *read_from && *read_from != '-'; read_from++)
6698 ;
6699
6700 if (*read_from)
6701 {
6702 *read_from = '\0';
6703 read_from++;
6704 }
6705
6706 point_size = atoi (point_size_start);
6707
6708 /* Convert to pixel height. */
6709 pixel_height = point_size
6710 * one_w32_display_info.height_in / 720;
6711
6712 /* Blank out this field and break. */
6713 *write_to = '-';
6714 write_to++;
6715 break;
6716 }
6717 }
6718 }
6719
6720 /* Shift the rest of the font spec into place. */
6721 if (write_to && read_from > write_to)
6722 {
6723 for (; *read_from; read_from++, write_to++)
6724 *write_to = *read_from;
6725 *write_to = '\0';
6726 }
6727
6728 return pixel_height;
6729 }
6730
6731 /* Assume parameter 1 is fully qualified, no wildcards. */
6732 static BOOL
6733 w32_font_match (fontname, pattern)
6734 char * fontname;
6735 char * pattern;
6736 {
6737 char *regex = alloca (strlen (pattern) * 2 + 3);
6738 char *font_name_copy = alloca (strlen (fontname) + 1);
6739 char *ptr;
6740
6741 /* Copy fontname so we can modify it during comparison. */
6742 strcpy (font_name_copy, fontname);
6743
6744 ptr = regex;
6745 *ptr++ = '^';
6746
6747 /* Turn pattern into a regexp and do a regexp match. */
6748 for (; *pattern; pattern++)
6749 {
6750 if (*pattern == '?')
6751 *ptr++ = '.';
6752 else if (*pattern == '*')
6753 {
6754 *ptr++ = '.';
6755 *ptr++ = '*';
6756 }
6757 else
6758 *ptr++ = *pattern;
6759 }
6760 *ptr = '$';
6761 *(ptr + 1) = '\0';
6762
6763 /* Strip out font heights and compare them seperately, since
6764 rounding error can cause mismatches. This also allows a
6765 comparison between a font that declares only a pixel height and a
6766 pattern that declares the point height.
6767 */
6768 {
6769 int font_height, pattern_height;
6770
6771 font_height = xlfd_strip_height (font_name_copy);
6772 pattern_height = xlfd_strip_height (regex);
6773
6774 /* Compare now, and don't bother doing expensive regexp matching
6775 if the heights differ. */
6776 if (font_height && pattern_height && (font_height != pattern_height))
6777 return FALSE;
6778 }
6779
6780 return (fast_c_string_match_ignore_case (build_string (regex),
6781 font_name_copy) >= 0);
6782 }
6783
6784 /* Callback functions, and a structure holding info they need, for
6785 listing system fonts on W32. We need one set of functions to do the
6786 job properly, but these don't work on NT 3.51 and earlier, so we
6787 have a second set which don't handle character sets properly to
6788 fall back on.
6789
6790 In both cases, there are two passes made. The first pass gets one
6791 font from each family, the second pass lists all the fonts from
6792 each family. */
6793
6794 typedef struct enumfont_t
6795 {
6796 HDC hdc;
6797 int numFonts;
6798 LOGFONT logfont;
6799 XFontStruct *size_ref;
6800 Lisp_Object *pattern;
6801 Lisp_Object *tail;
6802 } enumfont_t;
6803
6804 static int CALLBACK
6805 enum_font_cb2 (lplf, lptm, FontType, lpef)
6806 ENUMLOGFONT * lplf;
6807 NEWTEXTMETRIC * lptm;
6808 int FontType;
6809 enumfont_t * lpef;
6810 {
6811 /* Ignore struck out and underlined versions of fonts. */
6812 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline)
6813 return 1;
6814
6815 /* Only return fonts with names starting with @ if they were
6816 explicitly specified, since Microsoft uses an initial @ to
6817 denote fonts for vertical writing, without providing a more
6818 convenient way of identifying them. */
6819 if (lplf->elfLogFont.lfFaceName[0] == '@'
6820 && lpef->logfont.lfFaceName[0] != '@')
6821 return 1;
6822
6823 /* Check that the character set matches if it was specified */
6824 if (lpef->logfont.lfCharSet != DEFAULT_CHARSET &&
6825 lplf->elfLogFont.lfCharSet != lpef->logfont.lfCharSet)
6826 return 1;
6827
6828 {
6829 char buf[100];
6830 Lisp_Object width = Qnil;
6831 char *charset = NULL;
6832
6833 /* Truetype fonts do not report their true metrics until loaded */
6834 if (FontType != RASTER_FONTTYPE)
6835 {
6836 if (!NILP (*(lpef->pattern)))
6837 {
6838 /* Scalable fonts are as big as you want them to be. */
6839 lplf->elfLogFont.lfHeight = lpef->logfont.lfHeight;
6840 lplf->elfLogFont.lfWidth = lpef->logfont.lfWidth;
6841 width = make_number (lpef->logfont.lfWidth);
6842 }
6843 else
6844 {
6845 lplf->elfLogFont.lfHeight = 0;
6846 lplf->elfLogFont.lfWidth = 0;
6847 }
6848 }
6849
6850 /* Make sure the height used here is the same as everywhere
6851 else (ie character height, not cell height). */
6852 if (lplf->elfLogFont.lfHeight > 0)
6853 {
6854 /* lptm can be trusted for RASTER fonts, but not scalable ones. */
6855 if (FontType == RASTER_FONTTYPE)
6856 lplf->elfLogFont.lfHeight = lptm->tmInternalLeading - lptm->tmHeight;
6857 else
6858 lplf->elfLogFont.lfHeight = -lplf->elfLogFont.lfHeight;
6859 }
6860
6861 if (!NILP (*(lpef->pattern)))
6862 {
6863 charset = xlfd_charset_of_font (XSTRING(*(lpef->pattern))->data);
6864
6865 /* Ensure that charset is valid for this font. */
6866 if (charset
6867 && (x_to_w32_charset (charset) != lplf->elfLogFont.lfCharSet))
6868 charset = NULL;
6869 }
6870
6871 /* TODO: List all relevant charsets if charset not specified. */
6872 if (!w32_to_x_font (&(lplf->elfLogFont), buf, 100, charset))
6873 return 1;
6874
6875 if (NILP (*(lpef->pattern))
6876 || w32_font_match (buf, XSTRING (*(lpef->pattern))->data))
6877 {
6878 *lpef->tail = Fcons (Fcons (build_string (buf), width), Qnil);
6879 lpef->tail = &(XCDR (*lpef->tail));
6880 lpef->numFonts++;
6881 }
6882 }
6883
6884 return 1;
6885 }
6886
6887 static int CALLBACK
6888 enum_font_cb1 (lplf, lptm, FontType, lpef)
6889 ENUMLOGFONT * lplf;
6890 NEWTEXTMETRIC * lptm;
6891 int FontType;
6892 enumfont_t * lpef;
6893 {
6894 return EnumFontFamilies (lpef->hdc,
6895 lplf->elfLogFont.lfFaceName,
6896 (FONTENUMPROC) enum_font_cb2,
6897 (LPARAM) lpef);
6898 }
6899
6900
6901 static int CALLBACK
6902 enum_fontex_cb2 (lplf, lptm, font_type, lpef)
6903 ENUMLOGFONTEX * lplf;
6904 NEWTEXTMETRICEX * lptm;
6905 int font_type;
6906 enumfont_t * lpef;
6907 {
6908 /* We are not interested in the extra info we get back from the 'Ex
6909 version - only the fact that we get character set variations
6910 enumerated seperately. */
6911 return enum_font_cb2 ((ENUMLOGFONT *) lplf, (NEWTEXTMETRIC *) lptm,
6912 font_type, lpef);
6913 }
6914
6915 static int CALLBACK
6916 enum_fontex_cb1 (lplf, lptm, font_type, lpef)
6917 ENUMLOGFONTEX * lplf;
6918 NEWTEXTMETRICEX * lptm;
6919 int font_type;
6920 enumfont_t * lpef;
6921 {
6922 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
6923 FARPROC enum_font_families_ex
6924 = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
6925 /* We don't really expect EnumFontFamiliesEx to disappear once we
6926 get here, so don't bother handling it gracefully. */
6927 if (enum_font_families_ex == NULL)
6928 error ("gdi32.dll has disappeared!");
6929 return enum_font_families_ex (lpef->hdc,
6930 &lplf->elfLogFont,
6931 (FONTENUMPROC) enum_fontex_cb2,
6932 (LPARAM) lpef, 0);
6933 }
6934
6935 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
6936 and xterm.c in Emacs 20.3) */
6937
6938 static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names)
6939 {
6940 char *fontname, *ptnstr;
6941 Lisp_Object list, tem, newlist = Qnil;
6942 int n_fonts = 0;
6943
6944 list = Vw32_bdf_filename_alist;
6945 ptnstr = XSTRING (pattern)->data;
6946
6947 for ( ; CONSP (list); list = XCDR (list))
6948 {
6949 tem = XCAR (list);
6950 if (CONSP (tem))
6951 fontname = XSTRING (XCAR (tem))->data;
6952 else if (STRINGP (tem))
6953 fontname = XSTRING (tem)->data;
6954 else
6955 continue;
6956
6957 if (w32_font_match (fontname, ptnstr))
6958 {
6959 newlist = Fcons (XCAR (tem), newlist);
6960 n_fonts++;
6961 if (n_fonts >= max_names)
6962 break;
6963 }
6964 }
6965
6966 return newlist;
6967 }
6968
6969 static Lisp_Object w32_list_synthesized_fonts (FRAME_PTR f,
6970 Lisp_Object pattern,
6971 int size, int max_names);
6972
6973 /* Return a list of names of available fonts matching PATTERN on frame
6974 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6975 to be listed. Frame F NULL means we have not yet created any
6976 frame, which means we can't get proper size info, as we don't have
6977 a device context to use for GetTextMetrics.
6978 MAXNAMES sets a limit on how many fonts to match. */
6979
6980 Lisp_Object
6981 w32_list_fonts (f, pattern, size, maxnames)
6982 struct frame *f;
6983 Lisp_Object pattern;
6984 int size;
6985 int maxnames;
6986 {
6987 Lisp_Object patterns, key = Qnil, tem, tpat;
6988 Lisp_Object list = Qnil, newlist = Qnil, second_best = Qnil;
6989 struct w32_display_info *dpyinfo = &one_w32_display_info;
6990 int n_fonts = 0;
6991
6992 patterns = Fassoc (pattern, Valternate_fontname_alist);
6993 if (NILP (patterns))
6994 patterns = Fcons (pattern, Qnil);
6995
6996 for (; CONSP (patterns); patterns = XCDR (patterns))
6997 {
6998 enumfont_t ef;
6999 int codepage;
7000
7001 tpat = XCAR (patterns);
7002
7003 if (!STRINGP (tpat))
7004 continue;
7005
7006 /* Avoid expensive EnumFontFamilies functions if we are not
7007 going to be able to output one of these anyway. */
7008 codepage = w32_codepage_for_font (XSTRING (tpat)->data);
7009 if (codepage != CP_8BIT && codepage != CP_UNICODE
7010 && codepage != CP_DEFAULT && codepage != CP_UNKNOWN
7011 && !IsValidCodePage(codepage))
7012 continue;
7013
7014 /* See if we cached the result for this particular query.
7015 The cache is an alist of the form:
7016 ((PATTERN (FONTNAME . WIDTH) ...) ...)
7017 */
7018 if (tem = XCDR (dpyinfo->name_list_element),
7019 !NILP (list = Fassoc (tpat, tem)))
7020 {
7021 list = Fcdr_safe (list);
7022 /* We have a cached list. Don't have to get the list again. */
7023 goto label_cached;
7024 }
7025
7026 BLOCK_INPUT;
7027 /* At first, put PATTERN in the cache. */
7028 list = Qnil;
7029 ef.pattern = &tpat;
7030 ef.tail = &list;
7031 ef.numFonts = 0;
7032
7033 /* Use EnumFontFamiliesEx where it is available, as it knows
7034 about character sets. Fall back to EnumFontFamilies for
7035 older versions of NT that don't support the 'Ex function. */
7036 x_to_w32_font (XSTRING (tpat)->data, &ef.logfont);
7037 {
7038 LOGFONT font_match_pattern;
7039 HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
7040 FARPROC enum_font_families_ex
7041 = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
7042
7043 /* We do our own pattern matching so we can handle wildcards. */
7044 font_match_pattern.lfFaceName[0] = 0;
7045 font_match_pattern.lfPitchAndFamily = 0;
7046 /* We can use the charset, because if it is a wildcard it will
7047 be DEFAULT_CHARSET anyway. */
7048 font_match_pattern.lfCharSet = ef.logfont.lfCharSet;
7049
7050 ef.hdc = GetDC (dpyinfo->root_window);
7051
7052 if (enum_font_families_ex)
7053 enum_font_families_ex (ef.hdc,
7054 &font_match_pattern,
7055 (FONTENUMPROC) enum_fontex_cb1,
7056 (LPARAM) &ef, 0);
7057 else
7058 EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1,
7059 (LPARAM)&ef);
7060
7061 ReleaseDC (dpyinfo->root_window, ef.hdc);
7062 }
7063
7064 UNBLOCK_INPUT;
7065
7066 /* Make a list of the fonts we got back.
7067 Store that in the font cache for the display. */
7068 XSETCDR (dpyinfo->name_list_element,
7069 Fcons (Fcons (tpat, list),
7070 XCDR (dpyinfo->name_list_element)));
7071
7072 label_cached:
7073 if (NILP (list)) continue; /* Try the remaining alternatives. */
7074
7075 newlist = second_best = Qnil;
7076
7077 /* Make a list of the fonts that have the right width. */
7078 for (; CONSP (list); list = XCDR (list))
7079 {
7080 int found_size;
7081 tem = XCAR (list);
7082
7083 if (!CONSP (tem))
7084 continue;
7085 if (NILP (XCAR (tem)))
7086 continue;
7087 if (!size)
7088 {
7089 newlist = Fcons (XCAR (tem), newlist);
7090 n_fonts++;
7091 if (n_fonts >= maxnames)
7092 break;
7093 else
7094 continue;
7095 }
7096 if (!INTEGERP (XCDR (tem)))
7097 {
7098 /* Since we don't yet know the size of the font, we must
7099 load it and try GetTextMetrics. */
7100 W32FontStruct thisinfo;
7101 LOGFONT lf;
7102 HDC hdc;
7103 HANDLE oldobj;
7104
7105 if (!x_to_w32_font (XSTRING (XCAR (tem))->data, &lf))
7106 continue;
7107
7108 BLOCK_INPUT;
7109 thisinfo.bdf = NULL;
7110 thisinfo.hfont = CreateFontIndirect (&lf);
7111 if (thisinfo.hfont == NULL)
7112 continue;
7113
7114 hdc = GetDC (dpyinfo->root_window);
7115 oldobj = SelectObject (hdc, thisinfo.hfont);
7116 if (GetTextMetrics (hdc, &thisinfo.tm))
7117 XSETCDR (tem, make_number (FONT_WIDTH (&thisinfo)));
7118 else
7119 XSETCDR (tem, make_number (0));
7120 SelectObject (hdc, oldobj);
7121 ReleaseDC (dpyinfo->root_window, hdc);
7122 DeleteObject(thisinfo.hfont);
7123 UNBLOCK_INPUT;
7124 }
7125 found_size = XINT (XCDR (tem));
7126 if (found_size == size)
7127 {
7128 newlist = Fcons (XCAR (tem), newlist);
7129 n_fonts++;
7130 if (n_fonts >= maxnames)
7131 break;
7132 }
7133 /* keep track of the closest matching size in case
7134 no exact match is found. */
7135 else if (found_size > 0)
7136 {
7137 if (NILP (second_best))
7138 second_best = tem;
7139
7140 else if (found_size < size)
7141 {
7142 if (XINT (XCDR (second_best)) > size
7143 || XINT (XCDR (second_best)) < found_size)
7144 second_best = tem;
7145 }
7146 else
7147 {
7148 if (XINT (XCDR (second_best)) > size
7149 && XINT (XCDR (second_best)) >
7150 found_size)
7151 second_best = tem;
7152 }
7153 }
7154 }
7155
7156 if (!NILP (newlist))
7157 break;
7158 else if (!NILP (second_best))
7159 {
7160 newlist = Fcons (XCAR (second_best), Qnil);
7161 break;
7162 }
7163 }
7164
7165 /* Include any bdf fonts. */
7166 if (n_fonts < maxnames)
7167 {
7168 Lisp_Object combined[2];
7169 combined[0] = w32_list_bdf_fonts (pattern, maxnames - n_fonts);
7170 combined[1] = newlist;
7171 newlist = Fnconc(2, combined);
7172 }
7173
7174 /* If we can't find a font that matches, check if Windows would be
7175 able to synthesize it from a different style. */
7176 if (NILP (newlist) && !NILP (Vw32_enable_synthesized_fonts))
7177 newlist = w32_list_synthesized_fonts (f, pattern, size, maxnames);
7178
7179 return newlist;
7180 }
7181
7182 static Lisp_Object
7183 w32_list_synthesized_fonts (f, pattern, size, max_names)
7184 FRAME_PTR f;
7185 Lisp_Object pattern;
7186 int size;
7187 int max_names;
7188 {
7189 int fields;
7190 char *full_pattn, *new_pattn, foundary[50], family[50], *pattn_part2;
7191 char style[20], slant;
7192 Lisp_Object matches, tem, synthed_matches = Qnil;
7193
7194 full_pattn = XSTRING (pattern)->data;
7195
7196 pattn_part2 = alloca (XSTRING (pattern)->size + 1);
7197 /* Allow some space for wildcard expansion. */
7198 new_pattn = alloca (XSTRING (pattern)->size + 100);
7199
7200 fields = sscanf (full_pattn, "-%49[^-]-%49[^-]-%19[^-]-%c-%s",
7201 foundary, family, style, &slant, pattn_part2);
7202 if (fields == EOF || fields < 5)
7203 return Qnil;
7204
7205 /* If the style and slant are wildcards already there is no point
7206 checking again (and we don't want to keep recursing). */
7207 if (*style == '*' && slant == '*')
7208 return Qnil;
7209
7210 sprintf (new_pattn, "-%s-%s-*-*-%s", foundary, family, pattn_part2);
7211
7212 matches = w32_list_fonts (f, build_string (new_pattn), size, max_names);
7213
7214 for ( ; CONSP (matches); matches = XCDR (matches))
7215 {
7216 tem = XCAR (matches);
7217 if (!STRINGP (tem))
7218 continue;
7219
7220 full_pattn = XSTRING (tem)->data;
7221 fields = sscanf (full_pattn, "-%49[^-]-%49[^-]-%*[^-]-%*c-%s",
7222 foundary, family, pattn_part2);
7223 if (fields == EOF || fields < 3)
7224 continue;
7225
7226 sprintf (new_pattn, "-%s-%s-%s-%c-%s", foundary, family, style,
7227 slant, pattn_part2);
7228
7229 synthed_matches = Fcons (build_string (new_pattn),
7230 synthed_matches);
7231 }
7232
7233 return synthed_matches;
7234 }
7235
7236
7237 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7238 struct font_info *
7239 w32_get_font_info (f, font_idx)
7240 FRAME_PTR f;
7241 int font_idx;
7242 {
7243 return (FRAME_W32_FONT_TABLE (f) + font_idx);
7244 }
7245
7246
7247 struct font_info*
7248 w32_query_font (struct frame *f, char *fontname)
7249 {
7250 int i;
7251 struct font_info *pfi;
7252
7253 pfi = FRAME_W32_FONT_TABLE (f);
7254
7255 for (i = 0; i < one_w32_display_info.n_fonts ;i++, pfi++)
7256 {
7257 if (strcmp(pfi->name, fontname) == 0) return pfi;
7258 }
7259
7260 return NULL;
7261 }
7262
7263 /* Find a CCL program for a font specified by FONTP, and set the member
7264 `encoder' of the structure. */
7265
7266 void
7267 w32_find_ccl_program (fontp)
7268 struct font_info *fontp;
7269 {
7270 Lisp_Object list, elt;
7271
7272 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7273 {
7274 elt = XCAR (list);
7275 if (CONSP (elt)
7276 && STRINGP (XCAR (elt))
7277 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7278 >= 0))
7279 break;
7280 }
7281 if (! NILP (list))
7282 {
7283 struct ccl_program *ccl
7284 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7285
7286 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7287 xfree (ccl);
7288 else
7289 fontp->font_encoder = ccl;
7290 }
7291 }
7292
7293 \f
7294 /* Find BDF files in a specified directory. (use GCPRO when calling,
7295 as this calls lisp to get a directory listing). */
7296 static Lisp_Object
7297 w32_find_bdf_fonts_in_dir (Lisp_Object directory)
7298 {
7299 Lisp_Object filelist, list = Qnil;
7300 char fontname[100];
7301
7302 if (!STRINGP(directory))
7303 return Qnil;
7304
7305 filelist = Fdirectory_files (directory, Qt,
7306 build_string (".*\\.[bB][dD][fF]"), Qt);
7307
7308 for ( ; CONSP(filelist); filelist = XCDR (filelist))
7309 {
7310 Lisp_Object filename = XCAR (filelist);
7311 if (w32_BDF_to_x_font (XSTRING (filename)->data, fontname, 100))
7312 store_in_alist (&list, build_string (fontname), filename);
7313 }
7314 return list;
7315 }
7316
7317 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts, Sw32_find_bdf_fonts,
7318 1, 1, 0,
7319 doc: /* Return a list of BDF fonts in DIR.
7320 The list is suitable for appending to w32-bdf-filename-alist. Fonts
7321 which do not contain an xlfd description will not be included in the
7322 list. DIR may be a list of directories. */)
7323 (directory)
7324 Lisp_Object directory;
7325 {
7326 Lisp_Object list = Qnil;
7327 struct gcpro gcpro1, gcpro2;
7328
7329 if (!CONSP (directory))
7330 return w32_find_bdf_fonts_in_dir (directory);
7331
7332 for ( ; CONSP (directory); directory = XCDR (directory))
7333 {
7334 Lisp_Object pair[2];
7335 pair[0] = list;
7336 pair[1] = Qnil;
7337 GCPRO2 (directory, list);
7338 pair[1] = w32_find_bdf_fonts_in_dir( XCAR (directory) );
7339 list = Fnconc( 2, pair );
7340 UNGCPRO;
7341 }
7342 return list;
7343 }
7344
7345 \f
7346 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
7347 doc: /* Internal function called by `color-defined-p', which see. */)
7348 (color, frame)
7349 Lisp_Object color, frame;
7350 {
7351 XColor foo;
7352 FRAME_PTR f = check_x_frame (frame);
7353
7354 CHECK_STRING (color);
7355
7356 if (w32_defined_color (f, XSTRING (color)->data, &foo, 0))
7357 return Qt;
7358 else
7359 return Qnil;
7360 }
7361
7362 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
7363 doc: /* Internal function called by `color-values', which see. */)
7364 (color, frame)
7365 Lisp_Object color, frame;
7366 {
7367 XColor foo;
7368 FRAME_PTR f = check_x_frame (frame);
7369
7370 CHECK_STRING (color);
7371
7372 if (w32_defined_color (f, XSTRING (color)->data, &foo, 0))
7373 {
7374 Lisp_Object rgb[3];
7375
7376 rgb[0] = make_number ((GetRValue (foo.pixel) << 8)
7377 | GetRValue (foo.pixel));
7378 rgb[1] = make_number ((GetGValue (foo.pixel) << 8)
7379 | GetGValue (foo.pixel));
7380 rgb[2] = make_number ((GetBValue (foo.pixel) << 8)
7381 | GetBValue (foo.pixel));
7382 return Flist (3, rgb);
7383 }
7384 else
7385 return Qnil;
7386 }
7387
7388 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
7389 doc: /* Internal function called by `display-color-p', which see. */)
7390 (display)
7391 Lisp_Object display;
7392 {
7393 struct w32_display_info *dpyinfo = check_x_display_info (display);
7394
7395 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
7396 return Qnil;
7397
7398 return Qt;
7399 }
7400
7401 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
7402 Sx_display_grayscale_p, 0, 1, 0,
7403 doc: /* Return t if the X display supports shades of gray.
7404 Note that color displays do support shades of gray.
7405 The optional argument DISPLAY specifies which display to ask about.
7406 DISPLAY should be either a frame or a display name (a string).
7407 If omitted or nil, that stands for the selected frame's display. */)
7408 (display)
7409 Lisp_Object display;
7410 {
7411 struct w32_display_info *dpyinfo = check_x_display_info (display);
7412
7413 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
7414 return Qnil;
7415
7416 return Qt;
7417 }
7418
7419 DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
7420 Sx_display_pixel_width, 0, 1, 0,
7421 doc: /* Returns the width in pixels of DISPLAY.
7422 The optional argument DISPLAY specifies which display to ask about.
7423 DISPLAY should be either a frame or a display name (a string).
7424 If omitted or nil, that stands for the selected frame's display. */)
7425 (display)
7426 Lisp_Object display;
7427 {
7428 struct w32_display_info *dpyinfo = check_x_display_info (display);
7429
7430 return make_number (dpyinfo->width);
7431 }
7432
7433 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
7434 Sx_display_pixel_height, 0, 1, 0,
7435 doc: /* Returns the height in pixels of DISPLAY.
7436 The optional argument DISPLAY specifies which display to ask about.
7437 DISPLAY should be either a frame or a display name (a string).
7438 If omitted or nil, that stands for the selected frame's display. */)
7439 (display)
7440 Lisp_Object display;
7441 {
7442 struct w32_display_info *dpyinfo = check_x_display_info (display);
7443
7444 return make_number (dpyinfo->height);
7445 }
7446
7447 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
7448 0, 1, 0,
7449 doc: /* Returns the number of bitplanes of DISPLAY.
7450 The optional argument DISPLAY specifies which display to ask about.
7451 DISPLAY should be either a frame or a display name (a string).
7452 If omitted or nil, that stands for the selected frame's display. */)
7453 (display)
7454 Lisp_Object display;
7455 {
7456 struct w32_display_info *dpyinfo = check_x_display_info (display);
7457
7458 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
7459 }
7460
7461 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
7462 0, 1, 0,
7463 doc: /* Returns the number of color cells of DISPLAY.
7464 The optional argument DISPLAY specifies which display to ask about.
7465 DISPLAY should be either a frame or a display name (a string).
7466 If omitted or nil, that stands for the selected frame's display. */)
7467 (display)
7468 Lisp_Object display;
7469 {
7470 struct w32_display_info *dpyinfo = check_x_display_info (display);
7471 HDC hdc;
7472 int cap;
7473
7474 hdc = GetDC (dpyinfo->root_window);
7475 if (dpyinfo->has_palette)
7476 cap = GetDeviceCaps (hdc,SIZEPALETTE);
7477 else
7478 cap = GetDeviceCaps (hdc,NUMCOLORS);
7479
7480 if (cap < 0)
7481 cap = 1 << (dpyinfo->n_planes * dpyinfo->n_cbits);
7482
7483 ReleaseDC (dpyinfo->root_window, hdc);
7484
7485 return make_number (cap);
7486 }
7487
7488 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
7489 Sx_server_max_request_size,
7490 0, 1, 0,
7491 doc: /* Returns the maximum request size of the server of DISPLAY.
7492 The optional argument DISPLAY specifies which display to ask about.
7493 DISPLAY should be either a frame or a display name (a string).
7494 If omitted or nil, that stands for the selected frame's display. */)
7495 (display)
7496 Lisp_Object display;
7497 {
7498 struct w32_display_info *dpyinfo = check_x_display_info (display);
7499
7500 return make_number (1);
7501 }
7502
7503 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
7504 doc: /* Returns the vendor ID string of the W32 system (Microsoft).
7505 The optional argument DISPLAY specifies which display to ask about.
7506 DISPLAY should be either a frame or a display name (a string).
7507 If omitted or nil, that stands for the selected frame's display. */)
7508 (display)
7509 Lisp_Object display;
7510 {
7511 return build_string ("Microsoft Corp.");
7512 }
7513
7514 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
7515 doc: /* Returns the version numbers of the server of DISPLAY.
7516 The value is a list of three integers: the major and minor
7517 version numbers, and the vendor-specific release
7518 number. See also the function `x-server-vendor'.
7519
7520 The optional argument DISPLAY specifies which display to ask about.
7521 DISPLAY should be either a frame or a display name (a string).
7522 If omitted or nil, that stands for the selected frame's display. */)
7523 (display)
7524 Lisp_Object display;
7525 {
7526 return Fcons (make_number (w32_major_version),
7527 Fcons (make_number (w32_minor_version),
7528 Fcons (make_number (w32_build_number), Qnil)));
7529 }
7530
7531 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
7532 doc: /* Returns the number of screens on the server of DISPLAY.
7533 The optional argument DISPLAY specifies which display to ask about.
7534 DISPLAY should be either a frame or a display name (a string).
7535 If omitted or nil, that stands for the selected frame's display. */)
7536 (display)
7537 Lisp_Object display;
7538 {
7539 return make_number (1);
7540 }
7541
7542 DEFUN ("x-display-mm-height", Fx_display_mm_height,
7543 Sx_display_mm_height, 0, 1, 0,
7544 doc: /* Returns the height in millimeters of DISPLAY.
7545 The optional argument DISPLAY specifies which display to ask about.
7546 DISPLAY should be either a frame or a display name (a string).
7547 If omitted or nil, that stands for the selected frame's display. */)
7548 (display)
7549 Lisp_Object display;
7550 {
7551 struct w32_display_info *dpyinfo = check_x_display_info (display);
7552 HDC hdc;
7553 int cap;
7554
7555 hdc = GetDC (dpyinfo->root_window);
7556
7557 cap = GetDeviceCaps (hdc, VERTSIZE);
7558
7559 ReleaseDC (dpyinfo->root_window, hdc);
7560
7561 return make_number (cap);
7562 }
7563
7564 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
7565 doc: /* Returns the width in millimeters of DISPLAY.
7566 The optional argument DISPLAY specifies which display to ask about.
7567 DISPLAY should be either a frame or a display name (a string).
7568 If omitted or nil, that stands for the selected frame's display. */)
7569 (display)
7570 Lisp_Object display;
7571 {
7572 struct w32_display_info *dpyinfo = check_x_display_info (display);
7573
7574 HDC hdc;
7575 int cap;
7576
7577 hdc = GetDC (dpyinfo->root_window);
7578
7579 cap = GetDeviceCaps (hdc, HORZSIZE);
7580
7581 ReleaseDC (dpyinfo->root_window, hdc);
7582
7583 return make_number (cap);
7584 }
7585
7586 DEFUN ("x-display-backing-store", Fx_display_backing_store,
7587 Sx_display_backing_store, 0, 1, 0,
7588 doc: /* Returns an indication of whether DISPLAY does backing store.
7589 The value may be `always', `when-mapped', or `not-useful'.
7590 The optional argument DISPLAY specifies which display to ask about.
7591 DISPLAY should be either a frame or a display name (a string).
7592 If omitted or nil, that stands for the selected frame's display. */)
7593 (display)
7594 Lisp_Object display;
7595 {
7596 return intern ("not-useful");
7597 }
7598
7599 DEFUN ("x-display-visual-class", Fx_display_visual_class,
7600 Sx_display_visual_class, 0, 1, 0,
7601 doc: /* Returns the visual class of DISPLAY.
7602 The value is one of the symbols `static-gray', `gray-scale',
7603 `static-color', `pseudo-color', `true-color', or `direct-color'.
7604
7605 The optional argument DISPLAY specifies which display to ask about.
7606 DISPLAY should be either a frame or a display name (a string).
7607 If omitted or nil, that stands for the selected frame's display. */)
7608 (display)
7609 Lisp_Object display;
7610 {
7611 struct w32_display_info *dpyinfo = check_x_display_info (display);
7612 Lisp_Object result = Qnil;
7613
7614 if (dpyinfo->has_palette)
7615 result = intern ("pseudo-color");
7616 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 1)
7617 result = intern ("static-grey");
7618 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 4)
7619 result = intern ("static-color");
7620 else if (dpyinfo->n_planes * dpyinfo->n_cbits > 8)
7621 result = intern ("true-color");
7622
7623 return result;
7624 }
7625
7626 DEFUN ("x-display-save-under", Fx_display_save_under,
7627 Sx_display_save_under, 0, 1, 0,
7628 doc: /* Returns t if DISPLAY supports the save-under feature.
7629 The optional argument DISPLAY specifies which display to ask about.
7630 DISPLAY should be either a frame or a display name (a string).
7631 If omitted or nil, that stands for the selected frame's display. */)
7632 (display)
7633 Lisp_Object display;
7634 {
7635 return Qnil;
7636 }
7637 \f
7638 int
7639 x_pixel_width (f)
7640 register struct frame *f;
7641 {
7642 return PIXEL_WIDTH (f);
7643 }
7644
7645 int
7646 x_pixel_height (f)
7647 register struct frame *f;
7648 {
7649 return PIXEL_HEIGHT (f);
7650 }
7651
7652 int
7653 x_char_width (f)
7654 register struct frame *f;
7655 {
7656 return FONT_WIDTH (f->output_data.w32->font);
7657 }
7658
7659 int
7660 x_char_height (f)
7661 register struct frame *f;
7662 {
7663 return f->output_data.w32->line_height;
7664 }
7665
7666 int
7667 x_screen_planes (f)
7668 register struct frame *f;
7669 {
7670 return FRAME_W32_DISPLAY_INFO (f)->n_planes;
7671 }
7672 \f
7673 /* Return the display structure for the display named NAME.
7674 Open a new connection if necessary. */
7675
7676 struct w32_display_info *
7677 x_display_info_for_name (name)
7678 Lisp_Object name;
7679 {
7680 Lisp_Object names;
7681 struct w32_display_info *dpyinfo;
7682
7683 CHECK_STRING (name);
7684
7685 for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
7686 dpyinfo;
7687 dpyinfo = dpyinfo->next, names = XCDR (names))
7688 {
7689 Lisp_Object tem;
7690 tem = Fstring_equal (XCAR (XCAR (names)), name);
7691 if (!NILP (tem))
7692 return dpyinfo;
7693 }
7694
7695 /* Use this general default value to start with. */
7696 Vx_resource_name = Vinvocation_name;
7697
7698 validate_x_resource_name ();
7699
7700 dpyinfo = w32_term_init (name, (unsigned char *)0,
7701 (char *) XSTRING (Vx_resource_name)->data);
7702
7703 if (dpyinfo == 0)
7704 error ("Cannot connect to server %s", XSTRING (name)->data);
7705
7706 w32_in_use = 1;
7707 XSETFASTINT (Vwindow_system_version, 3);
7708
7709 return dpyinfo;
7710 }
7711
7712 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
7713 1, 3, 0, doc: /* Open a connection to a server.
7714 DISPLAY is the name of the display to connect to.
7715 Optional second arg XRM-STRING is a string of resources in xrdb format.
7716 If the optional third arg MUST-SUCCEED is non-nil,
7717 terminate Emacs if we can't open the connection. */)
7718 (display, xrm_string, must_succeed)
7719 Lisp_Object display, xrm_string, must_succeed;
7720 {
7721 unsigned char *xrm_option;
7722 struct w32_display_info *dpyinfo;
7723
7724 /* If initialization has already been done, return now to avoid
7725 overwriting critical parts of one_w32_display_info. */
7726 if (w32_in_use)
7727 return Qnil;
7728
7729 CHECK_STRING (display);
7730 if (! NILP (xrm_string))
7731 CHECK_STRING (xrm_string);
7732
7733 if (! EQ (Vwindow_system, intern ("w32")))
7734 error ("Not using Microsoft Windows");
7735
7736 /* Allow color mapping to be defined externally; first look in user's
7737 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
7738 {
7739 Lisp_Object color_file;
7740 struct gcpro gcpro1;
7741
7742 color_file = build_string("~/rgb.txt");
7743
7744 GCPRO1 (color_file);
7745
7746 if (NILP (Ffile_readable_p (color_file)))
7747 color_file =
7748 Fexpand_file_name (build_string ("rgb.txt"),
7749 Fsymbol_value (intern ("data-directory")));
7750
7751 Vw32_color_map = Fw32_load_color_file (color_file);
7752
7753 UNGCPRO;
7754 }
7755 if (NILP (Vw32_color_map))
7756 Vw32_color_map = Fw32_default_color_map ();
7757
7758 if (! NILP (xrm_string))
7759 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
7760 else
7761 xrm_option = (unsigned char *) 0;
7762
7763 /* Use this general default value to start with. */
7764 /* First remove .exe suffix from invocation-name - it looks ugly. */
7765 {
7766 char basename[ MAX_PATH ], *str;
7767
7768 strcpy (basename, XSTRING (Vinvocation_name)->data);
7769 str = strrchr (basename, '.');
7770 if (str) *str = 0;
7771 Vinvocation_name = build_string (basename);
7772 }
7773 Vx_resource_name = Vinvocation_name;
7774
7775 validate_x_resource_name ();
7776
7777 /* This is what opens the connection and sets x_current_display.
7778 This also initializes many symbols, such as those used for input. */
7779 dpyinfo = w32_term_init (display, xrm_option,
7780 (char *) XSTRING (Vx_resource_name)->data);
7781
7782 if (dpyinfo == 0)
7783 {
7784 if (!NILP (must_succeed))
7785 fatal ("Cannot connect to server %s.\n",
7786 XSTRING (display)->data);
7787 else
7788 error ("Cannot connect to server %s", XSTRING (display)->data);
7789 }
7790
7791 w32_in_use = 1;
7792
7793 XSETFASTINT (Vwindow_system_version, 3);
7794 return Qnil;
7795 }
7796
7797 DEFUN ("x-close-connection", Fx_close_connection,
7798 Sx_close_connection, 1, 1, 0,
7799 doc: /* Close the connection to DISPLAY's server.
7800 For DISPLAY, specify either a frame or a display name (a string).
7801 If DISPLAY is nil, that stands for the selected frame's display. */)
7802 (display)
7803 Lisp_Object display;
7804 {
7805 struct w32_display_info *dpyinfo = check_x_display_info (display);
7806 int i;
7807
7808 if (dpyinfo->reference_count > 0)
7809 error ("Display still has frames on it");
7810
7811 BLOCK_INPUT;
7812 /* Free the fonts in the font table. */
7813 for (i = 0; i < dpyinfo->n_fonts; i++)
7814 if (dpyinfo->font_table[i].name)
7815 {
7816 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
7817 xfree (dpyinfo->font_table[i].full_name);
7818 xfree (dpyinfo->font_table[i].name);
7819 w32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
7820 }
7821 x_destroy_all_bitmaps (dpyinfo);
7822
7823 x_delete_display (dpyinfo);
7824 UNBLOCK_INPUT;
7825
7826 return Qnil;
7827 }
7828
7829 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
7830 doc: /* Return the list of display names that Emacs has connections to. */)
7831 ()
7832 {
7833 Lisp_Object tail, result;
7834
7835 result = Qnil;
7836 for (tail = w32_display_name_list; ! NILP (tail); tail = XCDR (tail))
7837 result = Fcons (XCAR (XCAR (tail)), result);
7838
7839 return result;
7840 }
7841
7842 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
7843 doc: /* This is a noop on W32 systems. */)
7844 (on, display)
7845 Lisp_Object display, on;
7846 {
7847 return Qnil;
7848 }
7849
7850 \f
7851 \f
7852 /***********************************************************************
7853 Image types
7854 ***********************************************************************/
7855
7856 /* Value is the number of elements of vector VECTOR. */
7857
7858 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
7859
7860 /* List of supported image types. Use define_image_type to add new
7861 types. Use lookup_image_type to find a type for a given symbol. */
7862
7863 static struct image_type *image_types;
7864
7865 /* The symbol `image' which is the car of the lists used to represent
7866 images in Lisp. */
7867
7868 extern Lisp_Object Qimage;
7869
7870 /* The symbol `xbm' which is used as the type symbol for XBM images. */
7871
7872 Lisp_Object Qxbm;
7873
7874 /* Keywords. */
7875
7876 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
7877 extern Lisp_Object QCdata;
7878 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
7879 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
7880 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
7881
7882 /* Other symbols. */
7883
7884 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
7885
7886 /* Time in seconds after which images should be removed from the cache
7887 if not displayed. */
7888
7889 Lisp_Object Vimage_cache_eviction_delay;
7890
7891 /* Function prototypes. */
7892
7893 static void define_image_type P_ ((struct image_type *type));
7894 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
7895 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
7896 static void x_laplace P_ ((struct frame *, struct image *));
7897 static void x_emboss P_ ((struct frame *, struct image *));
7898 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
7899 Lisp_Object));
7900
7901
7902 /* Define a new image type from TYPE. This adds a copy of TYPE to
7903 image_types and adds the symbol *TYPE->type to Vimage_types. */
7904
7905 static void
7906 define_image_type (type)
7907 struct image_type *type;
7908 {
7909 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
7910 The initialized data segment is read-only. */
7911 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
7912 bcopy (type, p, sizeof *p);
7913 p->next = image_types;
7914 image_types = p;
7915 Vimage_types = Fcons (*p->type, Vimage_types);
7916 }
7917
7918
7919 /* Look up image type SYMBOL, and return a pointer to its image_type
7920 structure. Value is null if SYMBOL is not a known image type. */
7921
7922 static INLINE struct image_type *
7923 lookup_image_type (symbol)
7924 Lisp_Object symbol;
7925 {
7926 struct image_type *type;
7927
7928 for (type = image_types; type; type = type->next)
7929 if (EQ (symbol, *type->type))
7930 break;
7931
7932 return type;
7933 }
7934
7935
7936 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
7937 valid image specification is a list whose car is the symbol
7938 `image', and whose rest is a property list. The property list must
7939 contain a value for key `:type'. That value must be the name of a
7940 supported image type. The rest of the property list depends on the
7941 image type. */
7942
7943 int
7944 valid_image_p (object)
7945 Lisp_Object object;
7946 {
7947 int valid_p = 0;
7948
7949 if (CONSP (object) && EQ (XCAR (object), Qimage))
7950 {
7951 Lisp_Object tem;
7952
7953 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
7954 if (EQ (XCAR (tem), QCtype))
7955 {
7956 tem = XCDR (tem);
7957 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
7958 {
7959 struct image_type *type;
7960 type = lookup_image_type (XCAR (tem));
7961 if (type)
7962 valid_p = type->valid_p (object);
7963 }
7964
7965 break;
7966 }
7967 }
7968
7969 return valid_p;
7970 }
7971
7972
7973 /* Log error message with format string FORMAT and argument ARG.
7974 Signaling an error, e.g. when an image cannot be loaded, is not a
7975 good idea because this would interrupt redisplay, and the error
7976 message display would lead to another redisplay. This function
7977 therefore simply displays a message. */
7978
7979 static void
7980 image_error (format, arg1, arg2)
7981 char *format;
7982 Lisp_Object arg1, arg2;
7983 {
7984 add_to_log (format, arg1, arg2);
7985 }
7986
7987
7988 \f
7989 /***********************************************************************
7990 Image specifications
7991 ***********************************************************************/
7992
7993 enum image_value_type
7994 {
7995 IMAGE_DONT_CHECK_VALUE_TYPE,
7996 IMAGE_STRING_VALUE,
7997 IMAGE_STRING_OR_NIL_VALUE,
7998 IMAGE_SYMBOL_VALUE,
7999 IMAGE_POSITIVE_INTEGER_VALUE,
8000 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
8001 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
8002 IMAGE_ASCENT_VALUE,
8003 IMAGE_INTEGER_VALUE,
8004 IMAGE_FUNCTION_VALUE,
8005 IMAGE_NUMBER_VALUE,
8006 IMAGE_BOOL_VALUE
8007 };
8008
8009 /* Structure used when parsing image specifications. */
8010
8011 struct image_keyword
8012 {
8013 /* Name of keyword. */
8014 char *name;
8015
8016 /* The type of value allowed. */
8017 enum image_value_type type;
8018
8019 /* Non-zero means key must be present. */
8020 int mandatory_p;
8021
8022 /* Used to recognize duplicate keywords in a property list. */
8023 int count;
8024
8025 /* The value that was found. */
8026 Lisp_Object value;
8027 };
8028
8029
8030 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
8031 int, Lisp_Object));
8032 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
8033
8034
8035 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
8036 has the format (image KEYWORD VALUE ...). One of the keyword/
8037 value pairs must be `:type TYPE'. KEYWORDS is a vector of
8038 image_keywords structures of size NKEYWORDS describing other
8039 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
8040
8041 static int
8042 parse_image_spec (spec, keywords, nkeywords, type)
8043 Lisp_Object spec;
8044 struct image_keyword *keywords;
8045 int nkeywords;
8046 Lisp_Object type;
8047 {
8048 int i;
8049 Lisp_Object plist;
8050
8051 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
8052 return 0;
8053
8054 plist = XCDR (spec);
8055 while (CONSP (plist))
8056 {
8057 Lisp_Object key, value;
8058
8059 /* First element of a pair must be a symbol. */
8060 key = XCAR (plist);
8061 plist = XCDR (plist);
8062 if (!SYMBOLP (key))
8063 return 0;
8064
8065 /* There must follow a value. */
8066 if (!CONSP (plist))
8067 return 0;
8068 value = XCAR (plist);
8069 plist = XCDR (plist);
8070
8071 /* Find key in KEYWORDS. Error if not found. */
8072 for (i = 0; i < nkeywords; ++i)
8073 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
8074 break;
8075
8076 if (i == nkeywords)
8077 continue;
8078
8079 /* Record that we recognized the keyword. If a keywords
8080 was found more than once, it's an error. */
8081 keywords[i].value = value;
8082 ++keywords[i].count;
8083
8084 if (keywords[i].count > 1)
8085 return 0;
8086
8087 /* Check type of value against allowed type. */
8088 switch (keywords[i].type)
8089 {
8090 case IMAGE_STRING_VALUE:
8091 if (!STRINGP (value))
8092 return 0;
8093 break;
8094
8095 case IMAGE_STRING_OR_NIL_VALUE:
8096 if (!STRINGP (value) && !NILP (value))
8097 return 0;
8098 break;
8099
8100 case IMAGE_SYMBOL_VALUE:
8101 if (!SYMBOLP (value))
8102 return 0;
8103 break;
8104
8105 case IMAGE_POSITIVE_INTEGER_VALUE:
8106 if (!INTEGERP (value) || XINT (value) <= 0)
8107 return 0;
8108 break;
8109
8110 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
8111 if (INTEGERP (value) && XINT (value) >= 0)
8112 break;
8113 if (CONSP (value)
8114 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
8115 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
8116 break;
8117 return 0;
8118
8119 case IMAGE_ASCENT_VALUE:
8120 if (SYMBOLP (value) && EQ (value, Qcenter))
8121 break;
8122 else if (INTEGERP (value)
8123 && XINT (value) >= 0
8124 && XINT (value) <= 100)
8125 break;
8126 return 0;
8127
8128 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
8129 if (!INTEGERP (value) || XINT (value) < 0)
8130 return 0;
8131 break;
8132
8133 case IMAGE_DONT_CHECK_VALUE_TYPE:
8134 break;
8135
8136 case IMAGE_FUNCTION_VALUE:
8137 value = indirect_function (value);
8138 if (SUBRP (value)
8139 || COMPILEDP (value)
8140 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
8141 break;
8142 return 0;
8143
8144 case IMAGE_NUMBER_VALUE:
8145 if (!INTEGERP (value) && !FLOATP (value))
8146 return 0;
8147 break;
8148
8149 case IMAGE_INTEGER_VALUE:
8150 if (!INTEGERP (value))
8151 return 0;
8152 break;
8153
8154 case IMAGE_BOOL_VALUE:
8155 if (!NILP (value) && !EQ (value, Qt))
8156 return 0;
8157 break;
8158
8159 default:
8160 abort ();
8161 break;
8162 }
8163
8164 if (EQ (key, QCtype) && !EQ (type, value))
8165 return 0;
8166 }
8167
8168 /* Check that all mandatory fields are present. */
8169 for (i = 0; i < nkeywords; ++i)
8170 if (keywords[i].mandatory_p && keywords[i].count == 0)
8171 return 0;
8172
8173 return NILP (plist);
8174 }
8175
8176
8177 /* Return the value of KEY in image specification SPEC. Value is nil
8178 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
8179 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
8180
8181 static Lisp_Object
8182 image_spec_value (spec, key, found)
8183 Lisp_Object spec, key;
8184 int *found;
8185 {
8186 Lisp_Object tail;
8187
8188 xassert (valid_image_p (spec));
8189
8190 for (tail = XCDR (spec);
8191 CONSP (tail) && CONSP (XCDR (tail));
8192 tail = XCDR (XCDR (tail)))
8193 {
8194 if (EQ (XCAR (tail), key))
8195 {
8196 if (found)
8197 *found = 1;
8198 return XCAR (XCDR (tail));
8199 }
8200 }
8201
8202 if (found)
8203 *found = 0;
8204 return Qnil;
8205 }
8206
8207
8208
8209 \f
8210 /***********************************************************************
8211 Image type independent image structures
8212 ***********************************************************************/
8213
8214 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
8215 static void free_image P_ ((struct frame *f, struct image *img));
8216
8217
8218 /* Allocate and return a new image structure for image specification
8219 SPEC. SPEC has a hash value of HASH. */
8220
8221 static struct image *
8222 make_image (spec, hash)
8223 Lisp_Object spec;
8224 unsigned hash;
8225 {
8226 struct image *img = (struct image *) xmalloc (sizeof *img);
8227
8228 xassert (valid_image_p (spec));
8229 bzero (img, sizeof *img);
8230 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
8231 xassert (img->type != NULL);
8232 img->spec = spec;
8233 img->data.lisp_val = Qnil;
8234 img->ascent = DEFAULT_IMAGE_ASCENT;
8235 img->hash = hash;
8236 return img;
8237 }
8238
8239
8240 /* Free image IMG which was used on frame F, including its resources. */
8241
8242 static void
8243 free_image (f, img)
8244 struct frame *f;
8245 struct image *img;
8246 {
8247 if (img)
8248 {
8249 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8250
8251 /* Remove IMG from the hash table of its cache. */
8252 if (img->prev)
8253 img->prev->next = img->next;
8254 else
8255 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
8256
8257 if (img->next)
8258 img->next->prev = img->prev;
8259
8260 c->images[img->id] = NULL;
8261
8262 /* Free resources, then free IMG. */
8263 img->type->free (f, img);
8264 xfree (img);
8265 }
8266 }
8267
8268
8269 /* Prepare image IMG for display on frame F. Must be called before
8270 drawing an image. */
8271
8272 void
8273 prepare_image_for_display (f, img)
8274 struct frame *f;
8275 struct image *img;
8276 {
8277 EMACS_TIME t;
8278
8279 /* We're about to display IMG, so set its timestamp to `now'. */
8280 EMACS_GET_TIME (t);
8281 img->timestamp = EMACS_SECS (t);
8282
8283 /* If IMG doesn't have a pixmap yet, load it now, using the image
8284 type dependent loader function. */
8285 if (img->pixmap == 0 && !img->load_failed_p)
8286 img->load_failed_p = img->type->load (f, img) == 0;
8287 }
8288
8289
8290 /* Value is the number of pixels for the ascent of image IMG when
8291 drawn in face FACE. */
8292
8293 int
8294 image_ascent (img, face)
8295 struct image *img;
8296 struct face *face;
8297 {
8298 int height = img->height + img->vmargin;
8299 int ascent;
8300
8301 if (img->ascent == CENTERED_IMAGE_ASCENT)
8302 {
8303 if (face->font)
8304 ascent = height / 2 - (FONT_DESCENT(face->font)
8305 - FONT_BASE(face->font)) / 2;
8306 else
8307 ascent = height / 2;
8308 }
8309 else
8310 ascent = height * img->ascent / 100.0;
8311
8312 return ascent;
8313 }
8314
8315
8316 \f
8317 /* Image background colors. */
8318
8319 static unsigned long
8320 four_corners_best (ximg, width, height)
8321 XImage *ximg;
8322 unsigned long width, height;
8323 {
8324 #if 0 /* TODO: Image support. */
8325 unsigned long corners[4], best;
8326 int i, best_count;
8327
8328 /* Get the colors at the corners of ximg. */
8329 corners[0] = XGetPixel (ximg, 0, 0);
8330 corners[1] = XGetPixel (ximg, width - 1, 0);
8331 corners[2] = XGetPixel (ximg, width - 1, height - 1);
8332 corners[3] = XGetPixel (ximg, 0, height - 1);
8333
8334 /* Choose the most frequently found color as background. */
8335 for (i = best_count = 0; i < 4; ++i)
8336 {
8337 int j, n;
8338
8339 for (j = n = 0; j < 4; ++j)
8340 if (corners[i] == corners[j])
8341 ++n;
8342
8343 if (n > best_count)
8344 best = corners[i], best_count = n;
8345 }
8346
8347 return best;
8348 #else
8349 return 0;
8350 #endif
8351 }
8352
8353 /* Return the `background' field of IMG. If IMG doesn't have one yet,
8354 it is guessed heuristically. If non-zero, XIMG is an existing XImage
8355 object to use for the heuristic. */
8356
8357 unsigned long
8358 image_background (img, f, ximg)
8359 struct image *img;
8360 struct frame *f;
8361 XImage *ximg;
8362 {
8363 if (! img->background_valid)
8364 /* IMG doesn't have a background yet, try to guess a reasonable value. */
8365 {
8366 #if 0 /* TODO: Image support. */
8367 int free_ximg = !ximg;
8368
8369 if (! ximg)
8370 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8371 0, 0, img->width, img->height, ~0, ZPixmap);
8372
8373 img->background = four_corners_best (ximg, img->width, img->height);
8374
8375 if (free_ximg)
8376 XDestroyImage (ximg);
8377
8378 img->background_valid = 1;
8379 #endif
8380 }
8381
8382 return img->background;
8383 }
8384
8385 /* Return the `background_transparent' field of IMG. If IMG doesn't
8386 have one yet, it is guessed heuristically. If non-zero, MASK is an
8387 existing XImage object to use for the heuristic. */
8388
8389 int
8390 image_background_transparent (img, f, mask)
8391 struct image *img;
8392 struct frame *f;
8393 XImage *mask;
8394 {
8395 if (! img->background_transparent_valid)
8396 /* IMG doesn't have a background yet, try to guess a reasonable value. */
8397 {
8398 #if 0 /* TODO: Image support. */
8399 if (img->mask)
8400 {
8401 int free_mask = !mask;
8402
8403 if (! mask)
8404 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
8405 0, 0, img->width, img->height, ~0, ZPixmap);
8406
8407 img->background_transparent
8408 = !four_corners_best (mask, img->width, img->height);
8409
8410 if (free_mask)
8411 XDestroyImage (mask);
8412 }
8413 else
8414 #endif
8415 img->background_transparent = 0;
8416
8417 img->background_transparent_valid = 1;
8418 }
8419
8420 return img->background_transparent;
8421 }
8422
8423 \f
8424 /***********************************************************************
8425 Helper functions for X image types
8426 ***********************************************************************/
8427
8428 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
8429 int, int));
8430 static void x_clear_image P_ ((struct frame *f, struct image *img));
8431 static unsigned long x_alloc_image_color P_ ((struct frame *f,
8432 struct image *img,
8433 Lisp_Object color_name,
8434 unsigned long dflt));
8435
8436
8437 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
8438 free the pixmap if any. MASK_P non-zero means clear the mask
8439 pixmap if any. COLORS_P non-zero means free colors allocated for
8440 the image, if any. */
8441
8442 static void
8443 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
8444 struct frame *f;
8445 struct image *img;
8446 int pixmap_p, mask_p, colors_p;
8447 {
8448 #if 0 /* TODO: W32 image support */
8449 if (pixmap_p && img->pixmap)
8450 {
8451 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8452 img->pixmap = None;
8453 img->background_valid = 0;
8454 }
8455
8456 if (mask_p && img->mask)
8457 {
8458 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8459 img->mask = None;
8460 img->background_transparent_valid = 0;
8461 }
8462
8463 if (colors_p && img->ncolors)
8464 {
8465 x_free_colors (f, img->colors, img->ncolors);
8466 xfree (img->colors);
8467 img->colors = NULL;
8468 img->ncolors = 0;
8469 }
8470 #endif
8471 }
8472
8473 /* Free X resources of image IMG which is used on frame F. */
8474
8475 static void
8476 x_clear_image (f, img)
8477 struct frame *f;
8478 struct image *img;
8479 {
8480 #if 0 /* TODO: W32 image support */
8481
8482 if (img->pixmap)
8483 {
8484 BLOCK_INPUT;
8485 XFreePixmap (NULL, img->pixmap);
8486 img->pixmap = 0;
8487 UNBLOCK_INPUT;
8488 }
8489
8490 if (img->ncolors)
8491 {
8492 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
8493
8494 /* If display has an immutable color map, freeing colors is not
8495 necessary and some servers don't allow it. So don't do it. */
8496 if (class != StaticColor
8497 && class != StaticGray
8498 && class != TrueColor)
8499 {
8500 Colormap cmap;
8501 BLOCK_INPUT;
8502 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
8503 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
8504 img->ncolors, 0);
8505 UNBLOCK_INPUT;
8506 }
8507
8508 xfree (img->colors);
8509 img->colors = NULL;
8510 img->ncolors = 0;
8511 }
8512 #endif
8513 }
8514
8515
8516 /* Allocate color COLOR_NAME for image IMG on frame F. If color
8517 cannot be allocated, use DFLT. Add a newly allocated color to
8518 IMG->colors, so that it can be freed again. Value is the pixel
8519 color. */
8520
8521 static unsigned long
8522 x_alloc_image_color (f, img, color_name, dflt)
8523 struct frame *f;
8524 struct image *img;
8525 Lisp_Object color_name;
8526 unsigned long dflt;
8527 {
8528 #if 0 /* TODO: allocing colors. */
8529 XColor color;
8530 unsigned long result;
8531
8532 xassert (STRINGP (color_name));
8533
8534 if (w32_defined_color (f, XSTRING (color_name)->data, &color, 1))
8535 {
8536 /* This isn't called frequently so we get away with simply
8537 reallocating the color vector to the needed size, here. */
8538 ++img->ncolors;
8539 img->colors =
8540 (unsigned long *) xrealloc (img->colors,
8541 img->ncolors * sizeof *img->colors);
8542 img->colors[img->ncolors - 1] = color.pixel;
8543 result = color.pixel;
8544 }
8545 else
8546 result = dflt;
8547 return result;
8548 #endif
8549 return 0;
8550 }
8551
8552
8553 \f
8554 /***********************************************************************
8555 Image Cache
8556 ***********************************************************************/
8557
8558 static void cache_image P_ ((struct frame *f, struct image *img));
8559 static void postprocess_image P_ ((struct frame *, struct image *));
8560
8561
8562 /* Return a new, initialized image cache that is allocated from the
8563 heap. Call free_image_cache to free an image cache. */
8564
8565 struct image_cache *
8566 make_image_cache ()
8567 {
8568 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
8569 int size;
8570
8571 bzero (c, sizeof *c);
8572 c->size = 50;
8573 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
8574 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
8575 c->buckets = (struct image **) xmalloc (size);
8576 bzero (c->buckets, size);
8577 return c;
8578 }
8579
8580
8581 /* Free image cache of frame F. Be aware that X frames share images
8582 caches. */
8583
8584 void
8585 free_image_cache (f)
8586 struct frame *f;
8587 {
8588 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8589 if (c)
8590 {
8591 int i;
8592
8593 /* Cache should not be referenced by any frame when freed. */
8594 xassert (c->refcount == 0);
8595
8596 for (i = 0; i < c->used; ++i)
8597 free_image (f, c->images[i]);
8598 xfree (c->images);
8599 xfree (c);
8600 xfree (c->buckets);
8601 FRAME_X_IMAGE_CACHE (f) = NULL;
8602 }
8603 }
8604
8605
8606 /* Clear image cache of frame F. FORCE_P non-zero means free all
8607 images. FORCE_P zero means clear only images that haven't been
8608 displayed for some time. Should be called from time to time to
8609 reduce the number of loaded images. If image-eviction-seconds is
8610 non-nil, this frees images in the cache which weren't displayed for
8611 at least that many seconds. */
8612
8613 void
8614 clear_image_cache (f, force_p)
8615 struct frame *f;
8616 int force_p;
8617 {
8618 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8619
8620 if (c && INTEGERP (Vimage_cache_eviction_delay))
8621 {
8622 EMACS_TIME t;
8623 unsigned long old;
8624 int i, any_freed_p = 0;
8625
8626 EMACS_GET_TIME (t);
8627 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
8628
8629 for (i = 0; i < c->used; ++i)
8630 {
8631 struct image *img = c->images[i];
8632 if (img != NULL
8633 && (force_p
8634 || (img->timestamp > old)))
8635 {
8636 free_image (f, img);
8637 any_freed_p = 1;
8638 }
8639 }
8640
8641 /* We may be clearing the image cache because, for example,
8642 Emacs was iconified for a longer period of time. In that
8643 case, current matrices may still contain references to
8644 images freed above. So, clear these matrices. */
8645 if (any_freed_p)
8646 {
8647 clear_current_matrices (f);
8648 ++windows_or_buffers_changed;
8649 }
8650 }
8651 }
8652
8653
8654 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
8655 0, 1, 0,
8656 doc: /* Clear the image cache of FRAME.
8657 FRAME nil or omitted means use the selected frame.
8658 FRAME t means clear the image caches of all frames. */)
8659 (frame)
8660 Lisp_Object frame;
8661 {
8662 if (EQ (frame, Qt))
8663 {
8664 Lisp_Object tail;
8665
8666 FOR_EACH_FRAME (tail, frame)
8667 if (FRAME_W32_P (XFRAME (frame)))
8668 clear_image_cache (XFRAME (frame), 1);
8669 }
8670 else
8671 clear_image_cache (check_x_frame (frame), 1);
8672
8673 return Qnil;
8674 }
8675
8676
8677 /* Compute masks and transform image IMG on frame F, as specified
8678 by the image's specification, */
8679
8680 static void
8681 postprocess_image (f, img)
8682 struct frame *f;
8683 struct image *img;
8684 {
8685 #if 0 /* TODO: image support. */
8686 /* Manipulation of the image's mask. */
8687 if (img->pixmap)
8688 {
8689 Lisp_Object conversion, spec;
8690 Lisp_Object mask;
8691
8692 spec = img->spec;
8693
8694 /* `:heuristic-mask t'
8695 `:mask heuristic'
8696 means build a mask heuristically.
8697 `:heuristic-mask (R G B)'
8698 `:mask (heuristic (R G B))'
8699 means build a mask from color (R G B) in the
8700 image.
8701 `:mask nil'
8702 means remove a mask, if any. */
8703
8704 mask = image_spec_value (spec, QCheuristic_mask, NULL);
8705 if (!NILP (mask))
8706 x_build_heuristic_mask (f, img, mask);
8707 else
8708 {
8709 int found_p;
8710
8711 mask = image_spec_value (spec, QCmask, &found_p);
8712
8713 if (EQ (mask, Qheuristic))
8714 x_build_heuristic_mask (f, img, Qt);
8715 else if (CONSP (mask)
8716 && EQ (XCAR (mask), Qheuristic))
8717 {
8718 if (CONSP (XCDR (mask)))
8719 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
8720 else
8721 x_build_heuristic_mask (f, img, XCDR (mask));
8722 }
8723 else if (NILP (mask) && found_p && img->mask)
8724 {
8725 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8726 img->mask = NULL;
8727 }
8728 }
8729
8730
8731 /* Should we apply an image transformation algorithm? */
8732 conversion = image_spec_value (spec, QCconversion, NULL);
8733 if (EQ (conversion, Qdisabled))
8734 x_disable_image (f, img);
8735 else if (EQ (conversion, Qlaplace))
8736 x_laplace (f, img);
8737 else if (EQ (conversion, Qemboss))
8738 x_emboss (f, img);
8739 else if (CONSP (conversion)
8740 && EQ (XCAR (conversion), Qedge_detection))
8741 {
8742 Lisp_Object tem;
8743 tem = XCDR (conversion);
8744 if (CONSP (tem))
8745 x_edge_detection (f, img,
8746 Fplist_get (tem, QCmatrix),
8747 Fplist_get (tem, QCcolor_adjustment));
8748 }
8749 }
8750 #endif
8751 }
8752
8753
8754 /* Return the id of image with Lisp specification SPEC on frame F.
8755 SPEC must be a valid Lisp image specification (see valid_image_p). */
8756
8757 int
8758 lookup_image (f, spec)
8759 struct frame *f;
8760 Lisp_Object spec;
8761 {
8762 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8763 struct image *img;
8764 int i;
8765 unsigned hash;
8766 struct gcpro gcpro1;
8767 EMACS_TIME now;
8768
8769 /* F must be a window-system frame, and SPEC must be a valid image
8770 specification. */
8771 xassert (FRAME_WINDOW_P (f));
8772 xassert (valid_image_p (spec));
8773
8774 GCPRO1 (spec);
8775
8776 /* Look up SPEC in the hash table of the image cache. */
8777 hash = sxhash (spec, 0);
8778 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
8779
8780 for (img = c->buckets[i]; img; img = img->next)
8781 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
8782 break;
8783
8784 /* If not found, create a new image and cache it. */
8785 if (img == NULL)
8786 {
8787 extern Lisp_Object Qpostscript;
8788
8789 BLOCK_INPUT;
8790 img = make_image (spec, hash);
8791 cache_image (f, img);
8792 img->load_failed_p = img->type->load (f, img) == 0;
8793
8794 /* If we can't load the image, and we don't have a width and
8795 height, use some arbitrary width and height so that we can
8796 draw a rectangle for it. */
8797 if (img->load_failed_p)
8798 {
8799 Lisp_Object value;
8800
8801 value = image_spec_value (spec, QCwidth, NULL);
8802 img->width = (INTEGERP (value)
8803 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
8804 value = image_spec_value (spec, QCheight, NULL);
8805 img->height = (INTEGERP (value)
8806 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
8807 }
8808 else
8809 {
8810 /* Handle image type independent image attributes
8811 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF',
8812 `:background COLOR'. */
8813 Lisp_Object ascent, margin, relief, bg;
8814
8815 ascent = image_spec_value (spec, QCascent, NULL);
8816 if (INTEGERP (ascent))
8817 img->ascent = XFASTINT (ascent);
8818 else if (EQ (ascent, Qcenter))
8819 img->ascent = CENTERED_IMAGE_ASCENT;
8820
8821 margin = image_spec_value (spec, QCmargin, NULL);
8822 if (INTEGERP (margin) && XINT (margin) >= 0)
8823 img->vmargin = img->hmargin = XFASTINT (margin);
8824 else if (CONSP (margin) && INTEGERP (XCAR (margin))
8825 && INTEGERP (XCDR (margin)))
8826 {
8827 if (XINT (XCAR (margin)) > 0)
8828 img->hmargin = XFASTINT (XCAR (margin));
8829 if (XINT (XCDR (margin)) > 0)
8830 img->vmargin = XFASTINT (XCDR (margin));
8831 }
8832
8833 relief = image_spec_value (spec, QCrelief, NULL);
8834 if (INTEGERP (relief))
8835 {
8836 img->relief = XINT (relief);
8837 img->hmargin += abs (img->relief);
8838 img->vmargin += abs (img->relief);
8839 }
8840
8841 if (! img->background_valid)
8842 {
8843 bg = image_spec_value (img->spec, QCbackground, NULL);
8844 if (!NILP (bg))
8845 {
8846 img->background
8847 = x_alloc_image_color (f, img, bg,
8848 FRAME_BACKGROUND_PIXEL (f));
8849 img->background_valid = 1;
8850 }
8851 }
8852
8853 /* Do image transformations and compute masks, unless we
8854 don't have the image yet. */
8855 if (!EQ (*img->type->type, Qpostscript))
8856 postprocess_image (f, img);
8857 }
8858
8859 UNBLOCK_INPUT;
8860 xassert (!interrupt_input_blocked);
8861 }
8862
8863 /* We're using IMG, so set its timestamp to `now'. */
8864 EMACS_GET_TIME (now);
8865 img->timestamp = EMACS_SECS (now);
8866
8867 UNGCPRO;
8868
8869 /* Value is the image id. */
8870 return img->id;
8871 }
8872
8873
8874 /* Cache image IMG in the image cache of frame F. */
8875
8876 static void
8877 cache_image (f, img)
8878 struct frame *f;
8879 struct image *img;
8880 {
8881 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8882 int i;
8883
8884 /* Find a free slot in c->images. */
8885 for (i = 0; i < c->used; ++i)
8886 if (c->images[i] == NULL)
8887 break;
8888
8889 /* If no free slot found, maybe enlarge c->images. */
8890 if (i == c->used && c->used == c->size)
8891 {
8892 c->size *= 2;
8893 c->images = (struct image **) xrealloc (c->images,
8894 c->size * sizeof *c->images);
8895 }
8896
8897 /* Add IMG to c->images, and assign IMG an id. */
8898 c->images[i] = img;
8899 img->id = i;
8900 if (i == c->used)
8901 ++c->used;
8902
8903 /* Add IMG to the cache's hash table. */
8904 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
8905 img->next = c->buckets[i];
8906 if (img->next)
8907 img->next->prev = img;
8908 img->prev = NULL;
8909 c->buckets[i] = img;
8910 }
8911
8912
8913 /* Call FN on every image in the image cache of frame F. Used to mark
8914 Lisp Objects in the image cache. */
8915
8916 void
8917 forall_images_in_image_cache (f, fn)
8918 struct frame *f;
8919 void (*fn) P_ ((struct image *img));
8920 {
8921 if (FRAME_LIVE_P (f) && FRAME_W32_P (f))
8922 {
8923 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8924 if (c)
8925 {
8926 int i;
8927 for (i = 0; i < c->used; ++i)
8928 if (c->images[i])
8929 fn (c->images[i]);
8930 }
8931 }
8932 }
8933
8934
8935 \f
8936 /***********************************************************************
8937 W32 support code
8938 ***********************************************************************/
8939
8940 #if 0 /* TODO: W32 specific image code. */
8941
8942 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
8943 XImage **, Pixmap *));
8944 static void x_destroy_x_image P_ ((XImage *));
8945 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
8946
8947
8948 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
8949 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
8950 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
8951 via xmalloc. Print error messages via image_error if an error
8952 occurs. Value is non-zero if successful. */
8953
8954 static int
8955 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
8956 struct frame *f;
8957 int width, height, depth;
8958 XImage **ximg;
8959 Pixmap *pixmap;
8960 {
8961 #if 0 /* TODO: Image support for W32 */
8962 Display *display = FRAME_W32_DISPLAY (f);
8963 Screen *screen = FRAME_X_SCREEN (f);
8964 Window window = FRAME_W32_WINDOW (f);
8965
8966 xassert (interrupt_input_blocked);
8967
8968 if (depth <= 0)
8969 depth = one_w32_display_info.n_cbits;
8970 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
8971 depth, ZPixmap, 0, NULL, width, height,
8972 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
8973 if (*ximg == NULL)
8974 {
8975 image_error ("Unable to allocate X image", Qnil, Qnil);
8976 return 0;
8977 }
8978
8979 /* Allocate image raster. */
8980 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
8981
8982 /* Allocate a pixmap of the same size. */
8983 *pixmap = XCreatePixmap (display, window, width, height, depth);
8984 if (*pixmap == 0)
8985 {
8986 x_destroy_x_image (*ximg);
8987 *ximg = NULL;
8988 image_error ("Unable to create X pixmap", Qnil, Qnil);
8989 return 0;
8990 }
8991 #endif
8992 return 1;
8993 }
8994
8995
8996 /* Destroy XImage XIMG. Free XIMG->data. */
8997
8998 static void
8999 x_destroy_x_image (ximg)
9000 XImage *ximg;
9001 {
9002 xassert (interrupt_input_blocked);
9003 if (ximg)
9004 {
9005 xfree (ximg->data);
9006 ximg->data = NULL;
9007 XDestroyImage (ximg);
9008 }
9009 }
9010
9011
9012 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
9013 are width and height of both the image and pixmap. */
9014
9015 static void
9016 x_put_x_image (f, ximg, pixmap, width, height)
9017 struct frame *f;
9018 XImage *ximg;
9019 Pixmap pixmap;
9020 {
9021 GC gc;
9022
9023 xassert (interrupt_input_blocked);
9024 gc = XCreateGC (NULL, pixmap, 0, NULL);
9025 XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
9026 XFreeGC (NULL, gc);
9027 }
9028
9029 #endif
9030
9031 \f
9032 /***********************************************************************
9033 File Handling
9034 ***********************************************************************/
9035
9036 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
9037 static char *slurp_file P_ ((char *, int *));
9038
9039
9040 /* Find image file FILE. Look in data-directory, then
9041 x-bitmap-file-path. Value is the full name of the file found, or
9042 nil if not found. */
9043
9044 static Lisp_Object
9045 x_find_image_file (file)
9046 Lisp_Object file;
9047 {
9048 Lisp_Object file_found, search_path;
9049 struct gcpro gcpro1, gcpro2;
9050 int fd;
9051
9052 file_found = Qnil;
9053 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
9054 GCPRO2 (file_found, search_path);
9055
9056 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
9057 fd = openp (search_path, file, Qnil, &file_found, 0);
9058
9059 if (fd == -1)
9060 file_found = Qnil;
9061 else
9062 close (fd);
9063
9064 UNGCPRO;
9065 return file_found;
9066 }
9067
9068
9069 /* Read FILE into memory. Value is a pointer to a buffer allocated
9070 with xmalloc holding FILE's contents. Value is null if an error
9071 occurred. *SIZE is set to the size of the file. */
9072
9073 static char *
9074 slurp_file (file, size)
9075 char *file;
9076 int *size;
9077 {
9078 FILE *fp = NULL;
9079 char *buf = NULL;
9080 struct stat st;
9081
9082 if (stat (file, &st) == 0
9083 && (fp = fopen (file, "r")) != NULL
9084 && (buf = (char *) xmalloc (st.st_size),
9085 fread (buf, 1, st.st_size, fp) == st.st_size))
9086 {
9087 *size = st.st_size;
9088 fclose (fp);
9089 }
9090 else
9091 {
9092 if (fp)
9093 fclose (fp);
9094 if (buf)
9095 {
9096 xfree (buf);
9097 buf = NULL;
9098 }
9099 }
9100
9101 return buf;
9102 }
9103
9104
9105 \f
9106 /***********************************************************************
9107 XBM images
9108 ***********************************************************************/
9109
9110 static int xbm_load P_ ((struct frame *f, struct image *img));
9111 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
9112 Lisp_Object file));
9113 static int xbm_image_p P_ ((Lisp_Object object));
9114 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
9115 unsigned char **));
9116
9117
9118 /* Indices of image specification fields in xbm_format, below. */
9119
9120 enum xbm_keyword_index
9121 {
9122 XBM_TYPE,
9123 XBM_FILE,
9124 XBM_WIDTH,
9125 XBM_HEIGHT,
9126 XBM_DATA,
9127 XBM_FOREGROUND,
9128 XBM_BACKGROUND,
9129 XBM_ASCENT,
9130 XBM_MARGIN,
9131 XBM_RELIEF,
9132 XBM_ALGORITHM,
9133 XBM_HEURISTIC_MASK,
9134 XBM_MASK,
9135 XBM_LAST
9136 };
9137
9138 /* Vector of image_keyword structures describing the format
9139 of valid XBM image specifications. */
9140
9141 static struct image_keyword xbm_format[XBM_LAST] =
9142 {
9143 {":type", IMAGE_SYMBOL_VALUE, 1},
9144 {":file", IMAGE_STRING_VALUE, 0},
9145 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9146 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9147 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9148 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
9149 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
9150 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9151 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9152 {":relief", IMAGE_INTEGER_VALUE, 0},
9153 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9154 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9155 };
9156
9157 /* Structure describing the image type XBM. */
9158
9159 static struct image_type xbm_type =
9160 {
9161 &Qxbm,
9162 xbm_image_p,
9163 xbm_load,
9164 x_clear_image,
9165 NULL
9166 };
9167
9168 /* Tokens returned from xbm_scan. */
9169
9170 enum xbm_token
9171 {
9172 XBM_TK_IDENT = 256,
9173 XBM_TK_NUMBER
9174 };
9175
9176
9177 /* Return non-zero if OBJECT is a valid XBM-type image specification.
9178 A valid specification is a list starting with the symbol `image'
9179 The rest of the list is a property list which must contain an
9180 entry `:type xbm..
9181
9182 If the specification specifies a file to load, it must contain
9183 an entry `:file FILENAME' where FILENAME is a string.
9184
9185 If the specification is for a bitmap loaded from memory it must
9186 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
9187 WIDTH and HEIGHT are integers > 0. DATA may be:
9188
9189 1. a string large enough to hold the bitmap data, i.e. it must
9190 have a size >= (WIDTH + 7) / 8 * HEIGHT
9191
9192 2. a bool-vector of size >= WIDTH * HEIGHT
9193
9194 3. a vector of strings or bool-vectors, one for each line of the
9195 bitmap.
9196
9197 Both the file and data forms may contain the additional entries
9198 `:background COLOR' and `:foreground COLOR'. If not present,
9199 foreground and background of the frame on which the image is
9200 displayed, is used. */
9201
9202 static int
9203 xbm_image_p (object)
9204 Lisp_Object object;
9205 {
9206 struct image_keyword kw[XBM_LAST];
9207
9208 bcopy (xbm_format, kw, sizeof kw);
9209 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
9210 return 0;
9211
9212 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
9213
9214 if (kw[XBM_FILE].count)
9215 {
9216 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
9217 return 0;
9218 }
9219 else
9220 {
9221 Lisp_Object data;
9222 int width, height;
9223
9224 /* Entries for `:width', `:height' and `:data' must be present. */
9225 if (!kw[XBM_WIDTH].count
9226 || !kw[XBM_HEIGHT].count
9227 || !kw[XBM_DATA].count)
9228 return 0;
9229
9230 data = kw[XBM_DATA].value;
9231 width = XFASTINT (kw[XBM_WIDTH].value);
9232 height = XFASTINT (kw[XBM_HEIGHT].value);
9233
9234 /* Check type of data, and width and height against contents of
9235 data. */
9236 if (VECTORP (data))
9237 {
9238 int i;
9239
9240 /* Number of elements of the vector must be >= height. */
9241 if (XVECTOR (data)->size < height)
9242 return 0;
9243
9244 /* Each string or bool-vector in data must be large enough
9245 for one line of the image. */
9246 for (i = 0; i < height; ++i)
9247 {
9248 Lisp_Object elt = XVECTOR (data)->contents[i];
9249
9250 if (STRINGP (elt))
9251 {
9252 if (XSTRING (elt)->size
9253 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
9254 return 0;
9255 }
9256 else if (BOOL_VECTOR_P (elt))
9257 {
9258 if (XBOOL_VECTOR (elt)->size < width)
9259 return 0;
9260 }
9261 else
9262 return 0;
9263 }
9264 }
9265 else if (STRINGP (data))
9266 {
9267 if (XSTRING (data)->size
9268 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
9269 return 0;
9270 }
9271 else if (BOOL_VECTOR_P (data))
9272 {
9273 if (XBOOL_VECTOR (data)->size < width * height)
9274 return 0;
9275 }
9276 else
9277 return 0;
9278 }
9279
9280 /* Baseline must be a value between 0 and 100 (a percentage). */
9281 if (kw[XBM_ASCENT].count
9282 && XFASTINT (kw[XBM_ASCENT].value) > 100)
9283 return 0;
9284
9285 return 1;
9286 }
9287
9288
9289 /* Scan a bitmap file. FP is the stream to read from. Value is
9290 either an enumerator from enum xbm_token, or a character for a
9291 single-character token, or 0 at end of file. If scanning an
9292 identifier, store the lexeme of the identifier in SVAL. If
9293 scanning a number, store its value in *IVAL. */
9294
9295 static int
9296 xbm_scan (s, end, sval, ival)
9297 char **s, *end;
9298 char *sval;
9299 int *ival;
9300 {
9301 int c;
9302
9303 loop:
9304
9305 /* Skip white space. */
9306 while (*s < end &&(c = *(*s)++, isspace (c)))
9307 ;
9308
9309 if (*s >= end)
9310 c = 0;
9311 else if (isdigit (c))
9312 {
9313 int value = 0, digit;
9314
9315 if (c == '0' && *s < end)
9316 {
9317 c = *(*s)++;
9318 if (c == 'x' || c == 'X')
9319 {
9320 while (*s < end)
9321 {
9322 c = *(*s)++;
9323 if (isdigit (c))
9324 digit = c - '0';
9325 else if (c >= 'a' && c <= 'f')
9326 digit = c - 'a' + 10;
9327 else if (c >= 'A' && c <= 'F')
9328 digit = c - 'A' + 10;
9329 else
9330 break;
9331 value = 16 * value + digit;
9332 }
9333 }
9334 else if (isdigit (c))
9335 {
9336 value = c - '0';
9337 while (*s < end
9338 && (c = *(*s)++, isdigit (c)))
9339 value = 8 * value + c - '0';
9340 }
9341 }
9342 else
9343 {
9344 value = c - '0';
9345 while (*s < end
9346 && (c = *(*s)++, isdigit (c)))
9347 value = 10 * value + c - '0';
9348 }
9349
9350 if (*s < end)
9351 *s = *s - 1;
9352 *ival = value;
9353 c = XBM_TK_NUMBER;
9354 }
9355 else if (isalpha (c) || c == '_')
9356 {
9357 *sval++ = c;
9358 while (*s < end
9359 && (c = *(*s)++, (isalnum (c) || c == '_')))
9360 *sval++ = c;
9361 *sval = 0;
9362 if (*s < end)
9363 *s = *s - 1;
9364 c = XBM_TK_IDENT;
9365 }
9366 else if (c == '/' && **s == '*')
9367 {
9368 /* C-style comment. */
9369 ++*s;
9370 while (**s && (**s != '*' || *(*s + 1) != '/'))
9371 ++*s;
9372 if (**s)
9373 {
9374 *s += 2;
9375 goto loop;
9376 }
9377 }
9378
9379 return c;
9380 }
9381
9382
9383 /* Replacement for XReadBitmapFileData which isn't available under old
9384 X versions. CONTENTS is a pointer to a buffer to parse; END is the
9385 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
9386 the image. Return in *DATA the bitmap data allocated with xmalloc.
9387 Value is non-zero if successful. DATA null means just test if
9388 CONTENTS looks like an in-memory XBM file. */
9389
9390 static int
9391 xbm_read_bitmap_data (contents, end, width, height, data)
9392 char *contents, *end;
9393 int *width, *height;
9394 unsigned char **data;
9395 {
9396 char *s = contents;
9397 char buffer[BUFSIZ];
9398 int padding_p = 0;
9399 int v10 = 0;
9400 int bytes_per_line, i, nbytes;
9401 unsigned char *p;
9402 int value;
9403 int LA1;
9404
9405 #define match() \
9406 LA1 = xbm_scan (contents, end, buffer, &value)
9407
9408 #define expect(TOKEN) \
9409 if (LA1 != (TOKEN)) \
9410 goto failure; \
9411 else \
9412 match ()
9413
9414 #define expect_ident(IDENT) \
9415 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
9416 match (); \
9417 else \
9418 goto failure
9419
9420 *width = *height = -1;
9421 if (data)
9422 *data = NULL;
9423 LA1 = xbm_scan (&s, end, buffer, &value);
9424
9425 /* Parse defines for width, height and hot-spots. */
9426 while (LA1 == '#')
9427 {
9428 match ();
9429 expect_ident ("define");
9430 expect (XBM_TK_IDENT);
9431
9432 if (LA1 == XBM_TK_NUMBER);
9433 {
9434 char *p = strrchr (buffer, '_');
9435 p = p ? p + 1 : buffer;
9436 if (strcmp (p, "width") == 0)
9437 *width = value;
9438 else if (strcmp (p, "height") == 0)
9439 *height = value;
9440 }
9441 expect (XBM_TK_NUMBER);
9442 }
9443
9444 if (*width < 0 || *height < 0)
9445 goto failure;
9446 else if (data == NULL)
9447 goto success;
9448
9449 /* Parse bits. Must start with `static'. */
9450 expect_ident ("static");
9451 if (LA1 == XBM_TK_IDENT)
9452 {
9453 if (strcmp (buffer, "unsigned") == 0)
9454 {
9455 match ();
9456 expect_ident ("char");
9457 }
9458 else if (strcmp (buffer, "short") == 0)
9459 {
9460 match ();
9461 v10 = 1;
9462 if (*width % 16 && *width % 16 < 9)
9463 padding_p = 1;
9464 }
9465 else if (strcmp (buffer, "char") == 0)
9466 match ();
9467 else
9468 goto failure;
9469 }
9470 else
9471 goto failure;
9472
9473 expect (XBM_TK_IDENT);
9474 expect ('[');
9475 expect (']');
9476 expect ('=');
9477 expect ('{');
9478
9479 bytes_per_line = (*width + 7) / 8 + padding_p;
9480 nbytes = bytes_per_line * *height;
9481 p = *data = (char *) xmalloc (nbytes);
9482
9483 if (v10)
9484 {
9485
9486 for (i = 0; i < nbytes; i += 2)
9487 {
9488 int val = value;
9489 expect (XBM_TK_NUMBER);
9490
9491 *p++ = val;
9492 if (!padding_p || ((i + 2) % bytes_per_line))
9493 *p++ = value >> 8;
9494
9495 if (LA1 == ',' || LA1 == '}')
9496 match ();
9497 else
9498 goto failure;
9499 }
9500 }
9501 else
9502 {
9503 for (i = 0; i < nbytes; ++i)
9504 {
9505 int val = value;
9506 expect (XBM_TK_NUMBER);
9507
9508 *p++ = val;
9509
9510 if (LA1 == ',' || LA1 == '}')
9511 match ();
9512 else
9513 goto failure;
9514 }
9515 }
9516
9517 success:
9518 return 1;
9519
9520 failure:
9521
9522 if (data && *data)
9523 {
9524 xfree (*data);
9525 *data = NULL;
9526 }
9527 return 0;
9528
9529 #undef match
9530 #undef expect
9531 #undef expect_ident
9532 }
9533
9534
9535 /* Load XBM image IMG which will be displayed on frame F from buffer
9536 CONTENTS. END is the end of the buffer. Value is non-zero if
9537 successful. */
9538
9539 static int
9540 xbm_load_image (f, img, contents, end)
9541 struct frame *f;
9542 struct image *img;
9543 char *contents, *end;
9544 {
9545 int rc;
9546 unsigned char *data;
9547 int success_p = 0;
9548
9549 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
9550 if (rc)
9551 {
9552 int depth = one_w32_display_info.n_cbits;
9553 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
9554 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9555 Lisp_Object value;
9556
9557 xassert (img->width > 0 && img->height > 0);
9558
9559 /* Get foreground and background colors, maybe allocate colors. */
9560 value = image_spec_value (img->spec, QCforeground, NULL);
9561 if (!NILP (value))
9562 foreground = x_alloc_image_color (f, img, value, foreground);
9563 value = image_spec_value (img->spec, QCbackground, NULL);
9564 if (!NILP (value))
9565 {
9566 background = x_alloc_image_color (f, img, value, background);
9567 img->background = background;
9568 img->background_valid = 1;
9569 }
9570
9571 #if 0 /* TODO : Port image display to W32 */
9572 img->pixmap
9573 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
9574 FRAME_W32_WINDOW (f),
9575 data,
9576 img->width, img->height,
9577 foreground, background,
9578 depth);
9579 #endif
9580 xfree (data);
9581
9582 if (img->pixmap == 0)
9583 {
9584 x_clear_image (f, img);
9585 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
9586 }
9587 else
9588 success_p = 1;
9589 }
9590 else
9591 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
9592
9593 return success_p;
9594 }
9595
9596
9597 /* Value is non-zero if DATA looks like an in-memory XBM file. */
9598
9599 static int
9600 xbm_file_p (data)
9601 Lisp_Object data;
9602 {
9603 int w, h;
9604 return (STRINGP (data)
9605 && xbm_read_bitmap_data (XSTRING (data)->data,
9606 (XSTRING (data)->data
9607 + STRING_BYTES (XSTRING (data))),
9608 &w, &h, NULL));
9609 }
9610
9611
9612 /* Fill image IMG which is used on frame F with pixmap data. Value is
9613 non-zero if successful. */
9614
9615 static int
9616 xbm_load (f, img)
9617 struct frame *f;
9618 struct image *img;
9619 {
9620 int success_p = 0;
9621 Lisp_Object file_name;
9622
9623 xassert (xbm_image_p (img->spec));
9624
9625 /* If IMG->spec specifies a file name, create a non-file spec from it. */
9626 file_name = image_spec_value (img->spec, QCfile, NULL);
9627 if (STRINGP (file_name))
9628 {
9629 Lisp_Object file;
9630 char *contents;
9631 int size;
9632 struct gcpro gcpro1;
9633
9634 file = x_find_image_file (file_name);
9635 GCPRO1 (file);
9636 if (!STRINGP (file))
9637 {
9638 image_error ("Cannot find image file `%s'", file_name, Qnil);
9639 UNGCPRO;
9640 return 0;
9641 }
9642
9643 contents = slurp_file (XSTRING (file)->data, &size);
9644 if (contents == NULL)
9645 {
9646 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
9647 UNGCPRO;
9648 return 0;
9649 }
9650
9651 success_p = xbm_load_image (f, img, contents, contents + size);
9652 UNGCPRO;
9653 }
9654 else
9655 {
9656 struct image_keyword fmt[XBM_LAST];
9657 Lisp_Object data;
9658 int depth;
9659 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
9660 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9661 char *bits;
9662 int parsed_p;
9663 int in_memory_file_p = 0;
9664
9665 /* See if data looks like an in-memory XBM file. */
9666 data = image_spec_value (img->spec, QCdata, NULL);
9667 in_memory_file_p = xbm_file_p (data);
9668
9669 /* Parse the list specification. */
9670 bcopy (xbm_format, fmt, sizeof fmt);
9671 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
9672 xassert (parsed_p);
9673
9674 /* Get specified width, and height. */
9675 if (!in_memory_file_p)
9676 {
9677 img->width = XFASTINT (fmt[XBM_WIDTH].value);
9678 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
9679 xassert (img->width > 0 && img->height > 0);
9680 }
9681 /* Get foreground and background colors, maybe allocate colors. */
9682 if (fmt[XBM_FOREGROUND].count
9683 && STRINGP (fmt[XBM_FOREGROUND].value))
9684 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
9685 foreground);
9686 if (fmt[XBM_BACKGROUND].count
9687 && STRINGP (fmt[XBM_BACKGROUND].value))
9688 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
9689 background);
9690
9691 if (in_memory_file_p)
9692 success_p = xbm_load_image (f, img, XSTRING (data)->data,
9693 (XSTRING (data)->data
9694 + STRING_BYTES (XSTRING (data))));
9695 else
9696 {
9697 if (VECTORP (data))
9698 {
9699 int i;
9700 char *p;
9701 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
9702
9703 p = bits = (char *) alloca (nbytes * img->height);
9704 for (i = 0; i < img->height; ++i, p += nbytes)
9705 {
9706 Lisp_Object line = XVECTOR (data)->contents[i];
9707 if (STRINGP (line))
9708 bcopy (XSTRING (line)->data, p, nbytes);
9709 else
9710 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
9711 }
9712 }
9713 else if (STRINGP (data))
9714 bits = XSTRING (data)->data;
9715 else
9716 bits = XBOOL_VECTOR (data)->data;
9717 #ifdef TODO /* image support. */
9718 /* Create the pixmap. */
9719 depth = one_w32_display_info.n_cbits;
9720 img->pixmap
9721 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
9722 FRAME_X_WINDOW (f),
9723 bits,
9724 img->width, img->height,
9725 foreground, background,
9726 depth);
9727 #endif
9728 if (img->pixmap)
9729 success_p = 1;
9730 else
9731 {
9732 image_error ("Unable to create pixmap for XBM image `%s'",
9733 img->spec, Qnil);
9734 x_clear_image (f, img);
9735 }
9736 }
9737 }
9738
9739 return success_p;
9740 }
9741
9742
9743 \f
9744 /***********************************************************************
9745 XPM images
9746 ***********************************************************************/
9747
9748 #if HAVE_XPM
9749
9750 static int xpm_image_p P_ ((Lisp_Object object));
9751 static int xpm_load P_ ((struct frame *f, struct image *img));
9752 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
9753
9754 #include "X11/xpm.h"
9755
9756 /* The symbol `xpm' identifying XPM-format images. */
9757
9758 Lisp_Object Qxpm;
9759
9760 /* Indices of image specification fields in xpm_format, below. */
9761
9762 enum xpm_keyword_index
9763 {
9764 XPM_TYPE,
9765 XPM_FILE,
9766 XPM_DATA,
9767 XPM_ASCENT,
9768 XPM_MARGIN,
9769 XPM_RELIEF,
9770 XPM_ALGORITHM,
9771 XPM_HEURISTIC_MASK,
9772 XPM_MASK,
9773 XPM_COLOR_SYMBOLS,
9774 XPM_BACKGROUND,
9775 XPM_LAST
9776 };
9777
9778 /* Vector of image_keyword structures describing the format
9779 of valid XPM image specifications. */
9780
9781 static struct image_keyword xpm_format[XPM_LAST] =
9782 {
9783 {":type", IMAGE_SYMBOL_VALUE, 1},
9784 {":file", IMAGE_STRING_VALUE, 0},
9785 {":data", IMAGE_STRING_VALUE, 0},
9786 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9787 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9788 {":relief", IMAGE_INTEGER_VALUE, 0},
9789 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9790 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9791 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9792 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9793 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9794 };
9795
9796 /* Structure describing the image type XBM. */
9797
9798 static struct image_type xpm_type =
9799 {
9800 &Qxpm,
9801 xpm_image_p,
9802 xpm_load,
9803 x_clear_image,
9804 NULL
9805 };
9806
9807
9808 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
9809 for XPM images. Such a list must consist of conses whose car and
9810 cdr are strings. */
9811
9812 static int
9813 xpm_valid_color_symbols_p (color_symbols)
9814 Lisp_Object color_symbols;
9815 {
9816 while (CONSP (color_symbols))
9817 {
9818 Lisp_Object sym = XCAR (color_symbols);
9819 if (!CONSP (sym)
9820 || !STRINGP (XCAR (sym))
9821 || !STRINGP (XCDR (sym)))
9822 break;
9823 color_symbols = XCDR (color_symbols);
9824 }
9825
9826 return NILP (color_symbols);
9827 }
9828
9829
9830 /* Value is non-zero if OBJECT is a valid XPM image specification. */
9831
9832 static int
9833 xpm_image_p (object)
9834 Lisp_Object object;
9835 {
9836 struct image_keyword fmt[XPM_LAST];
9837 bcopy (xpm_format, fmt, sizeof fmt);
9838 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
9839 /* Either `:file' or `:data' must be present. */
9840 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
9841 /* Either no `:color-symbols' or it's a list of conses
9842 whose car and cdr are strings. */
9843 && (fmt[XPM_COLOR_SYMBOLS].count == 0
9844 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
9845 && (fmt[XPM_ASCENT].count == 0
9846 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
9847 }
9848
9849
9850 /* Load image IMG which will be displayed on frame F. Value is
9851 non-zero if successful. */
9852
9853 static int
9854 xpm_load (f, img)
9855 struct frame *f;
9856 struct image *img;
9857 {
9858 int rc, i;
9859 XpmAttributes attrs;
9860 Lisp_Object specified_file, color_symbols;
9861
9862 /* Configure the XPM lib. Use the visual of frame F. Allocate
9863 close colors. Return colors allocated. */
9864 bzero (&attrs, sizeof attrs);
9865 attrs.visual = FRAME_X_VISUAL (f);
9866 attrs.colormap = FRAME_X_COLORMAP (f);
9867 attrs.valuemask |= XpmVisual;
9868 attrs.valuemask |= XpmColormap;
9869 attrs.valuemask |= XpmReturnAllocPixels;
9870 #ifdef XpmAllocCloseColors
9871 attrs.alloc_close_colors = 1;
9872 attrs.valuemask |= XpmAllocCloseColors;
9873 #else
9874 attrs.closeness = 600;
9875 attrs.valuemask |= XpmCloseness;
9876 #endif
9877
9878 /* If image specification contains symbolic color definitions, add
9879 these to `attrs'. */
9880 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
9881 if (CONSP (color_symbols))
9882 {
9883 Lisp_Object tail;
9884 XpmColorSymbol *xpm_syms;
9885 int i, size;
9886
9887 attrs.valuemask |= XpmColorSymbols;
9888
9889 /* Count number of symbols. */
9890 attrs.numsymbols = 0;
9891 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
9892 ++attrs.numsymbols;
9893
9894 /* Allocate an XpmColorSymbol array. */
9895 size = attrs.numsymbols * sizeof *xpm_syms;
9896 xpm_syms = (XpmColorSymbol *) alloca (size);
9897 bzero (xpm_syms, size);
9898 attrs.colorsymbols = xpm_syms;
9899
9900 /* Fill the color symbol array. */
9901 for (tail = color_symbols, i = 0;
9902 CONSP (tail);
9903 ++i, tail = XCDR (tail))
9904 {
9905 Lisp_Object name = XCAR (XCAR (tail));
9906 Lisp_Object color = XCDR (XCAR (tail));
9907 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
9908 strcpy (xpm_syms[i].name, XSTRING (name)->data);
9909 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
9910 strcpy (xpm_syms[i].value, XSTRING (color)->data);
9911 }
9912 }
9913
9914 /* Create a pixmap for the image, either from a file, or from a
9915 string buffer containing data in the same format as an XPM file. */
9916 BLOCK_INPUT;
9917 specified_file = image_spec_value (img->spec, QCfile, NULL);
9918 if (STRINGP (specified_file))
9919 {
9920 Lisp_Object file = x_find_image_file (specified_file);
9921 if (!STRINGP (file))
9922 {
9923 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9924 UNBLOCK_INPUT;
9925 return 0;
9926 }
9927
9928 rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
9929 XSTRING (file)->data, &img->pixmap, &img->mask,
9930 &attrs);
9931 }
9932 else
9933 {
9934 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
9935 rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
9936 XSTRING (buffer)->data,
9937 &img->pixmap, &img->mask,
9938 &attrs);
9939 }
9940 UNBLOCK_INPUT;
9941
9942 if (rc == XpmSuccess)
9943 {
9944 /* Remember allocated colors. */
9945 img->ncolors = attrs.nalloc_pixels;
9946 img->colors = (unsigned long *) xmalloc (img->ncolors
9947 * sizeof *img->colors);
9948 for (i = 0; i < attrs.nalloc_pixels; ++i)
9949 img->colors[i] = attrs.alloc_pixels[i];
9950
9951 img->width = attrs.width;
9952 img->height = attrs.height;
9953 xassert (img->width > 0 && img->height > 0);
9954
9955 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
9956 BLOCK_INPUT;
9957 XpmFreeAttributes (&attrs);
9958 UNBLOCK_INPUT;
9959 }
9960 else
9961 {
9962 switch (rc)
9963 {
9964 case XpmOpenFailed:
9965 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
9966 break;
9967
9968 case XpmFileInvalid:
9969 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
9970 break;
9971
9972 case XpmNoMemory:
9973 image_error ("Out of memory (%s)", img->spec, Qnil);
9974 break;
9975
9976 case XpmColorFailed:
9977 image_error ("Color allocation error (%s)", img->spec, Qnil);
9978 break;
9979
9980 default:
9981 image_error ("Unknown error (%s)", img->spec, Qnil);
9982 break;
9983 }
9984 }
9985
9986 return rc == XpmSuccess;
9987 }
9988
9989 #endif /* HAVE_XPM != 0 */
9990
9991 \f
9992 #if 0 /* TODO : Color tables on W32. */
9993 /***********************************************************************
9994 Color table
9995 ***********************************************************************/
9996
9997 /* An entry in the color table mapping an RGB color to a pixel color. */
9998
9999 struct ct_color
10000 {
10001 int r, g, b;
10002 unsigned long pixel;
10003
10004 /* Next in color table collision list. */
10005 struct ct_color *next;
10006 };
10007
10008 /* The bucket vector size to use. Must be prime. */
10009
10010 #define CT_SIZE 101
10011
10012 /* Value is a hash of the RGB color given by R, G, and B. */
10013
10014 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
10015
10016 /* The color hash table. */
10017
10018 struct ct_color **ct_table;
10019
10020 /* Number of entries in the color table. */
10021
10022 int ct_colors_allocated;
10023
10024 /* Function prototypes. */
10025
10026 static void init_color_table P_ ((void));
10027 static void free_color_table P_ ((void));
10028 static unsigned long *colors_in_color_table P_ ((int *n));
10029 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
10030 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
10031
10032
10033 /* Initialize the color table. */
10034
10035 static void
10036 init_color_table ()
10037 {
10038 int size = CT_SIZE * sizeof (*ct_table);
10039 ct_table = (struct ct_color **) xmalloc (size);
10040 bzero (ct_table, size);
10041 ct_colors_allocated = 0;
10042 }
10043
10044
10045 /* Free memory associated with the color table. */
10046
10047 static void
10048 free_color_table ()
10049 {
10050 int i;
10051 struct ct_color *p, *next;
10052
10053 for (i = 0; i < CT_SIZE; ++i)
10054 for (p = ct_table[i]; p; p = next)
10055 {
10056 next = p->next;
10057 xfree (p);
10058 }
10059
10060 xfree (ct_table);
10061 ct_table = NULL;
10062 }
10063
10064
10065 /* Value is a pixel color for RGB color R, G, B on frame F. If an
10066 entry for that color already is in the color table, return the
10067 pixel color of that entry. Otherwise, allocate a new color for R,
10068 G, B, and make an entry in the color table. */
10069
10070 static unsigned long
10071 lookup_rgb_color (f, r, g, b)
10072 struct frame *f;
10073 int r, g, b;
10074 {
10075 unsigned hash = CT_HASH_RGB (r, g, b);
10076 int i = hash % CT_SIZE;
10077 struct ct_color *p;
10078
10079 for (p = ct_table[i]; p; p = p->next)
10080 if (p->r == r && p->g == g && p->b == b)
10081 break;
10082
10083 if (p == NULL)
10084 {
10085 COLORREF color;
10086 Colormap cmap;
10087 int rc;
10088
10089 color = PALETTERGB (r, g, b);
10090
10091 ++ct_colors_allocated;
10092
10093 p = (struct ct_color *) xmalloc (sizeof *p);
10094 p->r = r;
10095 p->g = g;
10096 p->b = b;
10097 p->pixel = color;
10098 p->next = ct_table[i];
10099 ct_table[i] = p;
10100 }
10101
10102 return p->pixel;
10103 }
10104
10105
10106 /* Look up pixel color PIXEL which is used on frame F in the color
10107 table. If not already present, allocate it. Value is PIXEL. */
10108
10109 static unsigned long
10110 lookup_pixel_color (f, pixel)
10111 struct frame *f;
10112 unsigned long pixel;
10113 {
10114 int i = pixel % CT_SIZE;
10115 struct ct_color *p;
10116
10117 for (p = ct_table[i]; p; p = p->next)
10118 if (p->pixel == pixel)
10119 break;
10120
10121 if (p == NULL)
10122 {
10123 XColor color;
10124 Colormap cmap;
10125 int rc;
10126
10127 BLOCK_INPUT;
10128
10129 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
10130 color.pixel = pixel;
10131 XQueryColor (NULL, cmap, &color);
10132 rc = x_alloc_nearest_color (f, cmap, &color);
10133 UNBLOCK_INPUT;
10134
10135 if (rc)
10136 {
10137 ++ct_colors_allocated;
10138
10139 p = (struct ct_color *) xmalloc (sizeof *p);
10140 p->r = color.red;
10141 p->g = color.green;
10142 p->b = color.blue;
10143 p->pixel = pixel;
10144 p->next = ct_table[i];
10145 ct_table[i] = p;
10146 }
10147 else
10148 return FRAME_FOREGROUND_PIXEL (f);
10149 }
10150 return p->pixel;
10151 }
10152
10153
10154 /* Value is a vector of all pixel colors contained in the color table,
10155 allocated via xmalloc. Set *N to the number of colors. */
10156
10157 static unsigned long *
10158 colors_in_color_table (n)
10159 int *n;
10160 {
10161 int i, j;
10162 struct ct_color *p;
10163 unsigned long *colors;
10164
10165 if (ct_colors_allocated == 0)
10166 {
10167 *n = 0;
10168 colors = NULL;
10169 }
10170 else
10171 {
10172 colors = (unsigned long *) xmalloc (ct_colors_allocated
10173 * sizeof *colors);
10174 *n = ct_colors_allocated;
10175
10176 for (i = j = 0; i < CT_SIZE; ++i)
10177 for (p = ct_table[i]; p; p = p->next)
10178 colors[j++] = p->pixel;
10179 }
10180
10181 return colors;
10182 }
10183
10184 #endif /* TODO */
10185
10186 \f
10187 /***********************************************************************
10188 Algorithms
10189 ***********************************************************************/
10190 #if 0 /* TODO: image support. */
10191 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
10192 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
10193 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
10194
10195 /* Non-zero means draw a cross on images having `:conversion
10196 disabled'. */
10197
10198 int cross_disabled_images;
10199
10200 /* Edge detection matrices for different edge-detection
10201 strategies. */
10202
10203 static int emboss_matrix[9] = {
10204 /* x - 1 x x + 1 */
10205 2, -1, 0, /* y - 1 */
10206 -1, 0, 1, /* y */
10207 0, 1, -2 /* y + 1 */
10208 };
10209
10210 static int laplace_matrix[9] = {
10211 /* x - 1 x x + 1 */
10212 1, 0, 0, /* y - 1 */
10213 0, 0, 0, /* y */
10214 0, 0, -1 /* y + 1 */
10215 };
10216
10217 /* Value is the intensity of the color whose red/green/blue values
10218 are R, G, and B. */
10219
10220 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
10221
10222
10223 /* On frame F, return an array of XColor structures describing image
10224 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
10225 non-zero means also fill the red/green/blue members of the XColor
10226 structures. Value is a pointer to the array of XColors structures,
10227 allocated with xmalloc; it must be freed by the caller. */
10228
10229 static XColor *
10230 x_to_xcolors (f, img, rgb_p)
10231 struct frame *f;
10232 struct image *img;
10233 int rgb_p;
10234 {
10235 int x, y;
10236 XColor *colors, *p;
10237 XImage *ximg;
10238
10239 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
10240
10241 /* Get the X image IMG->pixmap. */
10242 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10243 0, 0, img->width, img->height, ~0, ZPixmap);
10244
10245 /* Fill the `pixel' members of the XColor array. I wished there
10246 were an easy and portable way to circumvent XGetPixel. */
10247 p = colors;
10248 for (y = 0; y < img->height; ++y)
10249 {
10250 XColor *row = p;
10251
10252 for (x = 0; x < img->width; ++x, ++p)
10253 p->pixel = XGetPixel (ximg, x, y);
10254
10255 if (rgb_p)
10256 x_query_colors (f, row, img->width);
10257 }
10258
10259 XDestroyImage (ximg);
10260 return colors;
10261 }
10262
10263
10264 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
10265 RGB members are set. F is the frame on which this all happens.
10266 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
10267
10268 static void
10269 x_from_xcolors (f, img, colors)
10270 struct frame *f;
10271 struct image *img;
10272 XColor *colors;
10273 {
10274 int x, y;
10275 XImage *oimg;
10276 Pixmap pixmap;
10277 XColor *p;
10278
10279 init_color_table ();
10280
10281 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
10282 &oimg, &pixmap);
10283 p = colors;
10284 for (y = 0; y < img->height; ++y)
10285 for (x = 0; x < img->width; ++x, ++p)
10286 {
10287 unsigned long pixel;
10288 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
10289 XPutPixel (oimg, x, y, pixel);
10290 }
10291
10292 xfree (colors);
10293 x_clear_image_1 (f, img, 1, 0, 1);
10294
10295 x_put_x_image (f, oimg, pixmap, img->width, img->height);
10296 x_destroy_x_image (oimg);
10297 img->pixmap = pixmap;
10298 img->colors = colors_in_color_table (&img->ncolors);
10299 free_color_table ();
10300 }
10301
10302
10303 /* On frame F, perform edge-detection on image IMG.
10304
10305 MATRIX is a nine-element array specifying the transformation
10306 matrix. See emboss_matrix for an example.
10307
10308 COLOR_ADJUST is a color adjustment added to each pixel of the
10309 outgoing image. */
10310
10311 static void
10312 x_detect_edges (f, img, matrix, color_adjust)
10313 struct frame *f;
10314 struct image *img;
10315 int matrix[9], color_adjust;
10316 {
10317 XColor *colors = x_to_xcolors (f, img, 1);
10318 XColor *new, *p;
10319 int x, y, i, sum;
10320
10321 for (i = sum = 0; i < 9; ++i)
10322 sum += abs (matrix[i]);
10323
10324 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
10325
10326 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
10327
10328 for (y = 0; y < img->height; ++y)
10329 {
10330 p = COLOR (new, 0, y);
10331 p->red = p->green = p->blue = 0xffff/2;
10332 p = COLOR (new, img->width - 1, y);
10333 p->red = p->green = p->blue = 0xffff/2;
10334 }
10335
10336 for (x = 1; x < img->width - 1; ++x)
10337 {
10338 p = COLOR (new, x, 0);
10339 p->red = p->green = p->blue = 0xffff/2;
10340 p = COLOR (new, x, img->height - 1);
10341 p->red = p->green = p->blue = 0xffff/2;
10342 }
10343
10344 for (y = 1; y < img->height - 1; ++y)
10345 {
10346 p = COLOR (new, 1, y);
10347
10348 for (x = 1; x < img->width - 1; ++x, ++p)
10349 {
10350 int r, g, b, y1, x1;
10351
10352 r = g = b = i = 0;
10353 for (y1 = y - 1; y1 < y + 2; ++y1)
10354 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
10355 if (matrix[i])
10356 {
10357 XColor *t = COLOR (colors, x1, y1);
10358 r += matrix[i] * t->red;
10359 g += matrix[i] * t->green;
10360 b += matrix[i] * t->blue;
10361 }
10362
10363 r = (r / sum + color_adjust) & 0xffff;
10364 g = (g / sum + color_adjust) & 0xffff;
10365 b = (b / sum + color_adjust) & 0xffff;
10366 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
10367 }
10368 }
10369
10370 xfree (colors);
10371 x_from_xcolors (f, img, new);
10372
10373 #undef COLOR
10374 }
10375
10376
10377 /* Perform the pre-defined `emboss' edge-detection on image IMG
10378 on frame F. */
10379
10380 static void
10381 x_emboss (f, img)
10382 struct frame *f;
10383 struct image *img;
10384 {
10385 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
10386 }
10387
10388
10389 /* Transform image IMG which is used on frame F with a Laplace
10390 edge-detection algorithm. The result is an image that can be used
10391 to draw disabled buttons, for example. */
10392
10393 static void
10394 x_laplace (f, img)
10395 struct frame *f;
10396 struct image *img;
10397 {
10398 x_detect_edges (f, img, laplace_matrix, 45000);
10399 }
10400
10401
10402 /* Perform edge-detection on image IMG on frame F, with specified
10403 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
10404
10405 MATRIX must be either
10406
10407 - a list of at least 9 numbers in row-major form
10408 - a vector of at least 9 numbers
10409
10410 COLOR_ADJUST nil means use a default; otherwise it must be a
10411 number. */
10412
10413 static void
10414 x_edge_detection (f, img, matrix, color_adjust)
10415 struct frame *f;
10416 struct image *img;
10417 Lisp_Object matrix, color_adjust;
10418 {
10419 int i = 0;
10420 int trans[9];
10421
10422 if (CONSP (matrix))
10423 {
10424 for (i = 0;
10425 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
10426 ++i, matrix = XCDR (matrix))
10427 trans[i] = XFLOATINT (XCAR (matrix));
10428 }
10429 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
10430 {
10431 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
10432 trans[i] = XFLOATINT (AREF (matrix, i));
10433 }
10434
10435 if (NILP (color_adjust))
10436 color_adjust = make_number (0xffff / 2);
10437
10438 if (i == 9 && NUMBERP (color_adjust))
10439 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
10440 }
10441
10442
10443 /* Transform image IMG on frame F so that it looks disabled. */
10444
10445 static void
10446 x_disable_image (f, img)
10447 struct frame *f;
10448 struct image *img;
10449 {
10450 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10451
10452 if (dpyinfo->n_planes >= 2)
10453 {
10454 /* Color (or grayscale). Convert to gray, and equalize. Just
10455 drawing such images with a stipple can look very odd, so
10456 we're using this method instead. */
10457 XColor *colors = x_to_xcolors (f, img, 1);
10458 XColor *p, *end;
10459 const int h = 15000;
10460 const int l = 30000;
10461
10462 for (p = colors, end = colors + img->width * img->height;
10463 p < end;
10464 ++p)
10465 {
10466 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
10467 int i2 = (0xffff - h - l) * i / 0xffff + l;
10468 p->red = p->green = p->blue = i2;
10469 }
10470
10471 x_from_xcolors (f, img, colors);
10472 }
10473
10474 /* Draw a cross over the disabled image, if we must or if we
10475 should. */
10476 if (dpyinfo->n_planes < 2 || cross_disabled_images)
10477 {
10478 Display *dpy = FRAME_X_DISPLAY (f);
10479 GC gc;
10480
10481 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
10482 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
10483 XDrawLine (dpy, img->pixmap, gc, 0, 0,
10484 img->width - 1, img->height - 1);
10485 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
10486 img->width - 1, 0);
10487 XFreeGC (dpy, gc);
10488
10489 if (img->mask)
10490 {
10491 gc = XCreateGC (dpy, img->mask, 0, NULL);
10492 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
10493 XDrawLine (dpy, img->mask, gc, 0, 0,
10494 img->width - 1, img->height - 1);
10495 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
10496 img->width - 1, 0);
10497 XFreeGC (dpy, gc);
10498 }
10499 }
10500 }
10501
10502
10503 /* Build a mask for image IMG which is used on frame F. FILE is the
10504 name of an image file, for error messages. HOW determines how to
10505 determine the background color of IMG. If it is a list '(R G B)',
10506 with R, G, and B being integers >= 0, take that as the color of the
10507 background. Otherwise, determine the background color of IMG
10508 heuristically. Value is non-zero if successful. */
10509
10510 static int
10511 x_build_heuristic_mask (f, img, how)
10512 struct frame *f;
10513 struct image *img;
10514 Lisp_Object how;
10515 {
10516 Display *dpy = FRAME_W32_DISPLAY (f);
10517 XImage *ximg, *mask_img;
10518 int x, y, rc, use_img_background;
10519 unsigned long bg = 0;
10520
10521 if (img->mask)
10522 {
10523 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
10524 img->mask = None;
10525 img->background_transparent_valid = 0;
10526 }
10527
10528 /* Create an image and pixmap serving as mask. */
10529 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
10530 &mask_img, &img->mask);
10531 if (!rc)
10532 return 0;
10533
10534 /* Get the X image of IMG->pixmap. */
10535 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
10536 ~0, ZPixmap);
10537
10538 /* Determine the background color of ximg. If HOW is `(R G B)'
10539 take that as color. Otherwise, use the image's background color. */
10540 use_img_background = 1;
10541
10542 if (CONSP (how))
10543 {
10544 int rgb[3], i;
10545
10546 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
10547 {
10548 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
10549 how = XCDR (how);
10550 }
10551
10552 if (i == 3 && NILP (how))
10553 {
10554 char color_name[30];
10555 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
10556 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
10557 use_img_background = 0;
10558 }
10559 }
10560
10561 if (use_img_background)
10562 bg = four_corners_best (ximg, img->width, img->height);
10563
10564 /* Set all bits in mask_img to 1 whose color in ximg is different
10565 from the background color bg. */
10566 for (y = 0; y < img->height; ++y)
10567 for (x = 0; x < img->width; ++x)
10568 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
10569
10570 /* Fill in the background_transparent field while we have the mask handy. */
10571 image_background_transparent (img, f, mask_img);
10572
10573 /* Put mask_img into img->mask. */
10574 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
10575 x_destroy_x_image (mask_img);
10576 XDestroyImage (ximg);
10577
10578 return 1;
10579 }
10580 #endif /* TODO */
10581
10582 \f
10583 /***********************************************************************
10584 PBM (mono, gray, color)
10585 ***********************************************************************/
10586 #ifdef HAVE_PBM
10587
10588 static int pbm_image_p P_ ((Lisp_Object object));
10589 static int pbm_load P_ ((struct frame *f, struct image *img));
10590 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
10591
10592 /* The symbol `pbm' identifying images of this type. */
10593
10594 Lisp_Object Qpbm;
10595
10596 /* Indices of image specification fields in gs_format, below. */
10597
10598 enum pbm_keyword_index
10599 {
10600 PBM_TYPE,
10601 PBM_FILE,
10602 PBM_DATA,
10603 PBM_ASCENT,
10604 PBM_MARGIN,
10605 PBM_RELIEF,
10606 PBM_ALGORITHM,
10607 PBM_HEURISTIC_MASK,
10608 PBM_MASK,
10609 PBM_FOREGROUND,
10610 PBM_BACKGROUND,
10611 PBM_LAST
10612 };
10613
10614 /* Vector of image_keyword structures describing the format
10615 of valid user-defined image specifications. */
10616
10617 static struct image_keyword pbm_format[PBM_LAST] =
10618 {
10619 {":type", IMAGE_SYMBOL_VALUE, 1},
10620 {":file", IMAGE_STRING_VALUE, 0},
10621 {":data", IMAGE_STRING_VALUE, 0},
10622 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
10623 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10624 {":relief", IMAGE_INTEGER_VALUE, 0},
10625 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10626 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10627 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10628 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
10629 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10630 };
10631
10632 /* Structure describing the image type `pbm'. */
10633
10634 static struct image_type pbm_type =
10635 {
10636 &Qpbm,
10637 pbm_image_p,
10638 pbm_load,
10639 x_clear_image,
10640 NULL
10641 };
10642
10643
10644 /* Return non-zero if OBJECT is a valid PBM image specification. */
10645
10646 static int
10647 pbm_image_p (object)
10648 Lisp_Object object;
10649 {
10650 struct image_keyword fmt[PBM_LAST];
10651
10652 bcopy (pbm_format, fmt, sizeof fmt);
10653
10654 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
10655 || (fmt[PBM_ASCENT].count
10656 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
10657 return 0;
10658
10659 /* Must specify either :data or :file. */
10660 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
10661 }
10662
10663
10664 /* Scan a decimal number from *S and return it. Advance *S while
10665 reading the number. END is the end of the string. Value is -1 at
10666 end of input. */
10667
10668 static int
10669 pbm_scan_number (s, end)
10670 unsigned char **s, *end;
10671 {
10672 int c, val = -1;
10673
10674 while (*s < end)
10675 {
10676 /* Skip white-space. */
10677 while (*s < end && (c = *(*s)++, isspace (c)))
10678 ;
10679
10680 if (c == '#')
10681 {
10682 /* Skip comment to end of line. */
10683 while (*s < end && (c = *(*s)++, c != '\n'))
10684 ;
10685 }
10686 else if (isdigit (c))
10687 {
10688 /* Read decimal number. */
10689 val = c - '0';
10690 while (*s < end && (c = *(*s)++, isdigit (c)))
10691 val = 10 * val + c - '0';
10692 break;
10693 }
10694 else
10695 break;
10696 }
10697
10698 return val;
10699 }
10700
10701
10702 /* Read FILE into memory. Value is a pointer to a buffer allocated
10703 with xmalloc holding FILE's contents. Value is null if an error
10704 occured. *SIZE is set to the size of the file. */
10705
10706 static char *
10707 pbm_read_file (file, size)
10708 Lisp_Object file;
10709 int *size;
10710 {
10711 FILE *fp = NULL;
10712 char *buf = NULL;
10713 struct stat st;
10714
10715 if (stat (XSTRING (file)->data, &st) == 0
10716 && (fp = fopen (XSTRING (file)->data, "r")) != NULL
10717 && (buf = (char *) xmalloc (st.st_size),
10718 fread (buf, 1, st.st_size, fp) == st.st_size))
10719 {
10720 *size = st.st_size;
10721 fclose (fp);
10722 }
10723 else
10724 {
10725 if (fp)
10726 fclose (fp);
10727 if (buf)
10728 {
10729 xfree (buf);
10730 buf = NULL;
10731 }
10732 }
10733
10734 return buf;
10735 }
10736
10737
10738 /* Load PBM image IMG for use on frame F. */
10739
10740 static int
10741 pbm_load (f, img)
10742 struct frame *f;
10743 struct image *img;
10744 {
10745 int raw_p, x, y;
10746 int width, height, max_color_idx = 0;
10747 XImage *ximg;
10748 Lisp_Object file, specified_file;
10749 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
10750 struct gcpro gcpro1;
10751 unsigned char *contents = NULL;
10752 unsigned char *end, *p;
10753 int size;
10754
10755 specified_file = image_spec_value (img->spec, QCfile, NULL);
10756 file = Qnil;
10757 GCPRO1 (file);
10758
10759 if (STRINGP (specified_file))
10760 {
10761 file = x_find_image_file (specified_file);
10762 if (!STRINGP (file))
10763 {
10764 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10765 UNGCPRO;
10766 return 0;
10767 }
10768
10769 contents = slurp_file (XSTRING (file)->data, &size);
10770 if (contents == NULL)
10771 {
10772 image_error ("Error reading `%s'", file, Qnil);
10773 UNGCPRO;
10774 return 0;
10775 }
10776
10777 p = contents;
10778 end = contents + size;
10779 }
10780 else
10781 {
10782 Lisp_Object data;
10783 data = image_spec_value (img->spec, QCdata, NULL);
10784 p = XSTRING (data)->data;
10785 end = p + STRING_BYTES (XSTRING (data));
10786 }
10787
10788 /* Check magic number. */
10789 if (end - p < 2 || *p++ != 'P')
10790 {
10791 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
10792 error:
10793 xfree (contents);
10794 UNGCPRO;
10795 return 0;
10796 }
10797
10798 switch (*p++)
10799 {
10800 case '1':
10801 raw_p = 0, type = PBM_MONO;
10802 break;
10803
10804 case '2':
10805 raw_p = 0, type = PBM_GRAY;
10806 break;
10807
10808 case '3':
10809 raw_p = 0, type = PBM_COLOR;
10810 break;
10811
10812 case '4':
10813 raw_p = 1, type = PBM_MONO;
10814 break;
10815
10816 case '5':
10817 raw_p = 1, type = PBM_GRAY;
10818 break;
10819
10820 case '6':
10821 raw_p = 1, type = PBM_COLOR;
10822 break;
10823
10824 default:
10825 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
10826 goto error;
10827 }
10828
10829 /* Read width, height, maximum color-component. Characters
10830 starting with `#' up to the end of a line are ignored. */
10831 width = pbm_scan_number (&p, end);
10832 height = pbm_scan_number (&p, end);
10833
10834 if (type != PBM_MONO)
10835 {
10836 max_color_idx = pbm_scan_number (&p, end);
10837 if (raw_p && max_color_idx > 255)
10838 max_color_idx = 255;
10839 }
10840
10841 if (width < 0
10842 || height < 0
10843 || (type != PBM_MONO && max_color_idx < 0))
10844 goto error;
10845
10846 if (!x_create_x_image_and_pixmap (f, width, height, 0,
10847 &ximg, &img->pixmap))
10848 goto error;
10849
10850 /* Initialize the color hash table. */
10851 init_color_table ();
10852
10853 if (type == PBM_MONO)
10854 {
10855 int c = 0, g;
10856 struct image_keyword fmt[PBM_LAST];
10857 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
10858 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
10859
10860 /* Parse the image specification. */
10861 bcopy (pbm_format, fmt, sizeof fmt);
10862 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
10863
10864 /* Get foreground and background colors, maybe allocate colors. */
10865 if (fmt[PBM_FOREGROUND].count
10866 && STRINGP (fmt[PBM_FOREGROUND].value))
10867 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
10868 if (fmt[PBM_BACKGROUND].count
10869 && STRINGP (fmt[PBM_BACKGROUND].value))
10870 {
10871 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
10872 img->background = bg;
10873 img->background_valid = 1;
10874 }
10875
10876 for (y = 0; y < height; ++y)
10877 for (x = 0; x < width; ++x)
10878 {
10879 if (raw_p)
10880 {
10881 if ((x & 7) == 0)
10882 c = *p++;
10883 g = c & 0x80;
10884 c <<= 1;
10885 }
10886 else
10887 g = pbm_scan_number (&p, end);
10888
10889 XPutPixel (ximg, x, y, g ? fg : bg);
10890 }
10891 }
10892 else
10893 {
10894 for (y = 0; y < height; ++y)
10895 for (x = 0; x < width; ++x)
10896 {
10897 int r, g, b;
10898
10899 if (type == PBM_GRAY)
10900 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
10901 else if (raw_p)
10902 {
10903 r = *p++;
10904 g = *p++;
10905 b = *p++;
10906 }
10907 else
10908 {
10909 r = pbm_scan_number (&p, end);
10910 g = pbm_scan_number (&p, end);
10911 b = pbm_scan_number (&p, end);
10912 }
10913
10914 if (r < 0 || g < 0 || b < 0)
10915 {
10916 xfree (ximg->data);
10917 ximg->data = NULL;
10918 XDestroyImage (ximg);
10919 image_error ("Invalid pixel value in image `%s'",
10920 img->spec, Qnil);
10921 goto error;
10922 }
10923
10924 /* RGB values are now in the range 0..max_color_idx.
10925 Scale this to the range 0..0xffff supported by X. */
10926 r = (double) r * 65535 / max_color_idx;
10927 g = (double) g * 65535 / max_color_idx;
10928 b = (double) b * 65535 / max_color_idx;
10929 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
10930 }
10931 }
10932
10933 /* Store in IMG->colors the colors allocated for the image, and
10934 free the color table. */
10935 img->colors = colors_in_color_table (&img->ncolors);
10936 free_color_table ();
10937
10938 /* Maybe fill in the background field while we have ximg handy. */
10939 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10940 IMAGE_BACKGROUND (img, f, ximg);
10941
10942 /* Put the image into a pixmap. */
10943 x_put_x_image (f, ximg, img->pixmap, width, height);
10944 x_destroy_x_image (ximg);
10945
10946 img->width = width;
10947 img->height = height;
10948
10949 UNGCPRO;
10950 xfree (contents);
10951 return 1;
10952 }
10953 #endif /* HAVE_PBM */
10954
10955 \f
10956 /***********************************************************************
10957 PNG
10958 ***********************************************************************/
10959
10960 #if HAVE_PNG
10961
10962 #include <png.h>
10963
10964 /* Function prototypes. */
10965
10966 static int png_image_p P_ ((Lisp_Object object));
10967 static int png_load P_ ((struct frame *f, struct image *img));
10968
10969 /* The symbol `png' identifying images of this type. */
10970
10971 Lisp_Object Qpng;
10972
10973 /* Indices of image specification fields in png_format, below. */
10974
10975 enum png_keyword_index
10976 {
10977 PNG_TYPE,
10978 PNG_DATA,
10979 PNG_FILE,
10980 PNG_ASCENT,
10981 PNG_MARGIN,
10982 PNG_RELIEF,
10983 PNG_ALGORITHM,
10984 PNG_HEURISTIC_MASK,
10985 PNG_MASK,
10986 PNG_BACKGROUND,
10987 PNG_LAST
10988 };
10989
10990 /* Vector of image_keyword structures describing the format
10991 of valid user-defined image specifications. */
10992
10993 static struct image_keyword png_format[PNG_LAST] =
10994 {
10995 {":type", IMAGE_SYMBOL_VALUE, 1},
10996 {":data", IMAGE_STRING_VALUE, 0},
10997 {":file", IMAGE_STRING_VALUE, 0},
10998 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
10999 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11000 {":relief", IMAGE_INTEGER_VALUE, 0},
11001 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11002 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11003 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11004 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11005 };
11006
11007 /* Structure describing the image type `png'. */
11008
11009 static struct image_type png_type =
11010 {
11011 &Qpng,
11012 png_image_p,
11013 png_load,
11014 x_clear_image,
11015 NULL
11016 };
11017
11018
11019 /* Return non-zero if OBJECT is a valid PNG image specification. */
11020
11021 static int
11022 png_image_p (object)
11023 Lisp_Object object;
11024 {
11025 struct image_keyword fmt[PNG_LAST];
11026 bcopy (png_format, fmt, sizeof fmt);
11027
11028 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
11029 || (fmt[PNG_ASCENT].count
11030 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
11031 return 0;
11032
11033 /* Must specify either the :data or :file keyword. */
11034 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
11035 }
11036
11037
11038 /* Error and warning handlers installed when the PNG library
11039 is initialized. */
11040
11041 static void
11042 my_png_error (png_ptr, msg)
11043 png_struct *png_ptr;
11044 char *msg;
11045 {
11046 xassert (png_ptr != NULL);
11047 image_error ("PNG error: %s", build_string (msg), Qnil);
11048 longjmp (png_ptr->jmpbuf, 1);
11049 }
11050
11051
11052 static void
11053 my_png_warning (png_ptr, msg)
11054 png_struct *png_ptr;
11055 char *msg;
11056 {
11057 xassert (png_ptr != NULL);
11058 image_error ("PNG warning: %s", build_string (msg), Qnil);
11059 }
11060
11061 /* Memory source for PNG decoding. */
11062
11063 struct png_memory_storage
11064 {
11065 unsigned char *bytes; /* The data */
11066 size_t len; /* How big is it? */
11067 int index; /* Where are we? */
11068 };
11069
11070
11071 /* Function set as reader function when reading PNG image from memory.
11072 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
11073 bytes from the input to DATA. */
11074
11075 static void
11076 png_read_from_memory (png_ptr, data, length)
11077 png_structp png_ptr;
11078 png_bytep data;
11079 png_size_t length;
11080 {
11081 struct png_memory_storage *tbr
11082 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
11083
11084 if (length > tbr->len - tbr->index)
11085 png_error (png_ptr, "Read error");
11086
11087 bcopy (tbr->bytes + tbr->index, data, length);
11088 tbr->index = tbr->index + length;
11089 }
11090
11091 /* Load PNG image IMG for use on frame F. Value is non-zero if
11092 successful. */
11093
11094 static int
11095 png_load (f, img)
11096 struct frame *f;
11097 struct image *img;
11098 {
11099 Lisp_Object file, specified_file;
11100 Lisp_Object specified_data;
11101 int x, y, i;
11102 XImage *ximg, *mask_img = NULL;
11103 struct gcpro gcpro1;
11104 png_struct *png_ptr = NULL;
11105 png_info *info_ptr = NULL, *end_info = NULL;
11106 FILE *volatile fp = NULL;
11107 png_byte sig[8];
11108 png_byte *volatile pixels = NULL;
11109 png_byte **volatile rows = NULL;
11110 png_uint_32 width, height;
11111 int bit_depth, color_type, interlace_type;
11112 png_byte channels;
11113 png_uint_32 row_bytes;
11114 int transparent_p;
11115 char *gamma_str;
11116 double screen_gamma, image_gamma;
11117 int intent;
11118 struct png_memory_storage tbr; /* Data to be read */
11119
11120 /* Find out what file to load. */
11121 specified_file = image_spec_value (img->spec, QCfile, NULL);
11122 specified_data = image_spec_value (img->spec, QCdata, NULL);
11123 file = Qnil;
11124 GCPRO1 (file);
11125
11126 if (NILP (specified_data))
11127 {
11128 file = x_find_image_file (specified_file);
11129 if (!STRINGP (file))
11130 {
11131 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11132 UNGCPRO;
11133 return 0;
11134 }
11135
11136 /* Open the image file. */
11137 fp = fopen (XSTRING (file)->data, "rb");
11138 if (!fp)
11139 {
11140 image_error ("Cannot open image file `%s'", file, Qnil);
11141 UNGCPRO;
11142 fclose (fp);
11143 return 0;
11144 }
11145
11146 /* Check PNG signature. */
11147 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
11148 || !png_check_sig (sig, sizeof sig))
11149 {
11150 image_error ("Not a PNG file:` %s'", file, Qnil);
11151 UNGCPRO;
11152 fclose (fp);
11153 return 0;
11154 }
11155 }
11156 else
11157 {
11158 /* Read from memory. */
11159 tbr.bytes = XSTRING (specified_data)->data;
11160 tbr.len = STRING_BYTES (XSTRING (specified_data));
11161 tbr.index = 0;
11162
11163 /* Check PNG signature. */
11164 if (tbr.len < sizeof sig
11165 || !png_check_sig (tbr.bytes, sizeof sig))
11166 {
11167 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
11168 UNGCPRO;
11169 return 0;
11170 }
11171
11172 /* Need to skip past the signature. */
11173 tbr.bytes += sizeof (sig);
11174 }
11175
11176 /* Initialize read and info structs for PNG lib. */
11177 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
11178 my_png_error, my_png_warning);
11179 if (!png_ptr)
11180 {
11181 if (fp) fclose (fp);
11182 UNGCPRO;
11183 return 0;
11184 }
11185
11186 info_ptr = png_create_info_struct (png_ptr);
11187 if (!info_ptr)
11188 {
11189 png_destroy_read_struct (&png_ptr, NULL, NULL);
11190 if (fp) fclose (fp);
11191 UNGCPRO;
11192 return 0;
11193 }
11194
11195 end_info = png_create_info_struct (png_ptr);
11196 if (!end_info)
11197 {
11198 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
11199 if (fp) fclose (fp);
11200 UNGCPRO;
11201 return 0;
11202 }
11203
11204 /* Set error jump-back. We come back here when the PNG library
11205 detects an error. */
11206 if (setjmp (png_ptr->jmpbuf))
11207 {
11208 error:
11209 if (png_ptr)
11210 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
11211 xfree (pixels);
11212 xfree (rows);
11213 if (fp) fclose (fp);
11214 UNGCPRO;
11215 return 0;
11216 }
11217
11218 /* Read image info. */
11219 if (!NILP (specified_data))
11220 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
11221 else
11222 png_init_io (png_ptr, fp);
11223
11224 png_set_sig_bytes (png_ptr, sizeof sig);
11225 png_read_info (png_ptr, info_ptr);
11226 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
11227 &interlace_type, NULL, NULL);
11228
11229 /* If image contains simply transparency data, we prefer to
11230 construct a clipping mask. */
11231 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
11232 transparent_p = 1;
11233 else
11234 transparent_p = 0;
11235
11236 /* This function is easier to write if we only have to handle
11237 one data format: RGB or RGBA with 8 bits per channel. Let's
11238 transform other formats into that format. */
11239
11240 /* Strip more than 8 bits per channel. */
11241 if (bit_depth == 16)
11242 png_set_strip_16 (png_ptr);
11243
11244 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
11245 if available. */
11246 png_set_expand (png_ptr);
11247
11248 /* Convert grayscale images to RGB. */
11249 if (color_type == PNG_COLOR_TYPE_GRAY
11250 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
11251 png_set_gray_to_rgb (png_ptr);
11252
11253 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
11254 gamma_str = getenv ("SCREEN_GAMMA");
11255 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
11256
11257 /* Tell the PNG lib to handle gamma correction for us. */
11258
11259 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
11260 if (png_get_sRGB (png_ptr, info_ptr, &intent))
11261 /* There is a special chunk in the image specifying the gamma. */
11262 png_set_sRGB (png_ptr, info_ptr, intent);
11263 else
11264 #endif
11265 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
11266 /* Image contains gamma information. */
11267 png_set_gamma (png_ptr, screen_gamma, image_gamma);
11268 else
11269 /* Use a default of 0.5 for the image gamma. */
11270 png_set_gamma (png_ptr, screen_gamma, 0.5);
11271
11272 /* Handle alpha channel by combining the image with a background
11273 color. Do this only if a real alpha channel is supplied. For
11274 simple transparency, we prefer a clipping mask. */
11275 if (!transparent_p)
11276 {
11277 png_color_16 *image_background;
11278 Lisp_Object specified_bg
11279 = image_spec_value (img->spec, QCbackground, NULL);
11280
11281
11282 if (STRINGP (specified_bg))
11283 /* The user specified `:background', use that. */
11284 {
11285 COLORREF color;
11286 if (w32_defined_color (f, XSTRING (specified_bg)->data, &color, 0))
11287 {
11288 png_color_16 user_bg;
11289
11290 bzero (&user_bg, sizeof user_bg);
11291 user_bg.red = color.red;
11292 user_bg.green = color.green;
11293 user_bg.blue = color.blue;
11294
11295 png_set_background (png_ptr, &user_bg,
11296 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
11297 }
11298 }
11299 else if (png_get_bKGD (png_ptr, info_ptr, &image_background))
11300 /* Image contains a background color with which to
11301 combine the image. */
11302 png_set_background (png_ptr, image_background,
11303 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
11304 else
11305 {
11306 /* Image does not contain a background color with which
11307 to combine the image data via an alpha channel. Use
11308 the frame's background instead. */
11309 XColor color;
11310 Colormap cmap;
11311 png_color_16 frame_background;
11312
11313 cmap = FRAME_X_COLORMAP (f);
11314 color.pixel = FRAME_BACKGROUND_PIXEL (f);
11315 x_query_color (f, &color);
11316
11317 bzero (&frame_background, sizeof frame_background);
11318 frame_background.red = color.red;
11319 frame_background.green = color.green;
11320 frame_background.blue = color.blue;
11321
11322 png_set_background (png_ptr, &frame_background,
11323 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
11324 }
11325 }
11326
11327 /* Update info structure. */
11328 png_read_update_info (png_ptr, info_ptr);
11329
11330 /* Get number of channels. Valid values are 1 for grayscale images
11331 and images with a palette, 2 for grayscale images with transparency
11332 information (alpha channel), 3 for RGB images, and 4 for RGB
11333 images with alpha channel, i.e. RGBA. If conversions above were
11334 sufficient we should only have 3 or 4 channels here. */
11335 channels = png_get_channels (png_ptr, info_ptr);
11336 xassert (channels == 3 || channels == 4);
11337
11338 /* Number of bytes needed for one row of the image. */
11339 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
11340
11341 /* Allocate memory for the image. */
11342 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
11343 rows = (png_byte **) xmalloc (height * sizeof *rows);
11344 for (i = 0; i < height; ++i)
11345 rows[i] = pixels + i * row_bytes;
11346
11347 /* Read the entire image. */
11348 png_read_image (png_ptr, rows);
11349 png_read_end (png_ptr, info_ptr);
11350 if (fp)
11351 {
11352 fclose (fp);
11353 fp = NULL;
11354 }
11355
11356 /* Create the X image and pixmap. */
11357 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
11358 &img->pixmap))
11359 goto error;
11360
11361 /* Create an image and pixmap serving as mask if the PNG image
11362 contains an alpha channel. */
11363 if (channels == 4
11364 && !transparent_p
11365 && !x_create_x_image_and_pixmap (f, width, height, 1,
11366 &mask_img, &img->mask))
11367 {
11368 x_destroy_x_image (ximg);
11369 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
11370 img->pixmap = 0;
11371 goto error;
11372 }
11373
11374 /* Fill the X image and mask from PNG data. */
11375 init_color_table ();
11376
11377 for (y = 0; y < height; ++y)
11378 {
11379 png_byte *p = rows[y];
11380
11381 for (x = 0; x < width; ++x)
11382 {
11383 unsigned r, g, b;
11384
11385 r = *p++ << 8;
11386 g = *p++ << 8;
11387 b = *p++ << 8;
11388 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
11389
11390 /* An alpha channel, aka mask channel, associates variable
11391 transparency with an image. Where other image formats
11392 support binary transparency---fully transparent or fully
11393 opaque---PNG allows up to 254 levels of partial transparency.
11394 The PNG library implements partial transparency by combining
11395 the image with a specified background color.
11396
11397 I'm not sure how to handle this here nicely: because the
11398 background on which the image is displayed may change, for
11399 real alpha channel support, it would be necessary to create
11400 a new image for each possible background.
11401
11402 What I'm doing now is that a mask is created if we have
11403 boolean transparency information. Otherwise I'm using
11404 the frame's background color to combine the image with. */
11405
11406 if (channels == 4)
11407 {
11408 if (mask_img)
11409 XPutPixel (mask_img, x, y, *p > 0);
11410 ++p;
11411 }
11412 }
11413 }
11414
11415 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11416 /* Set IMG's background color from the PNG image, unless the user
11417 overrode it. */
11418 {
11419 png_color_16 *bg;
11420 if (png_get_bKGD (png_ptr, info_ptr, &bg))
11421 {
11422 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
11423 img->background_valid = 1;
11424 }
11425 }
11426
11427 /* Remember colors allocated for this image. */
11428 img->colors = colors_in_color_table (&img->ncolors);
11429 free_color_table ();
11430
11431 /* Clean up. */
11432 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
11433 xfree (rows);
11434 xfree (pixels);
11435
11436 img->width = width;
11437 img->height = height;
11438
11439 /* Maybe fill in the background field while we have ximg handy. */
11440 IMAGE_BACKGROUND (img, f, ximg);
11441
11442 /* Put the image into the pixmap, then free the X image and its buffer. */
11443 x_put_x_image (f, ximg, img->pixmap, width, height);
11444 x_destroy_x_image (ximg);
11445
11446 /* Same for the mask. */
11447 if (mask_img)
11448 {
11449 /* Fill in the background_transparent field while we have the mask
11450 handy. */
11451 image_background_transparent (img, f, mask_img);
11452
11453 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
11454 x_destroy_x_image (mask_img);
11455 }
11456
11457 UNGCPRO;
11458 return 1;
11459 }
11460
11461 #endif /* HAVE_PNG != 0 */
11462
11463
11464 \f
11465 /***********************************************************************
11466 JPEG
11467 ***********************************************************************/
11468
11469 #if HAVE_JPEG
11470
11471 /* Work around a warning about HAVE_STDLIB_H being redefined in
11472 jconfig.h. */
11473 #ifdef HAVE_STDLIB_H
11474 #define HAVE_STDLIB_H_1
11475 #undef HAVE_STDLIB_H
11476 #endif /* HAVE_STLIB_H */
11477
11478 #include <jpeglib.h>
11479 #include <jerror.h>
11480 #include <setjmp.h>
11481
11482 #ifdef HAVE_STLIB_H_1
11483 #define HAVE_STDLIB_H 1
11484 #endif
11485
11486 static int jpeg_image_p P_ ((Lisp_Object object));
11487 static int jpeg_load P_ ((struct frame *f, struct image *img));
11488
11489 /* The symbol `jpeg' identifying images of this type. */
11490
11491 Lisp_Object Qjpeg;
11492
11493 /* Indices of image specification fields in gs_format, below. */
11494
11495 enum jpeg_keyword_index
11496 {
11497 JPEG_TYPE,
11498 JPEG_DATA,
11499 JPEG_FILE,
11500 JPEG_ASCENT,
11501 JPEG_MARGIN,
11502 JPEG_RELIEF,
11503 JPEG_ALGORITHM,
11504 JPEG_HEURISTIC_MASK,
11505 JPEG_MASK,
11506 JPEG_BACKGROUND,
11507 JPEG_LAST
11508 };
11509
11510 /* Vector of image_keyword structures describing the format
11511 of valid user-defined image specifications. */
11512
11513 static struct image_keyword jpeg_format[JPEG_LAST] =
11514 {
11515 {":type", IMAGE_SYMBOL_VALUE, 1},
11516 {":data", IMAGE_STRING_VALUE, 0},
11517 {":file", IMAGE_STRING_VALUE, 0},
11518 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
11519 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11520 {":relief", IMAGE_INTEGER_VALUE, 0},
11521 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11522 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11523 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11524 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11525 };
11526
11527 /* Structure describing the image type `jpeg'. */
11528
11529 static struct image_type jpeg_type =
11530 {
11531 &Qjpeg,
11532 jpeg_image_p,
11533 jpeg_load,
11534 x_clear_image,
11535 NULL
11536 };
11537
11538
11539 /* Return non-zero if OBJECT is a valid JPEG image specification. */
11540
11541 static int
11542 jpeg_image_p (object)
11543 Lisp_Object object;
11544 {
11545 struct image_keyword fmt[JPEG_LAST];
11546
11547 bcopy (jpeg_format, fmt, sizeof fmt);
11548
11549 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
11550 || (fmt[JPEG_ASCENT].count
11551 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
11552 return 0;
11553
11554 /* Must specify either the :data or :file keyword. */
11555 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
11556 }
11557
11558
11559 struct my_jpeg_error_mgr
11560 {
11561 struct jpeg_error_mgr pub;
11562 jmp_buf setjmp_buffer;
11563 };
11564
11565 static void
11566 my_error_exit (cinfo)
11567 j_common_ptr cinfo;
11568 {
11569 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
11570 longjmp (mgr->setjmp_buffer, 1);
11571 }
11572
11573 /* Init source method for JPEG data source manager. Called by
11574 jpeg_read_header() before any data is actually read. See
11575 libjpeg.doc from the JPEG lib distribution. */
11576
11577 static void
11578 our_init_source (cinfo)
11579 j_decompress_ptr cinfo;
11580 {
11581 }
11582
11583
11584 /* Fill input buffer method for JPEG data source manager. Called
11585 whenever more data is needed. We read the whole image in one step,
11586 so this only adds a fake end of input marker at the end. */
11587
11588 static boolean
11589 our_fill_input_buffer (cinfo)
11590 j_decompress_ptr cinfo;
11591 {
11592 /* Insert a fake EOI marker. */
11593 struct jpeg_source_mgr *src = cinfo->src;
11594 static JOCTET buffer[2];
11595
11596 buffer[0] = (JOCTET) 0xFF;
11597 buffer[1] = (JOCTET) JPEG_EOI;
11598
11599 src->next_input_byte = buffer;
11600 src->bytes_in_buffer = 2;
11601 return TRUE;
11602 }
11603
11604
11605 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
11606 is the JPEG data source manager. */
11607
11608 static void
11609 our_skip_input_data (cinfo, num_bytes)
11610 j_decompress_ptr cinfo;
11611 long num_bytes;
11612 {
11613 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
11614
11615 if (src)
11616 {
11617 if (num_bytes > src->bytes_in_buffer)
11618 ERREXIT (cinfo, JERR_INPUT_EOF);
11619
11620 src->bytes_in_buffer -= num_bytes;
11621 src->next_input_byte += num_bytes;
11622 }
11623 }
11624
11625
11626 /* Method to terminate data source. Called by
11627 jpeg_finish_decompress() after all data has been processed. */
11628
11629 static void
11630 our_term_source (cinfo)
11631 j_decompress_ptr cinfo;
11632 {
11633 }
11634
11635
11636 /* Set up the JPEG lib for reading an image from DATA which contains
11637 LEN bytes. CINFO is the decompression info structure created for
11638 reading the image. */
11639
11640 static void
11641 jpeg_memory_src (cinfo, data, len)
11642 j_decompress_ptr cinfo;
11643 JOCTET *data;
11644 unsigned int len;
11645 {
11646 struct jpeg_source_mgr *src;
11647
11648 if (cinfo->src == NULL)
11649 {
11650 /* First time for this JPEG object? */
11651 cinfo->src = (struct jpeg_source_mgr *)
11652 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
11653 sizeof (struct jpeg_source_mgr));
11654 src = (struct jpeg_source_mgr *) cinfo->src;
11655 src->next_input_byte = data;
11656 }
11657
11658 src = (struct jpeg_source_mgr *) cinfo->src;
11659 src->init_source = our_init_source;
11660 src->fill_input_buffer = our_fill_input_buffer;
11661 src->skip_input_data = our_skip_input_data;
11662 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
11663 src->term_source = our_term_source;
11664 src->bytes_in_buffer = len;
11665 src->next_input_byte = data;
11666 }
11667
11668
11669 /* Load image IMG for use on frame F. Patterned after example.c
11670 from the JPEG lib. */
11671
11672 static int
11673 jpeg_load (f, img)
11674 struct frame *f;
11675 struct image *img;
11676 {
11677 struct jpeg_decompress_struct cinfo;
11678 struct my_jpeg_error_mgr mgr;
11679 Lisp_Object file, specified_file;
11680 Lisp_Object specified_data;
11681 FILE * volatile fp = NULL;
11682 JSAMPARRAY buffer;
11683 int row_stride, x, y;
11684 XImage *ximg = NULL;
11685 int rc;
11686 unsigned long *colors;
11687 int width, height;
11688 struct gcpro gcpro1;
11689
11690 /* Open the JPEG file. */
11691 specified_file = image_spec_value (img->spec, QCfile, NULL);
11692 specified_data = image_spec_value (img->spec, QCdata, NULL);
11693 file = Qnil;
11694 GCPRO1 (file);
11695
11696 if (NILP (specified_data))
11697 {
11698 file = x_find_image_file (specified_file);
11699 if (!STRINGP (file))
11700 {
11701 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11702 UNGCPRO;
11703 return 0;
11704 }
11705
11706 fp = fopen (XSTRING (file)->data, "r");
11707 if (fp == NULL)
11708 {
11709 image_error ("Cannot open `%s'", file, Qnil);
11710 UNGCPRO;
11711 return 0;
11712 }
11713 }
11714
11715 /* Customize libjpeg's error handling to call my_error_exit when an
11716 error is detected. This function will perform a longjmp. */
11717 cinfo.err = jpeg_std_error (&mgr.pub);
11718 mgr.pub.error_exit = my_error_exit;
11719
11720 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
11721 {
11722 if (rc == 1)
11723 {
11724 /* Called from my_error_exit. Display a JPEG error. */
11725 char buffer[JMSG_LENGTH_MAX];
11726 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
11727 image_error ("Error reading JPEG image `%s': %s", img->spec,
11728 build_string (buffer));
11729 }
11730
11731 /* Close the input file and destroy the JPEG object. */
11732 if (fp)
11733 fclose (fp);
11734 jpeg_destroy_decompress (&cinfo);
11735
11736 /* If we already have an XImage, free that. */
11737 x_destroy_x_image (ximg);
11738
11739 /* Free pixmap and colors. */
11740 x_clear_image (f, img);
11741
11742 UNGCPRO;
11743 return 0;
11744 }
11745
11746 /* Create the JPEG decompression object. Let it read from fp.
11747 Read the JPEG image header. */
11748 jpeg_create_decompress (&cinfo);
11749
11750 if (NILP (specified_data))
11751 jpeg_stdio_src (&cinfo, fp);
11752 else
11753 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
11754 STRING_BYTES (XSTRING (specified_data)));
11755
11756 jpeg_read_header (&cinfo, TRUE);
11757
11758 /* Customize decompression so that color quantization will be used.
11759 Start decompression. */
11760 cinfo.quantize_colors = TRUE;
11761 jpeg_start_decompress (&cinfo);
11762 width = img->width = cinfo.output_width;
11763 height = img->height = cinfo.output_height;
11764
11765 /* Create X image and pixmap. */
11766 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
11767 &img->pixmap))
11768 longjmp (mgr.setjmp_buffer, 2);
11769
11770 /* Allocate colors. When color quantization is used,
11771 cinfo.actual_number_of_colors has been set with the number of
11772 colors generated, and cinfo.colormap is a two-dimensional array
11773 of color indices in the range 0..cinfo.actual_number_of_colors.
11774 No more than 255 colors will be generated. */
11775 {
11776 int i, ir, ig, ib;
11777
11778 if (cinfo.out_color_components > 2)
11779 ir = 0, ig = 1, ib = 2;
11780 else if (cinfo.out_color_components > 1)
11781 ir = 0, ig = 1, ib = 0;
11782 else
11783 ir = 0, ig = 0, ib = 0;
11784
11785 /* Use the color table mechanism because it handles colors that
11786 cannot be allocated nicely. Such colors will be replaced with
11787 a default color, and we don't have to care about which colors
11788 can be freed safely, and which can't. */
11789 init_color_table ();
11790 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
11791 * sizeof *colors);
11792
11793 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
11794 {
11795 /* Multiply RGB values with 255 because X expects RGB values
11796 in the range 0..0xffff. */
11797 int r = cinfo.colormap[ir][i] << 8;
11798 int g = cinfo.colormap[ig][i] << 8;
11799 int b = cinfo.colormap[ib][i] << 8;
11800 colors[i] = lookup_rgb_color (f, r, g, b);
11801 }
11802
11803 /* Remember those colors actually allocated. */
11804 img->colors = colors_in_color_table (&img->ncolors);
11805 free_color_table ();
11806 }
11807
11808 /* Read pixels. */
11809 row_stride = width * cinfo.output_components;
11810 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
11811 row_stride, 1);
11812 for (y = 0; y < height; ++y)
11813 {
11814 jpeg_read_scanlines (&cinfo, buffer, 1);
11815 for (x = 0; x < cinfo.output_width; ++x)
11816 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
11817 }
11818
11819 /* Clean up. */
11820 jpeg_finish_decompress (&cinfo);
11821 jpeg_destroy_decompress (&cinfo);
11822 if (fp)
11823 fclose (fp);
11824
11825 /* Maybe fill in the background field while we have ximg handy. */
11826 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11827 IMAGE_BACKGROUND (img, f, ximg);
11828
11829 /* Put the image into the pixmap. */
11830 x_put_x_image (f, ximg, img->pixmap, width, height);
11831 x_destroy_x_image (ximg);
11832 UNBLOCK_INPUT;
11833 UNGCPRO;
11834 return 1;
11835 }
11836
11837 #endif /* HAVE_JPEG */
11838
11839
11840 \f
11841 /***********************************************************************
11842 TIFF
11843 ***********************************************************************/
11844
11845 #if HAVE_TIFF
11846
11847 #include <tiffio.h>
11848
11849 static int tiff_image_p P_ ((Lisp_Object object));
11850 static int tiff_load P_ ((struct frame *f, struct image *img));
11851
11852 /* The symbol `tiff' identifying images of this type. */
11853
11854 Lisp_Object Qtiff;
11855
11856 /* Indices of image specification fields in tiff_format, below. */
11857
11858 enum tiff_keyword_index
11859 {
11860 TIFF_TYPE,
11861 TIFF_DATA,
11862 TIFF_FILE,
11863 TIFF_ASCENT,
11864 TIFF_MARGIN,
11865 TIFF_RELIEF,
11866 TIFF_ALGORITHM,
11867 TIFF_HEURISTIC_MASK,
11868 TIFF_MASK,
11869 TIFF_BACKGROUND,
11870 TIFF_LAST
11871 };
11872
11873 /* Vector of image_keyword structures describing the format
11874 of valid user-defined image specifications. */
11875
11876 static struct image_keyword tiff_format[TIFF_LAST] =
11877 {
11878 {":type", IMAGE_SYMBOL_VALUE, 1},
11879 {":data", IMAGE_STRING_VALUE, 0},
11880 {":file", IMAGE_STRING_VALUE, 0},
11881 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
11882 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11883 {":relief", IMAGE_INTEGER_VALUE, 0},
11884 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11885 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11886 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11887 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11888 };
11889
11890 /* Structure describing the image type `tiff'. */
11891
11892 static struct image_type tiff_type =
11893 {
11894 &Qtiff,
11895 tiff_image_p,
11896 tiff_load,
11897 x_clear_image,
11898 NULL
11899 };
11900
11901
11902 /* Return non-zero if OBJECT is a valid TIFF image specification. */
11903
11904 static int
11905 tiff_image_p (object)
11906 Lisp_Object object;
11907 {
11908 struct image_keyword fmt[TIFF_LAST];
11909 bcopy (tiff_format, fmt, sizeof fmt);
11910
11911 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
11912 || (fmt[TIFF_ASCENT].count
11913 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
11914 return 0;
11915
11916 /* Must specify either the :data or :file keyword. */
11917 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
11918 }
11919
11920
11921 /* Reading from a memory buffer for TIFF images Based on the PNG
11922 memory source, but we have to provide a lot of extra functions.
11923 Blah.
11924
11925 We really only need to implement read and seek, but I am not
11926 convinced that the TIFF library is smart enough not to destroy
11927 itself if we only hand it the function pointers we need to
11928 override. */
11929
11930 typedef struct
11931 {
11932 unsigned char *bytes;
11933 size_t len;
11934 int index;
11935 }
11936 tiff_memory_source;
11937
11938 static size_t
11939 tiff_read_from_memory (data, buf, size)
11940 thandle_t data;
11941 tdata_t buf;
11942 tsize_t size;
11943 {
11944 tiff_memory_source *src = (tiff_memory_source *) data;
11945
11946 if (size > src->len - src->index)
11947 return (size_t) -1;
11948 bcopy (src->bytes + src->index, buf, size);
11949 src->index += size;
11950 return size;
11951 }
11952
11953 static size_t
11954 tiff_write_from_memory (data, buf, size)
11955 thandle_t data;
11956 tdata_t buf;
11957 tsize_t size;
11958 {
11959 return (size_t) -1;
11960 }
11961
11962 static toff_t
11963 tiff_seek_in_memory (data, off, whence)
11964 thandle_t data;
11965 toff_t off;
11966 int whence;
11967 {
11968 tiff_memory_source *src = (tiff_memory_source *) data;
11969 int idx;
11970
11971 switch (whence)
11972 {
11973 case SEEK_SET: /* Go from beginning of source. */
11974 idx = off;
11975 break;
11976
11977 case SEEK_END: /* Go from end of source. */
11978 idx = src->len + off;
11979 break;
11980
11981 case SEEK_CUR: /* Go from current position. */
11982 idx = src->index + off;
11983 break;
11984
11985 default: /* Invalid `whence'. */
11986 return -1;
11987 }
11988
11989 if (idx > src->len || idx < 0)
11990 return -1;
11991
11992 src->index = idx;
11993 return src->index;
11994 }
11995
11996 static int
11997 tiff_close_memory (data)
11998 thandle_t data;
11999 {
12000 /* NOOP */
12001 return 0;
12002 }
12003
12004 static int
12005 tiff_mmap_memory (data, pbase, psize)
12006 thandle_t data;
12007 tdata_t *pbase;
12008 toff_t *psize;
12009 {
12010 /* It is already _IN_ memory. */
12011 return 0;
12012 }
12013
12014 static void
12015 tiff_unmap_memory (data, base, size)
12016 thandle_t data;
12017 tdata_t base;
12018 toff_t size;
12019 {
12020 /* We don't need to do this. */
12021 }
12022
12023 static toff_t
12024 tiff_size_of_memory (data)
12025 thandle_t data;
12026 {
12027 return ((tiff_memory_source *) data)->len;
12028 }
12029
12030
12031 static void
12032 tiff_error_handler (title, format, ap)
12033 const char *title, *format;
12034 va_list ap;
12035 {
12036 char buf[512];
12037 int len;
12038
12039 len = sprintf (buf, "TIFF error: %s ", title);
12040 vsprintf (buf + len, format, ap);
12041 add_to_log (buf, Qnil, Qnil);
12042 }
12043
12044
12045 static void
12046 tiff_warning_handler (title, format, ap)
12047 const char *title, *format;
12048 va_list ap;
12049 {
12050 char buf[512];
12051 int len;
12052
12053 len = sprintf (buf, "TIFF warning: %s ", title);
12054 vsprintf (buf + len, format, ap);
12055 add_to_log (buf, Qnil, Qnil);
12056 }
12057
12058
12059 /* Load TIFF image IMG for use on frame F. Value is non-zero if
12060 successful. */
12061
12062 static int
12063 tiff_load (f, img)
12064 struct frame *f;
12065 struct image *img;
12066 {
12067 Lisp_Object file, specified_file;
12068 Lisp_Object specified_data;
12069 TIFF *tiff;
12070 int width, height, x, y;
12071 uint32 *buf;
12072 int rc;
12073 XImage *ximg;
12074 struct gcpro gcpro1;
12075 tiff_memory_source memsrc;
12076
12077 specified_file = image_spec_value (img->spec, QCfile, NULL);
12078 specified_data = image_spec_value (img->spec, QCdata, NULL);
12079 file = Qnil;
12080 GCPRO1 (file);
12081
12082 TIFFSetErrorHandler (tiff_error_handler);
12083 TIFFSetWarningHandler (tiff_warning_handler);
12084
12085 if (NILP (specified_data))
12086 {
12087 /* Read from a file */
12088 file = x_find_image_file (specified_file);
12089 if (!STRINGP (file))
12090 {
12091 image_error ("Cannot find image file `%s'", file, Qnil);
12092 UNGCPRO;
12093 return 0;
12094 }
12095
12096 /* Try to open the image file. */
12097 tiff = TIFFOpen (XSTRING (file)->data, "r");
12098 if (tiff == NULL)
12099 {
12100 image_error ("Cannot open `%s'", file, Qnil);
12101 UNGCPRO;
12102 return 0;
12103 }
12104 }
12105 else
12106 {
12107 /* Memory source! */
12108 memsrc.bytes = XSTRING (specified_data)->data;
12109 memsrc.len = STRING_BYTES (XSTRING (specified_data));
12110 memsrc.index = 0;
12111
12112 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
12113 (TIFFReadWriteProc) tiff_read_from_memory,
12114 (TIFFReadWriteProc) tiff_write_from_memory,
12115 tiff_seek_in_memory,
12116 tiff_close_memory,
12117 tiff_size_of_memory,
12118 tiff_mmap_memory,
12119 tiff_unmap_memory);
12120
12121 if (!tiff)
12122 {
12123 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
12124 UNGCPRO;
12125 return 0;
12126 }
12127 }
12128
12129 /* Get width and height of the image, and allocate a raster buffer
12130 of width x height 32-bit values. */
12131 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
12132 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
12133 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
12134
12135 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
12136 TIFFClose (tiff);
12137 if (!rc)
12138 {
12139 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
12140 xfree (buf);
12141 UNGCPRO;
12142 return 0;
12143 }
12144
12145 /* Create the X image and pixmap. */
12146 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
12147 {
12148 xfree (buf);
12149 UNGCPRO;
12150 return 0;
12151 }
12152
12153 /* Initialize the color table. */
12154 init_color_table ();
12155
12156 /* Process the pixel raster. Origin is in the lower-left corner. */
12157 for (y = 0; y < height; ++y)
12158 {
12159 uint32 *row = buf + y * width;
12160
12161 for (x = 0; x < width; ++x)
12162 {
12163 uint32 abgr = row[x];
12164 int r = TIFFGetR (abgr) << 8;
12165 int g = TIFFGetG (abgr) << 8;
12166 int b = TIFFGetB (abgr) << 8;
12167 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
12168 }
12169 }
12170
12171 /* Remember the colors allocated for the image. Free the color table. */
12172 img->colors = colors_in_color_table (&img->ncolors);
12173 free_color_table ();
12174
12175 img->width = width;
12176 img->height = height;
12177
12178 /* Maybe fill in the background field while we have ximg handy. */
12179 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12180 IMAGE_BACKGROUND (img, f, ximg);
12181
12182 /* Put the image into the pixmap, then free the X image and its buffer. */
12183 x_put_x_image (f, ximg, img->pixmap, width, height);
12184 x_destroy_x_image (ximg);
12185 xfree (buf);
12186
12187 UNGCPRO;
12188 return 1;
12189 }
12190
12191 #endif /* HAVE_TIFF != 0 */
12192
12193
12194 \f
12195 /***********************************************************************
12196 GIF
12197 ***********************************************************************/
12198
12199 #if HAVE_GIF
12200
12201 #include <gif_lib.h>
12202
12203 static int gif_image_p P_ ((Lisp_Object object));
12204 static int gif_load P_ ((struct frame *f, struct image *img));
12205
12206 /* The symbol `gif' identifying images of this type. */
12207
12208 Lisp_Object Qgif;
12209
12210 /* Indices of image specification fields in gif_format, below. */
12211
12212 enum gif_keyword_index
12213 {
12214 GIF_TYPE,
12215 GIF_DATA,
12216 GIF_FILE,
12217 GIF_ASCENT,
12218 GIF_MARGIN,
12219 GIF_RELIEF,
12220 GIF_ALGORITHM,
12221 GIF_HEURISTIC_MASK,
12222 GIF_MASK,
12223 GIF_IMAGE,
12224 GIF_BACKGROUND,
12225 GIF_LAST
12226 };
12227
12228 /* Vector of image_keyword structures describing the format
12229 of valid user-defined image specifications. */
12230
12231 static struct image_keyword gif_format[GIF_LAST] =
12232 {
12233 {":type", IMAGE_SYMBOL_VALUE, 1},
12234 {":data", IMAGE_STRING_VALUE, 0},
12235 {":file", IMAGE_STRING_VALUE, 0},
12236 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12237 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12238 {":relief", IMAGE_INTEGER_VALUE, 0},
12239 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12240 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12241 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12242 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12243 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12244 };
12245
12246 /* Structure describing the image type `gif'. */
12247
12248 static struct image_type gif_type =
12249 {
12250 &Qgif,
12251 gif_image_p,
12252 gif_load,
12253 x_clear_image,
12254 NULL
12255 };
12256
12257 /* Return non-zero if OBJECT is a valid GIF image specification. */
12258
12259 static int
12260 gif_image_p (object)
12261 Lisp_Object object;
12262 {
12263 struct image_keyword fmt[GIF_LAST];
12264 bcopy (gif_format, fmt, sizeof fmt);
12265
12266 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
12267 || (fmt[GIF_ASCENT].count
12268 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
12269 return 0;
12270
12271 /* Must specify either the :data or :file keyword. */
12272 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
12273 }
12274
12275 /* Reading a GIF image from memory
12276 Based on the PNG memory stuff to a certain extent. */
12277
12278 typedef struct
12279 {
12280 unsigned char *bytes;
12281 size_t len;
12282 int index;
12283 }
12284 gif_memory_source;
12285
12286 /* Make the current memory source available to gif_read_from_memory.
12287 It's done this way because not all versions of libungif support
12288 a UserData field in the GifFileType structure. */
12289 static gif_memory_source *current_gif_memory_src;
12290
12291 static int
12292 gif_read_from_memory (file, buf, len)
12293 GifFileType *file;
12294 GifByteType *buf;
12295 int len;
12296 {
12297 gif_memory_source *src = current_gif_memory_src;
12298
12299 if (len > src->len - src->index)
12300 return -1;
12301
12302 bcopy (src->bytes + src->index, buf, len);
12303 src->index += len;
12304 return len;
12305 }
12306
12307
12308 /* Load GIF image IMG for use on frame F. Value is non-zero if
12309 successful. */
12310
12311 static int
12312 gif_load (f, img)
12313 struct frame *f;
12314 struct image *img;
12315 {
12316 Lisp_Object file, specified_file;
12317 Lisp_Object specified_data;
12318 int rc, width, height, x, y, i;
12319 XImage *ximg;
12320 ColorMapObject *gif_color_map;
12321 unsigned long pixel_colors[256];
12322 GifFileType *gif;
12323 struct gcpro gcpro1;
12324 Lisp_Object image;
12325 int ino, image_left, image_top, image_width, image_height;
12326 gif_memory_source memsrc;
12327 unsigned char *raster;
12328
12329 specified_file = image_spec_value (img->spec, QCfile, NULL);
12330 specified_data = image_spec_value (img->spec, QCdata, NULL);
12331 file = Qnil;
12332 GCPRO1 (file);
12333
12334 if (NILP (specified_data))
12335 {
12336 file = x_find_image_file (specified_file);
12337 if (!STRINGP (file))
12338 {
12339 image_error ("Cannot find image file `%s'", specified_file, Qnil);
12340 UNGCPRO;
12341 return 0;
12342 }
12343
12344 /* Open the GIF file. */
12345 gif = DGifOpenFileName (XSTRING (file)->data);
12346 if (gif == NULL)
12347 {
12348 image_error ("Cannot open `%s'", file, Qnil);
12349 UNGCPRO;
12350 return 0;
12351 }
12352 }
12353 else
12354 {
12355 /* Read from memory! */
12356 current_gif_memory_src = &memsrc;
12357 memsrc.bytes = XSTRING (specified_data)->data;
12358 memsrc.len = STRING_BYTES (XSTRING (specified_data));
12359 memsrc.index = 0;
12360
12361 gif = DGifOpen(&memsrc, gif_read_from_memory);
12362 if (!gif)
12363 {
12364 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
12365 UNGCPRO;
12366 return 0;
12367 }
12368 }
12369
12370 /* Read entire contents. */
12371 rc = DGifSlurp (gif);
12372 if (rc == GIF_ERROR)
12373 {
12374 image_error ("Error reading `%s'", img->spec, Qnil);
12375 DGifCloseFile (gif);
12376 UNGCPRO;
12377 return 0;
12378 }
12379
12380 image = image_spec_value (img->spec, QCindex, NULL);
12381 ino = INTEGERP (image) ? XFASTINT (image) : 0;
12382 if (ino >= gif->ImageCount)
12383 {
12384 image_error ("Invalid image number `%s' in image `%s'",
12385 image, img->spec);
12386 DGifCloseFile (gif);
12387 UNGCPRO;
12388 return 0;
12389 }
12390
12391 width = img->width = gif->SWidth;
12392 height = img->height = gif->SHeight;
12393
12394 /* Create the X image and pixmap. */
12395 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
12396 {
12397 DGifCloseFile (gif);
12398 UNGCPRO;
12399 return 0;
12400 }
12401
12402 /* Allocate colors. */
12403 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
12404 if (!gif_color_map)
12405 gif_color_map = gif->SColorMap;
12406 init_color_table ();
12407 bzero (pixel_colors, sizeof pixel_colors);
12408
12409 for (i = 0; i < gif_color_map->ColorCount; ++i)
12410 {
12411 int r = gif_color_map->Colors[i].Red << 8;
12412 int g = gif_color_map->Colors[i].Green << 8;
12413 int b = gif_color_map->Colors[i].Blue << 8;
12414 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
12415 }
12416
12417 img->colors = colors_in_color_table (&img->ncolors);
12418 free_color_table ();
12419
12420 /* Clear the part of the screen image that are not covered by
12421 the image from the GIF file. Full animated GIF support
12422 requires more than can be done here (see the gif89 spec,
12423 disposal methods). Let's simply assume that the part
12424 not covered by a sub-image is in the frame's background color. */
12425 image_top = gif->SavedImages[ino].ImageDesc.Top;
12426 image_left = gif->SavedImages[ino].ImageDesc.Left;
12427 image_width = gif->SavedImages[ino].ImageDesc.Width;
12428 image_height = gif->SavedImages[ino].ImageDesc.Height;
12429
12430 for (y = 0; y < image_top; ++y)
12431 for (x = 0; x < width; ++x)
12432 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12433
12434 for (y = image_top + image_height; y < height; ++y)
12435 for (x = 0; x < width; ++x)
12436 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12437
12438 for (y = image_top; y < image_top + image_height; ++y)
12439 {
12440 for (x = 0; x < image_left; ++x)
12441 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12442 for (x = image_left + image_width; x < width; ++x)
12443 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12444 }
12445
12446 /* Read the GIF image into the X image. We use a local variable
12447 `raster' here because RasterBits below is a char *, and invites
12448 problems with bytes >= 0x80. */
12449 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
12450
12451 if (gif->SavedImages[ino].ImageDesc.Interlace)
12452 {
12453 static int interlace_start[] = {0, 4, 2, 1};
12454 static int interlace_increment[] = {8, 8, 4, 2};
12455 int pass;
12456 int row = interlace_start[0];
12457
12458 pass = 0;
12459
12460 for (y = 0; y < image_height; y++)
12461 {
12462 if (row >= image_height)
12463 {
12464 row = interlace_start[++pass];
12465 while (row >= image_height)
12466 row = interlace_start[++pass];
12467 }
12468
12469 for (x = 0; x < image_width; x++)
12470 {
12471 int i = raster[(y * image_width) + x];
12472 XPutPixel (ximg, x + image_left, row + image_top,
12473 pixel_colors[i]);
12474 }
12475
12476 row += interlace_increment[pass];
12477 }
12478 }
12479 else
12480 {
12481 for (y = 0; y < image_height; ++y)
12482 for (x = 0; x < image_width; ++x)
12483 {
12484 int i = raster[y* image_width + x];
12485 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
12486 }
12487 }
12488
12489 DGifCloseFile (gif);
12490
12491 /* Maybe fill in the background field while we have ximg handy. */
12492 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12493 IMAGE_BACKGROUND (img, f, ximg);
12494
12495 /* Put the image into the pixmap, then free the X image and its buffer. */
12496 x_put_x_image (f, ximg, img->pixmap, width, height);
12497 x_destroy_x_image (ximg);
12498
12499 UNGCPRO;
12500 return 1;
12501 }
12502
12503 #endif /* HAVE_GIF != 0 */
12504
12505
12506 \f
12507 /***********************************************************************
12508 Ghostscript
12509 ***********************************************************************/
12510
12511 Lisp_Object Qpostscript;
12512
12513 #ifdef HAVE_GHOSTSCRIPT
12514 static int gs_image_p P_ ((Lisp_Object object));
12515 static int gs_load P_ ((struct frame *f, struct image *img));
12516 static void gs_clear_image P_ ((struct frame *f, struct image *img));
12517
12518 /* The symbol `postscript' identifying images of this type. */
12519
12520 /* Keyword symbols. */
12521
12522 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
12523
12524 /* Indices of image specification fields in gs_format, below. */
12525
12526 enum gs_keyword_index
12527 {
12528 GS_TYPE,
12529 GS_PT_WIDTH,
12530 GS_PT_HEIGHT,
12531 GS_FILE,
12532 GS_LOADER,
12533 GS_BOUNDING_BOX,
12534 GS_ASCENT,
12535 GS_MARGIN,
12536 GS_RELIEF,
12537 GS_ALGORITHM,
12538 GS_HEURISTIC_MASK,
12539 GS_MASK,
12540 GS_BACKGROUND,
12541 GS_LAST
12542 };
12543
12544 /* Vector of image_keyword structures describing the format
12545 of valid user-defined image specifications. */
12546
12547 static struct image_keyword gs_format[GS_LAST] =
12548 {
12549 {":type", IMAGE_SYMBOL_VALUE, 1},
12550 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12551 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12552 {":file", IMAGE_STRING_VALUE, 1},
12553 {":loader", IMAGE_FUNCTION_VALUE, 0},
12554 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
12555 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
12556 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12557 {":relief", IMAGE_INTEGER_VALUE, 0},
12558 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12559 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12560 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12561 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12562 };
12563
12564 /* Structure describing the image type `ghostscript'. */
12565
12566 static struct image_type gs_type =
12567 {
12568 &Qpostscript,
12569 gs_image_p,
12570 gs_load,
12571 gs_clear_image,
12572 NULL
12573 };
12574
12575
12576 /* Free X resources of Ghostscript image IMG which is used on frame F. */
12577
12578 static void
12579 gs_clear_image (f, img)
12580 struct frame *f;
12581 struct image *img;
12582 {
12583 /* IMG->data.ptr_val may contain a recorded colormap. */
12584 xfree (img->data.ptr_val);
12585 x_clear_image (f, img);
12586 }
12587
12588
12589 /* Return non-zero if OBJECT is a valid Ghostscript image
12590 specification. */
12591
12592 static int
12593 gs_image_p (object)
12594 Lisp_Object object;
12595 {
12596 struct image_keyword fmt[GS_LAST];
12597 Lisp_Object tem;
12598 int i;
12599
12600 bcopy (gs_format, fmt, sizeof fmt);
12601
12602 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
12603 || (fmt[GS_ASCENT].count
12604 && XFASTINT (fmt[GS_ASCENT].value) > 100))
12605 return 0;
12606
12607 /* Bounding box must be a list or vector containing 4 integers. */
12608 tem = fmt[GS_BOUNDING_BOX].value;
12609 if (CONSP (tem))
12610 {
12611 for (i = 0; i < 4; ++i, tem = XCDR (tem))
12612 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
12613 return 0;
12614 if (!NILP (tem))
12615 return 0;
12616 }
12617 else if (VECTORP (tem))
12618 {
12619 if (XVECTOR (tem)->size != 4)
12620 return 0;
12621 for (i = 0; i < 4; ++i)
12622 if (!INTEGERP (XVECTOR (tem)->contents[i]))
12623 return 0;
12624 }
12625 else
12626 return 0;
12627
12628 return 1;
12629 }
12630
12631
12632 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
12633 if successful. */
12634
12635 static int
12636 gs_load (f, img)
12637 struct frame *f;
12638 struct image *img;
12639 {
12640 char buffer[100];
12641 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
12642 struct gcpro gcpro1, gcpro2;
12643 Lisp_Object frame;
12644 double in_width, in_height;
12645 Lisp_Object pixel_colors = Qnil;
12646
12647 /* Compute pixel size of pixmap needed from the given size in the
12648 image specification. Sizes in the specification are in pt. 1 pt
12649 = 1/72 in, xdpi and ydpi are stored in the frame's X display
12650 info. */
12651 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
12652 in_width = XFASTINT (pt_width) / 72.0;
12653 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
12654 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
12655 in_height = XFASTINT (pt_height) / 72.0;
12656 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
12657
12658 /* Create the pixmap. */
12659 BLOCK_INPUT;
12660 xassert (img->pixmap == 0);
12661 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12662 img->width, img->height,
12663 one_w32_display_info.n_cbits);
12664 UNBLOCK_INPUT;
12665
12666 if (!img->pixmap)
12667 {
12668 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
12669 return 0;
12670 }
12671
12672 /* Call the loader to fill the pixmap. It returns a process object
12673 if successful. We do not record_unwind_protect here because
12674 other places in redisplay like calling window scroll functions
12675 don't either. Let the Lisp loader use `unwind-protect' instead. */
12676 GCPRO2 (window_and_pixmap_id, pixel_colors);
12677
12678 sprintf (buffer, "%lu %lu",
12679 (unsigned long) FRAME_W32_WINDOW (f),
12680 (unsigned long) img->pixmap);
12681 window_and_pixmap_id = build_string (buffer);
12682
12683 sprintf (buffer, "%lu %lu",
12684 FRAME_FOREGROUND_PIXEL (f),
12685 FRAME_BACKGROUND_PIXEL (f));
12686 pixel_colors = build_string (buffer);
12687
12688 XSETFRAME (frame, f);
12689 loader = image_spec_value (img->spec, QCloader, NULL);
12690 if (NILP (loader))
12691 loader = intern ("gs-load-image");
12692
12693 img->data.lisp_val = call6 (loader, frame, img->spec,
12694 make_number (img->width),
12695 make_number (img->height),
12696 window_and_pixmap_id,
12697 pixel_colors);
12698 UNGCPRO;
12699 return PROCESSP (img->data.lisp_val);
12700 }
12701
12702
12703 /* Kill the Ghostscript process that was started to fill PIXMAP on
12704 frame F. Called from XTread_socket when receiving an event
12705 telling Emacs that Ghostscript has finished drawing. */
12706
12707 void
12708 x_kill_gs_process (pixmap, f)
12709 Pixmap pixmap;
12710 struct frame *f;
12711 {
12712 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
12713 int class, i;
12714 struct image *img;
12715
12716 /* Find the image containing PIXMAP. */
12717 for (i = 0; i < c->used; ++i)
12718 if (c->images[i]->pixmap == pixmap)
12719 break;
12720
12721 /* Should someone in between have cleared the image cache, for
12722 instance, give up. */
12723 if (i == c->used)
12724 return;
12725
12726 /* Kill the GS process. We should have found PIXMAP in the image
12727 cache and its image should contain a process object. */
12728 img = c->images[i];
12729 xassert (PROCESSP (img->data.lisp_val));
12730 Fkill_process (img->data.lisp_val, Qnil);
12731 img->data.lisp_val = Qnil;
12732
12733 /* On displays with a mutable colormap, figure out the colors
12734 allocated for the image by looking at the pixels of an XImage for
12735 img->pixmap. */
12736 class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
12737 if (class != StaticColor && class != StaticGray && class != TrueColor)
12738 {
12739 XImage *ximg;
12740
12741 BLOCK_INPUT;
12742
12743 /* Try to get an XImage for img->pixmep. */
12744 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
12745 0, 0, img->width, img->height, ~0, ZPixmap);
12746 if (ximg)
12747 {
12748 int x, y;
12749
12750 /* Initialize the color table. */
12751 init_color_table ();
12752
12753 /* For each pixel of the image, look its color up in the
12754 color table. After having done so, the color table will
12755 contain an entry for each color used by the image. */
12756 for (y = 0; y < img->height; ++y)
12757 for (x = 0; x < img->width; ++x)
12758 {
12759 unsigned long pixel = XGetPixel (ximg, x, y);
12760 lookup_pixel_color (f, pixel);
12761 }
12762
12763 /* Record colors in the image. Free color table and XImage. */
12764 img->colors = colors_in_color_table (&img->ncolors);
12765 free_color_table ();
12766 XDestroyImage (ximg);
12767
12768 #if 0 /* This doesn't seem to be the case. If we free the colors
12769 here, we get a BadAccess later in x_clear_image when
12770 freeing the colors. */
12771 /* We have allocated colors once, but Ghostscript has also
12772 allocated colors on behalf of us. So, to get the
12773 reference counts right, free them once. */
12774 if (img->ncolors)
12775 x_free_colors (FRAME_W32_DISPLAY (f), cmap,
12776 img->colors, img->ncolors, 0);
12777 #endif
12778 }
12779 else
12780 image_error ("Cannot get X image of `%s'; colors will not be freed",
12781 img->spec, Qnil);
12782
12783 UNBLOCK_INPUT;
12784 }
12785
12786 /* Now that we have the pixmap, compute mask and transform the
12787 image if requested. */
12788 BLOCK_INPUT;
12789 postprocess_image (f, img);
12790 UNBLOCK_INPUT;
12791 }
12792
12793 #endif /* HAVE_GHOSTSCRIPT */
12794
12795 \f
12796 /***********************************************************************
12797 Window properties
12798 ***********************************************************************/
12799
12800 DEFUN ("x-change-window-property", Fx_change_window_property,
12801 Sx_change_window_property, 2, 3, 0,
12802 doc: /* Change window property PROP to VALUE on the X window of FRAME.
12803 PROP and VALUE must be strings. FRAME nil or omitted means use the
12804 selected frame. Value is VALUE. */)
12805 (prop, value, frame)
12806 Lisp_Object frame, prop, value;
12807 {
12808 #if 0 /* TODO : port window properties to W32 */
12809 struct frame *f = check_x_frame (frame);
12810 Atom prop_atom;
12811
12812 CHECK_STRING (prop);
12813 CHECK_STRING (value);
12814
12815 BLOCK_INPUT;
12816 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
12817 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12818 prop_atom, XA_STRING, 8, PropModeReplace,
12819 XSTRING (value)->data, XSTRING (value)->size);
12820
12821 /* Make sure the property is set when we return. */
12822 XFlush (FRAME_W32_DISPLAY (f));
12823 UNBLOCK_INPUT;
12824
12825 #endif /* TODO */
12826
12827 return value;
12828 }
12829
12830
12831 DEFUN ("x-delete-window-property", Fx_delete_window_property,
12832 Sx_delete_window_property, 1, 2, 0,
12833 doc: /* Remove window property PROP from X window of FRAME.
12834 FRAME nil or omitted means use the selected frame. Value is PROP. */)
12835 (prop, frame)
12836 Lisp_Object prop, frame;
12837 {
12838 #if 0 /* TODO : port window properties to W32 */
12839
12840 struct frame *f = check_x_frame (frame);
12841 Atom prop_atom;
12842
12843 CHECK_STRING (prop);
12844 BLOCK_INPUT;
12845 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
12846 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
12847
12848 /* Make sure the property is removed when we return. */
12849 XFlush (FRAME_W32_DISPLAY (f));
12850 UNBLOCK_INPUT;
12851 #endif /* TODO */
12852
12853 return prop;
12854 }
12855
12856
12857 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
12858 1, 2, 0,
12859 doc: /* Value is the value of window property PROP on FRAME.
12860 If FRAME is nil or omitted, use the selected frame. Value is nil
12861 if FRAME hasn't a property with name PROP or if PROP has no string
12862 value. */)
12863 (prop, frame)
12864 Lisp_Object prop, frame;
12865 {
12866 #if 0 /* TODO : port window properties to W32 */
12867
12868 struct frame *f = check_x_frame (frame);
12869 Atom prop_atom;
12870 int rc;
12871 Lisp_Object prop_value = Qnil;
12872 char *tmp_data = NULL;
12873 Atom actual_type;
12874 int actual_format;
12875 unsigned long actual_size, bytes_remaining;
12876
12877 CHECK_STRING (prop);
12878 BLOCK_INPUT;
12879 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
12880 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12881 prop_atom, 0, 0, False, XA_STRING,
12882 &actual_type, &actual_format, &actual_size,
12883 &bytes_remaining, (unsigned char **) &tmp_data);
12884 if (rc == Success)
12885 {
12886 int size = bytes_remaining;
12887
12888 XFree (tmp_data);
12889 tmp_data = NULL;
12890
12891 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12892 prop_atom, 0, bytes_remaining,
12893 False, XA_STRING,
12894 &actual_type, &actual_format,
12895 &actual_size, &bytes_remaining,
12896 (unsigned char **) &tmp_data);
12897 if (rc == Success)
12898 prop_value = make_string (tmp_data, size);
12899
12900 XFree (tmp_data);
12901 }
12902
12903 UNBLOCK_INPUT;
12904
12905 return prop_value;
12906
12907 #endif /* TODO */
12908 return Qnil;
12909 }
12910
12911
12912 \f
12913 /***********************************************************************
12914 Busy cursor
12915 ***********************************************************************/
12916
12917 /* If non-null, an asynchronous timer that, when it expires, displays
12918 an hourglass cursor on all frames. */
12919
12920 static struct atimer *hourglass_atimer;
12921
12922 /* Non-zero means an hourglass cursor is currently shown. */
12923
12924 static int hourglass_shown_p;
12925
12926 /* Number of seconds to wait before displaying an hourglass cursor. */
12927
12928 static Lisp_Object Vhourglass_delay;
12929
12930 /* Default number of seconds to wait before displaying an hourglass
12931 cursor. */
12932
12933 #define DEFAULT_HOURGLASS_DELAY 1
12934
12935 /* Function prototypes. */
12936
12937 static void show_hourglass P_ ((struct atimer *));
12938 static void hide_hourglass P_ ((void));
12939
12940
12941 /* Cancel a currently active hourglass timer, and start a new one. */
12942
12943 void
12944 start_hourglass ()
12945 {
12946 #if 0 /* TODO: cursor shape changes. */
12947 EMACS_TIME delay;
12948 int secs, usecs = 0;
12949
12950 cancel_hourglass ();
12951
12952 if (INTEGERP (Vhourglass_delay)
12953 && XINT (Vhourglass_delay) > 0)
12954 secs = XFASTINT (Vhourglass_delay);
12955 else if (FLOATP (Vhourglass_delay)
12956 && XFLOAT_DATA (Vhourglass_delay) > 0)
12957 {
12958 Lisp_Object tem;
12959 tem = Ftruncate (Vhourglass_delay, Qnil);
12960 secs = XFASTINT (tem);
12961 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
12962 }
12963 else
12964 secs = DEFAULT_HOURGLASS_DELAY;
12965
12966 EMACS_SET_SECS_USECS (delay, secs, usecs);
12967 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
12968 show_hourglass, NULL);
12969 #endif
12970 }
12971
12972
12973 /* Cancel the hourglass cursor timer if active, hide an hourglass
12974 cursor if shown. */
12975
12976 void
12977 cancel_hourglass ()
12978 {
12979 if (hourglass_atimer)
12980 {
12981 cancel_atimer (hourglass_atimer);
12982 hourglass_atimer = NULL;
12983 }
12984
12985 if (hourglass_shown_p)
12986 hide_hourglass ();
12987 }
12988
12989
12990 /* Timer function of hourglass_atimer. TIMER is equal to
12991 hourglass_atimer.
12992
12993 Display an hourglass cursor on all frames by mapping the frames'
12994 hourglass_window. Set the hourglass_p flag in the frames'
12995 output_data.x structure to indicate that an hourglass cursor is
12996 shown on the frames. */
12997
12998 static void
12999 show_hourglass (timer)
13000 struct atimer *timer;
13001 {
13002 #if 0 /* TODO: cursor shape changes. */
13003 /* The timer implementation will cancel this timer automatically
13004 after this function has run. Set hourglass_atimer to null
13005 so that we know the timer doesn't have to be canceled. */
13006 hourglass_atimer = NULL;
13007
13008 if (!hourglass_shown_p)
13009 {
13010 Lisp_Object rest, frame;
13011
13012 BLOCK_INPUT;
13013
13014 FOR_EACH_FRAME (rest, frame)
13015 if (FRAME_W32_P (XFRAME (frame)))
13016 {
13017 struct frame *f = XFRAME (frame);
13018
13019 f->output_data.w32->hourglass_p = 1;
13020
13021 if (!f->output_data.w32->hourglass_window)
13022 {
13023 unsigned long mask = CWCursor;
13024 XSetWindowAttributes attrs;
13025
13026 attrs.cursor = f->output_data.w32->hourglass_cursor;
13027
13028 f->output_data.w32->hourglass_window
13029 = XCreateWindow (FRAME_X_DISPLAY (f),
13030 FRAME_OUTER_WINDOW (f),
13031 0, 0, 32000, 32000, 0, 0,
13032 InputOnly,
13033 CopyFromParent,
13034 mask, &attrs);
13035 }
13036
13037 XMapRaised (FRAME_X_DISPLAY (f),
13038 f->output_data.w32->hourglass_window);
13039 XFlush (FRAME_X_DISPLAY (f));
13040 }
13041
13042 hourglass_shown_p = 1;
13043 UNBLOCK_INPUT;
13044 }
13045 #endif
13046 }
13047
13048
13049 /* Hide the hourglass cursor on all frames, if it is currently shown. */
13050
13051 static void
13052 hide_hourglass ()
13053 {
13054 #if 0 /* TODO: cursor shape changes. */
13055 if (hourglass_shown_p)
13056 {
13057 Lisp_Object rest, frame;
13058
13059 BLOCK_INPUT;
13060 FOR_EACH_FRAME (rest, frame)
13061 {
13062 struct frame *f = XFRAME (frame);
13063
13064 if (FRAME_W32_P (f)
13065 /* Watch out for newly created frames. */
13066 && f->output_data.x->hourglass_window)
13067 {
13068 XUnmapWindow (FRAME_X_DISPLAY (f),
13069 f->output_data.x->hourglass_window);
13070 /* Sync here because XTread_socket looks at the
13071 hourglass_p flag that is reset to zero below. */
13072 XSync (FRAME_X_DISPLAY (f), False);
13073 f->output_data.x->hourglass_p = 0;
13074 }
13075 }
13076
13077 hourglass_shown_p = 0;
13078 UNBLOCK_INPUT;
13079 }
13080 #endif
13081 }
13082
13083
13084 \f
13085 /***********************************************************************
13086 Tool tips
13087 ***********************************************************************/
13088
13089 static Lisp_Object x_create_tip_frame P_ ((struct w32_display_info *,
13090 Lisp_Object, Lisp_Object));
13091 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
13092 Lisp_Object, int, int, int *, int *));
13093
13094 /* The frame of a currently visible tooltip. */
13095
13096 Lisp_Object tip_frame;
13097
13098 /* If non-nil, a timer started that hides the last tooltip when it
13099 fires. */
13100
13101 Lisp_Object tip_timer;
13102 Window tip_window;
13103
13104 /* If non-nil, a vector of 3 elements containing the last args
13105 with which x-show-tip was called. See there. */
13106
13107 Lisp_Object last_show_tip_args;
13108
13109 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
13110
13111 Lisp_Object Vx_max_tooltip_size;
13112
13113
13114 static Lisp_Object
13115 unwind_create_tip_frame (frame)
13116 Lisp_Object frame;
13117 {
13118 Lisp_Object deleted;
13119
13120 deleted = unwind_create_frame (frame);
13121 if (EQ (deleted, Qt))
13122 {
13123 tip_window = NULL;
13124 tip_frame = Qnil;
13125 }
13126
13127 return deleted;
13128 }
13129
13130
13131 /* Create a frame for a tooltip on the display described by DPYINFO.
13132 PARMS is a list of frame parameters. TEXT is the string to
13133 display in the tip frame. Value is the frame.
13134
13135 Note that functions called here, esp. x_default_parameter can
13136 signal errors, for instance when a specified color name is
13137 undefined. We have to make sure that we're in a consistent state
13138 when this happens. */
13139
13140 static Lisp_Object
13141 x_create_tip_frame (dpyinfo, parms, text)
13142 struct w32_display_info *dpyinfo;
13143 Lisp_Object parms, text;
13144 {
13145 struct frame *f;
13146 Lisp_Object frame, tem;
13147 Lisp_Object name;
13148 long window_prompting = 0;
13149 int width, height;
13150 int count = BINDING_STACK_SIZE ();
13151 struct gcpro gcpro1, gcpro2, gcpro3;
13152 struct kboard *kb;
13153 int face_change_count_before = face_change_count;
13154 Lisp_Object buffer;
13155 struct buffer *old_buffer;
13156
13157 check_w32 ();
13158
13159 /* Use this general default value to start with until we know if
13160 this frame has a specified name. */
13161 Vx_resource_name = Vinvocation_name;
13162
13163 #ifdef MULTI_KBOARD
13164 kb = dpyinfo->kboard;
13165 #else
13166 kb = &the_only_kboard;
13167 #endif
13168
13169 /* Get the name of the frame to use for resource lookup. */
13170 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
13171 if (!STRINGP (name)
13172 && !EQ (name, Qunbound)
13173 && !NILP (name))
13174 error ("Invalid frame name--not a string or nil");
13175 Vx_resource_name = name;
13176
13177 frame = Qnil;
13178 GCPRO3 (parms, name, frame);
13179 /* Make a frame without minibuffer nor mode-line. */
13180 f = make_frame (0);
13181 f->wants_modeline = 0;
13182 XSETFRAME (frame, f);
13183
13184 buffer = Fget_buffer_create (build_string (" *tip*"));
13185 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
13186 old_buffer = current_buffer;
13187 set_buffer_internal_1 (XBUFFER (buffer));
13188 current_buffer->truncate_lines = Qnil;
13189 Ferase_buffer ();
13190 Finsert (1, &text);
13191 set_buffer_internal_1 (old_buffer);
13192
13193 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
13194 record_unwind_protect (unwind_create_tip_frame, frame);
13195
13196 /* By setting the output method, we're essentially saying that
13197 the frame is live, as per FRAME_LIVE_P. If we get a signal
13198 from this point on, x_destroy_window might screw up reference
13199 counts etc. */
13200 f->output_method = output_w32;
13201 f->output_data.w32 =
13202 (struct w32_output *) xmalloc (sizeof (struct w32_output));
13203 bzero (f->output_data.w32, sizeof (struct w32_output));
13204
13205 FRAME_FONTSET (f) = -1;
13206 f->icon_name = Qnil;
13207
13208 #if 0 /* GLYPH_DEBUG TODO: image support. */
13209 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
13210 dpyinfo_refcount = dpyinfo->reference_count;
13211 #endif /* GLYPH_DEBUG */
13212 #ifdef MULTI_KBOARD
13213 FRAME_KBOARD (f) = kb;
13214 #endif
13215 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
13216 f->output_data.w32->explicit_parent = 0;
13217
13218 /* Set the name; the functions to which we pass f expect the name to
13219 be set. */
13220 if (EQ (name, Qunbound) || NILP (name))
13221 {
13222 f->name = build_string (dpyinfo->w32_id_name);
13223 f->explicit_name = 0;
13224 }
13225 else
13226 {
13227 f->name = name;
13228 f->explicit_name = 1;
13229 /* use the frame's title when getting resources for this frame. */
13230 specbind (Qx_resource_name, name);
13231 }
13232
13233 /* Extract the window parameters from the supplied values
13234 that are needed to determine window geometry. */
13235 {
13236 Lisp_Object font;
13237
13238 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
13239
13240 BLOCK_INPUT;
13241 /* First, try whatever font the caller has specified. */
13242 if (STRINGP (font))
13243 {
13244 tem = Fquery_fontset (font, Qnil);
13245 if (STRINGP (tem))
13246 font = x_new_fontset (f, XSTRING (tem)->data);
13247 else
13248 font = x_new_font (f, XSTRING (font)->data);
13249 }
13250
13251 /* Try out a font which we hope has bold and italic variations. */
13252 if (!STRINGP (font))
13253 font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
13254 if (! STRINGP (font))
13255 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
13256 /* If those didn't work, look for something which will at least work. */
13257 if (! STRINGP (font))
13258 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
13259 UNBLOCK_INPUT;
13260 if (! STRINGP (font))
13261 font = build_string ("Fixedsys");
13262
13263 x_default_parameter (f, parms, Qfont, font,
13264 "font", "Font", RES_TYPE_STRING);
13265 }
13266
13267 x_default_parameter (f, parms, Qborder_width, make_number (2),
13268 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
13269 /* This defaults to 2 in order to match xterm. We recognize either
13270 internalBorderWidth or internalBorder (which is what xterm calls
13271 it). */
13272 if (NILP (Fassq (Qinternal_border_width, parms)))
13273 {
13274 Lisp_Object value;
13275
13276 value = w32_get_arg (parms, Qinternal_border_width,
13277 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
13278 if (! EQ (value, Qunbound))
13279 parms = Fcons (Fcons (Qinternal_border_width, value),
13280 parms);
13281 }
13282 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
13283 "internalBorderWidth", "internalBorderWidth",
13284 RES_TYPE_NUMBER);
13285
13286 /* Also do the stuff which must be set before the window exists. */
13287 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
13288 "foreground", "Foreground", RES_TYPE_STRING);
13289 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
13290 "background", "Background", RES_TYPE_STRING);
13291 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
13292 "pointerColor", "Foreground", RES_TYPE_STRING);
13293 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
13294 "cursorColor", "Foreground", RES_TYPE_STRING);
13295 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
13296 "borderColor", "BorderColor", RES_TYPE_STRING);
13297
13298 /* Init faces before x_default_parameter is called for scroll-bar
13299 parameters because that function calls x_set_scroll_bar_width,
13300 which calls change_frame_size, which calls Fset_window_buffer,
13301 which runs hooks, which call Fvertical_motion. At the end, we
13302 end up in init_iterator with a null face cache, which should not
13303 happen. */
13304 init_frame_faces (f);
13305
13306 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
13307 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
13308
13309 window_prompting = x_figure_window_size (f, parms);
13310
13311 /* No fringes on tip frame. */
13312 f->output_data.w32->fringes_extra = 0;
13313 f->output_data.w32->fringe_cols = 0;
13314 f->output_data.w32->left_fringe_width = 0;
13315 f->output_data.w32->right_fringe_width = 0;
13316
13317 if (window_prompting & XNegative)
13318 {
13319 if (window_prompting & YNegative)
13320 f->output_data.w32->win_gravity = SouthEastGravity;
13321 else
13322 f->output_data.w32->win_gravity = NorthEastGravity;
13323 }
13324 else
13325 {
13326 if (window_prompting & YNegative)
13327 f->output_data.w32->win_gravity = SouthWestGravity;
13328 else
13329 f->output_data.w32->win_gravity = NorthWestGravity;
13330 }
13331
13332 f->output_data.w32->size_hint_flags = window_prompting;
13333
13334 BLOCK_INPUT;
13335 my_create_tip_window (f);
13336 UNBLOCK_INPUT;
13337
13338 x_make_gc (f);
13339
13340 x_default_parameter (f, parms, Qauto_raise, Qnil,
13341 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
13342 x_default_parameter (f, parms, Qauto_lower, Qnil,
13343 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
13344 x_default_parameter (f, parms, Qcursor_type, Qbox,
13345 "cursorType", "CursorType", RES_TYPE_SYMBOL);
13346
13347 /* Dimensions, especially f->height, must be done via change_frame_size.
13348 Change will not be effected unless different from the current
13349 f->height. */
13350 width = f->width;
13351 height = f->height;
13352 f->height = 0;
13353 SET_FRAME_WIDTH (f, 0);
13354 change_frame_size (f, height, width, 1, 0, 0);
13355
13356 /* Set up faces after all frame parameters are known. This call
13357 also merges in face attributes specified for new frames.
13358
13359 Frame parameters may be changed if .Xdefaults contains
13360 specifications for the default font. For example, if there is an
13361 `Emacs.default.attributeBackground: pink', the `background-color'
13362 attribute of the frame get's set, which let's the internal border
13363 of the tooltip frame appear in pink. Prevent this. */
13364 {
13365 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
13366
13367 /* Set tip_frame here, so that */
13368 tip_frame = frame;
13369 call1 (Qface_set_after_frame_default, frame);
13370
13371 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
13372 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
13373 Qnil));
13374 }
13375
13376 f->no_split = 1;
13377
13378 UNGCPRO;
13379
13380 /* It is now ok to make the frame official even if we get an error
13381 below. And the frame needs to be on Vframe_list or making it
13382 visible won't work. */
13383 Vframe_list = Fcons (frame, Vframe_list);
13384
13385 /* Now that the frame is official, it counts as a reference to
13386 its display. */
13387 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
13388
13389 /* Setting attributes of faces of the tooltip frame from resources
13390 and similar will increment face_change_count, which leads to the
13391 clearing of all current matrices. Since this isn't necessary
13392 here, avoid it by resetting face_change_count to the value it
13393 had before we created the tip frame. */
13394 face_change_count = face_change_count_before;
13395
13396 /* Discard the unwind_protect. */
13397 return unbind_to (count, frame);
13398 }
13399
13400
13401 /* Compute where to display tip frame F. PARMS is the list of frame
13402 parameters for F. DX and DY are specified offsets from the current
13403 location of the mouse. WIDTH and HEIGHT are the width and height
13404 of the tooltip. Return coordinates relative to the root window of
13405 the display in *ROOT_X, and *ROOT_Y. */
13406
13407 static void
13408 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
13409 struct frame *f;
13410 Lisp_Object parms, dx, dy;
13411 int width, height;
13412 int *root_x, *root_y;
13413 {
13414 Lisp_Object left, top;
13415
13416 /* User-specified position? */
13417 left = Fcdr (Fassq (Qleft, parms));
13418 top = Fcdr (Fassq (Qtop, parms));
13419
13420 /* Move the tooltip window where the mouse pointer is. Resize and
13421 show it. */
13422 if (!INTEGERP (left) || !INTEGERP (top))
13423 {
13424 POINT pt;
13425
13426 BLOCK_INPUT;
13427 GetCursorPos (&pt);
13428 *root_x = pt.x;
13429 *root_y = pt.y;
13430 UNBLOCK_INPUT;
13431 }
13432
13433 if (INTEGERP (top))
13434 *root_y = XINT (top);
13435 else if (*root_y + XINT (dy) - height < 0)
13436 *root_y -= XINT (dy);
13437 else
13438 {
13439 *root_y -= height;
13440 *root_y += XINT (dy);
13441 }
13442
13443 if (INTEGERP (left))
13444 *root_x = XINT (left);
13445 else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width)
13446 /* It fits to the right of the pointer. */
13447 *root_x += XINT (dx);
13448 else if (width + XINT (dx) <= *root_x)
13449 /* It fits to the left of the pointer. */
13450 *root_x -= width + XINT (dx);
13451 else
13452 /* Put it left justified on the screen -- it ought to fit that way. */
13453 *root_x = 0;
13454 }
13455
13456
13457 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
13458 doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
13459 A tooltip window is a small window displaying a string.
13460
13461 FRAME nil or omitted means use the selected frame.
13462
13463 PARMS is an optional list of frame parameters which can be
13464 used to change the tooltip's appearance.
13465
13466 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
13467 means use the default timeout of 5 seconds.
13468
13469 If the list of frame parameters PARAMS contains a `left' parameter,
13470 the tooltip is displayed at that x-position. Otherwise it is
13471 displayed at the mouse position, with offset DX added (default is 5 if
13472 DX isn't specified). Likewise for the y-position; if a `top' frame
13473 parameter is specified, it determines the y-position of the tooltip
13474 window, otherwise it is displayed at the mouse position, with offset
13475 DY added (default is -10).
13476
13477 A tooltip's maximum size is specified by `x-max-tooltip-size'.
13478 Text larger than the specified size is clipped. */)
13479 (string, frame, parms, timeout, dx, dy)
13480 Lisp_Object string, frame, parms, timeout, dx, dy;
13481 {
13482 struct frame *f;
13483 struct window *w;
13484 int root_x, root_y;
13485 struct buffer *old_buffer;
13486 struct text_pos pos;
13487 int i, width, height;
13488 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
13489 int old_windows_or_buffers_changed = windows_or_buffers_changed;
13490 int count = BINDING_STACK_SIZE ();
13491
13492 specbind (Qinhibit_redisplay, Qt);
13493
13494 GCPRO4 (string, parms, frame, timeout);
13495
13496 CHECK_STRING (string);
13497 f = check_x_frame (frame);
13498 if (NILP (timeout))
13499 timeout = make_number (5);
13500 else
13501 CHECK_NATNUM (timeout);
13502
13503 if (NILP (dx))
13504 dx = make_number (5);
13505 else
13506 CHECK_NUMBER (dx);
13507
13508 if (NILP (dy))
13509 dy = make_number (-10);
13510 else
13511 CHECK_NUMBER (dy);
13512
13513 if (NILP (last_show_tip_args))
13514 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
13515
13516 if (!NILP (tip_frame))
13517 {
13518 Lisp_Object last_string = AREF (last_show_tip_args, 0);
13519 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
13520 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
13521
13522 if (EQ (frame, last_frame)
13523 && !NILP (Fequal (last_string, string))
13524 && !NILP (Fequal (last_parms, parms)))
13525 {
13526 struct frame *f = XFRAME (tip_frame);
13527
13528 /* Only DX and DY have changed. */
13529 if (!NILP (tip_timer))
13530 {
13531 Lisp_Object timer = tip_timer;
13532 tip_timer = Qnil;
13533 call1 (Qcancel_timer, timer);
13534 }
13535
13536 BLOCK_INPUT;
13537 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
13538 PIXEL_HEIGHT (f), &root_x, &root_y);
13539 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
13540 root_x, root_y, 0, 0,
13541 SWP_NOSIZE | SWP_NOACTIVATE);
13542 UNBLOCK_INPUT;
13543 goto start_timer;
13544 }
13545 }
13546
13547 /* Hide a previous tip, if any. */
13548 Fx_hide_tip ();
13549
13550 ASET (last_show_tip_args, 0, string);
13551 ASET (last_show_tip_args, 1, frame);
13552 ASET (last_show_tip_args, 2, parms);
13553
13554 /* Add default values to frame parameters. */
13555 if (NILP (Fassq (Qname, parms)))
13556 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
13557 if (NILP (Fassq (Qinternal_border_width, parms)))
13558 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
13559 if (NILP (Fassq (Qborder_width, parms)))
13560 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
13561 if (NILP (Fassq (Qborder_color, parms)))
13562 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
13563 if (NILP (Fassq (Qbackground_color, parms)))
13564 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
13565 parms);
13566
13567 /* Block input until the tip has been fully drawn, to avoid crashes
13568 when drawing tips in menus. */
13569 BLOCK_INPUT;
13570
13571 /* Create a frame for the tooltip, and record it in the global
13572 variable tip_frame. */
13573 frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
13574 f = XFRAME (frame);
13575
13576 /* Set up the frame's root window. */
13577 w = XWINDOW (FRAME_ROOT_WINDOW (f));
13578 w->left = w->top = make_number (0);
13579
13580 if (CONSP (Vx_max_tooltip_size)
13581 && INTEGERP (XCAR (Vx_max_tooltip_size))
13582 && XINT (XCAR (Vx_max_tooltip_size)) > 0
13583 && INTEGERP (XCDR (Vx_max_tooltip_size))
13584 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
13585 {
13586 w->width = XCAR (Vx_max_tooltip_size);
13587 w->height = XCDR (Vx_max_tooltip_size);
13588 }
13589 else
13590 {
13591 w->width = make_number (80);
13592 w->height = make_number (40);
13593 }
13594
13595 f->window_width = XINT (w->width);
13596 adjust_glyphs (f);
13597 w->pseudo_window_p = 1;
13598
13599 /* Display the tooltip text in a temporary buffer. */
13600 old_buffer = current_buffer;
13601 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
13602 current_buffer->truncate_lines = Qnil;
13603 clear_glyph_matrix (w->desired_matrix);
13604 clear_glyph_matrix (w->current_matrix);
13605 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
13606 try_window (FRAME_ROOT_WINDOW (f), pos);
13607
13608 /* Compute width and height of the tooltip. */
13609 width = height = 0;
13610 for (i = 0; i < w->desired_matrix->nrows; ++i)
13611 {
13612 struct glyph_row *row = &w->desired_matrix->rows[i];
13613 struct glyph *last;
13614 int row_width;
13615
13616 /* Stop at the first empty row at the end. */
13617 if (!row->enabled_p || !row->displays_text_p)
13618 break;
13619
13620 /* Let the row go over the full width of the frame. */
13621 row->full_width_p = 1;
13622
13623 #ifdef TODO /* Investigate why some fonts need more width than is
13624 calculated for some tooltips. */
13625 /* There's a glyph at the end of rows that is use to place
13626 the cursor there. Don't include the width of this glyph. */
13627 if (row->used[TEXT_AREA])
13628 {
13629 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
13630 row_width = row->pixel_width - last->pixel_width;
13631 }
13632 else
13633 #endif
13634 row_width = row->pixel_width;
13635
13636 /* TODO: find why tips do not draw along baseline as instructed. */
13637 height += row->height;
13638 width = max (width, row_width);
13639 }
13640
13641 /* Add the frame's internal border to the width and height the X
13642 window should have. */
13643 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
13644 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
13645
13646 /* Move the tooltip window where the mouse pointer is. Resize and
13647 show it. */
13648 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
13649
13650 {
13651 /* Adjust Window size to take border into account. */
13652 RECT rect;
13653 rect.left = rect.top = 0;
13654 rect.right = width;
13655 rect.bottom = height;
13656 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
13657 FRAME_EXTERNAL_MENU_BAR (f));
13658
13659 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
13660 root_x, root_y, rect.right - rect.left,
13661 rect.bottom - rect.top, SWP_NOACTIVATE);
13662
13663 /* Let redisplay know that we have made the frame visible already. */
13664 f->async_visible = 1;
13665
13666 ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
13667 }
13668
13669 /* Draw into the window. */
13670 w->must_be_updated_p = 1;
13671 update_single_window (w, 1);
13672
13673 UNBLOCK_INPUT;
13674
13675 /* Restore original current buffer. */
13676 set_buffer_internal_1 (old_buffer);
13677 windows_or_buffers_changed = old_windows_or_buffers_changed;
13678
13679 start_timer:
13680 /* Let the tip disappear after timeout seconds. */
13681 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
13682 intern ("x-hide-tip"));
13683
13684 UNGCPRO;
13685 return unbind_to (count, Qnil);
13686 }
13687
13688
13689 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
13690 doc: /* Hide the current tooltip window, if there is any.
13691 Value is t if tooltip was open, nil otherwise. */)
13692 ()
13693 {
13694 int count;
13695 Lisp_Object deleted, frame, timer;
13696 struct gcpro gcpro1, gcpro2;
13697
13698 /* Return quickly if nothing to do. */
13699 if (NILP (tip_timer) && NILP (tip_frame))
13700 return Qnil;
13701
13702 frame = tip_frame;
13703 timer = tip_timer;
13704 GCPRO2 (frame, timer);
13705 tip_frame = tip_timer = deleted = Qnil;
13706
13707 count = BINDING_STACK_SIZE ();
13708 specbind (Qinhibit_redisplay, Qt);
13709 specbind (Qinhibit_quit, Qt);
13710
13711 if (!NILP (timer))
13712 call1 (Qcancel_timer, timer);
13713
13714 if (FRAMEP (frame))
13715 {
13716 Fdelete_frame (frame, Qnil);
13717 deleted = Qt;
13718 }
13719
13720 UNGCPRO;
13721 return unbind_to (count, deleted);
13722 }
13723
13724
13725 \f
13726 /***********************************************************************
13727 File selection dialog
13728 ***********************************************************************/
13729
13730 extern Lisp_Object Qfile_name_history;
13731
13732 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
13733 doc: /* Read file name, prompting with PROMPT in directory DIR.
13734 Use a file selection dialog.
13735 Select DEFAULT-FILENAME in the dialog's file selection box, if
13736 specified. Ensure that file exists if MUSTMATCH is non-nil. */)
13737 (prompt, dir, default_filename, mustmatch)
13738 Lisp_Object prompt, dir, default_filename, mustmatch;
13739 {
13740 struct frame *f = SELECTED_FRAME ();
13741 Lisp_Object file = Qnil;
13742 int count = specpdl_ptr - specpdl;
13743 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
13744 char filename[MAX_PATH + 1];
13745 char init_dir[MAX_PATH + 1];
13746 int use_dialog_p = 1;
13747
13748 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
13749 CHECK_STRING (prompt);
13750 CHECK_STRING (dir);
13751
13752 /* Create the dialog with PROMPT as title, using DIR as initial
13753 directory and using "*" as pattern. */
13754 dir = Fexpand_file_name (dir, Qnil);
13755 strncpy (init_dir, XSTRING (dir)->data, MAX_PATH);
13756 init_dir[MAX_PATH] = '\0';
13757 unixtodos_filename (init_dir);
13758
13759 if (STRINGP (default_filename))
13760 {
13761 char *file_name_only;
13762 char *full_path_name = XSTRING (default_filename)->data;
13763
13764 unixtodos_filename (full_path_name);
13765
13766 file_name_only = strrchr (full_path_name, '\\');
13767 if (!file_name_only)
13768 file_name_only = full_path_name;
13769 else
13770 {
13771 file_name_only++;
13772
13773 /* If default_file_name is a directory, don't use the open
13774 file dialog, as it does not support selecting
13775 directories. */
13776 if (!(*file_name_only))
13777 use_dialog_p = 0;
13778 }
13779
13780 strncpy (filename, file_name_only, MAX_PATH);
13781 filename[MAX_PATH] = '\0';
13782 }
13783 else
13784 filename[0] = '\0';
13785
13786 if (use_dialog_p)
13787 {
13788 OPENFILENAME file_details;
13789
13790 /* Prevent redisplay. */
13791 specbind (Qinhibit_redisplay, Qt);
13792 BLOCK_INPUT;
13793
13794 bzero (&file_details, sizeof (file_details));
13795 file_details.lStructSize = sizeof (file_details);
13796 file_details.hwndOwner = FRAME_W32_WINDOW (f);
13797 /* Undocumented Bug in Common File Dialog:
13798 If a filter is not specified, shell links are not resolved. */
13799 file_details.lpstrFilter = "ALL Files (*.*)\0*.*\0\0";
13800 file_details.lpstrFile = filename;
13801 file_details.nMaxFile = sizeof (filename);
13802 file_details.lpstrInitialDir = init_dir;
13803 file_details.lpstrTitle = XSTRING (prompt)->data;
13804 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
13805
13806 if (!NILP (mustmatch))
13807 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
13808
13809 if (GetOpenFileName (&file_details))
13810 {
13811 dostounix_filename (filename);
13812 file = build_string (filename);
13813 }
13814 else
13815 file = Qnil;
13816
13817 UNBLOCK_INPUT;
13818 file = unbind_to (count, file);
13819 }
13820 /* Open File dialog will not allow folders to be selected, so resort
13821 to minibuffer completing reads for directories. */
13822 else
13823 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
13824 dir, mustmatch, dir, Qfile_name_history,
13825 default_filename, Qnil);
13826
13827 UNGCPRO;
13828
13829 /* Make "Cancel" equivalent to C-g. */
13830 if (NILP (file))
13831 Fsignal (Qquit, Qnil);
13832
13833 return unbind_to (count, file);
13834 }
13835
13836
13837 \f
13838 /***********************************************************************
13839 w32 specialized functions
13840 ***********************************************************************/
13841
13842 DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 1, 0,
13843 doc: /* Select a font using the W32 font dialog.
13844 Returns an X font string corresponding to the selection. */)
13845 (frame)
13846 Lisp_Object frame;
13847 {
13848 FRAME_PTR f = check_x_frame (frame);
13849 CHOOSEFONT cf;
13850 LOGFONT lf;
13851 TEXTMETRIC tm;
13852 HDC hdc;
13853 HANDLE oldobj;
13854 char buf[100];
13855
13856 bzero (&cf, sizeof (cf));
13857 bzero (&lf, sizeof (lf));
13858
13859 cf.lStructSize = sizeof (cf);
13860 cf.hwndOwner = FRAME_W32_WINDOW (f);
13861 cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS;
13862 cf.lpLogFont = &lf;
13863
13864 /* Initialize as much of the font details as we can from the current
13865 default font. */
13866 hdc = GetDC (FRAME_W32_WINDOW (f));
13867 oldobj = SelectObject (hdc, FRAME_FONT (f)->hfont);
13868 GetTextFace (hdc, LF_FACESIZE, lf.lfFaceName);
13869 if (GetTextMetrics (hdc, &tm))
13870 {
13871 lf.lfHeight = tm.tmInternalLeading - tm.tmHeight;
13872 lf.lfWeight = tm.tmWeight;
13873 lf.lfItalic = tm.tmItalic;
13874 lf.lfUnderline = tm.tmUnderlined;
13875 lf.lfStrikeOut = tm.tmStruckOut;
13876 lf.lfCharSet = tm.tmCharSet;
13877 cf.Flags |= CF_INITTOLOGFONTSTRUCT;
13878 }
13879 SelectObject (hdc, oldobj);
13880 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
13881
13882 if (!ChooseFont (&cf) || !w32_to_x_font (&lf, buf, 100, NULL))
13883 return Qnil;
13884
13885 return build_string (buf);
13886 }
13887
13888 DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
13889 Sw32_send_sys_command, 1, 2, 0,
13890 doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
13891 Some useful values for command are 0xf030 to maximise frame (0xf020
13892 to minimize), 0xf120 to restore frame to original size, and 0xf100
13893 to activate the menubar for keyboard access. 0xf140 activates the
13894 screen saver if defined.
13895
13896 If optional parameter FRAME is not specified, use selected frame. */)
13897 (command, frame)
13898 Lisp_Object command, frame;
13899 {
13900 FRAME_PTR f = check_x_frame (frame);
13901
13902 CHECK_NUMBER (command);
13903
13904 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
13905
13906 return Qnil;
13907 }
13908
13909 DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
13910 doc: /* Get Windows to perform OPERATION on DOCUMENT.
13911 This is a wrapper around the ShellExecute system function, which
13912 invokes the application registered to handle OPERATION for DOCUMENT.
13913 OPERATION is typically \"open\", \"print\" or \"explore\" (but can be
13914 nil for the default action), and DOCUMENT is typically the name of a
13915 document file or URL, but can also be a program executable to run or
13916 a directory to open in the Windows Explorer.
13917
13918 If DOCUMENT is a program executable, PARAMETERS can be a string
13919 containing command line parameters, but otherwise should be nil.
13920
13921 SHOW-FLAG can be used to control whether the invoked application is hidden
13922 or minimized. If SHOW-FLAG is nil, the application is displayed normally,
13923 otherwise it is an integer representing a ShowWindow flag:
13924
13925 0 - start hidden
13926 1 - start normally
13927 3 - start maximized
13928 6 - start minimized */)
13929 (operation, document, parameters, show_flag)
13930 Lisp_Object operation, document, parameters, show_flag;
13931 {
13932 Lisp_Object current_dir;
13933
13934 CHECK_STRING (document);
13935
13936 /* Encode filename and current directory. */
13937 current_dir = ENCODE_FILE (current_buffer->directory);
13938 document = ENCODE_FILE (document);
13939 if ((int) ShellExecute (NULL,
13940 (STRINGP (operation) ?
13941 XSTRING (operation)->data : NULL),
13942 XSTRING (document)->data,
13943 (STRINGP (parameters) ?
13944 XSTRING (parameters)->data : NULL),
13945 XSTRING (current_dir)->data,
13946 (INTEGERP (show_flag) ?
13947 XINT (show_flag) : SW_SHOWDEFAULT))
13948 > 32)
13949 return Qt;
13950 error ("ShellExecute failed: %s", w32_strerror (0));
13951 }
13952
13953 /* Lookup virtual keycode from string representing the name of a
13954 non-ascii keystroke into the corresponding virtual key, using
13955 lispy_function_keys. */
13956 static int
13957 lookup_vk_code (char *key)
13958 {
13959 int i;
13960
13961 for (i = 0; i < 256; i++)
13962 if (lispy_function_keys[i] != 0
13963 && strcmp (lispy_function_keys[i], key) == 0)
13964 return i;
13965
13966 return -1;
13967 }
13968
13969 /* Convert a one-element vector style key sequence to a hot key
13970 definition. */
13971 static int
13972 w32_parse_hot_key (key)
13973 Lisp_Object key;
13974 {
13975 /* Copied from Fdefine_key and store_in_keymap. */
13976 register Lisp_Object c;
13977 int vk_code;
13978 int lisp_modifiers;
13979 int w32_modifiers;
13980 struct gcpro gcpro1;
13981
13982 CHECK_VECTOR (key);
13983
13984 if (XFASTINT (Flength (key)) != 1)
13985 return Qnil;
13986
13987 GCPRO1 (key);
13988
13989 c = Faref (key, make_number (0));
13990
13991 if (CONSP (c) && lucid_event_type_list_p (c))
13992 c = Fevent_convert_list (c);
13993
13994 UNGCPRO;
13995
13996 if (! INTEGERP (c) && ! SYMBOLP (c))
13997 error ("Key definition is invalid");
13998
13999 /* Work out the base key and the modifiers. */
14000 if (SYMBOLP (c))
14001 {
14002 c = parse_modifiers (c);
14003 lisp_modifiers = Fcar (Fcdr (c));
14004 c = Fcar (c);
14005 if (!SYMBOLP (c))
14006 abort ();
14007 vk_code = lookup_vk_code (XSYMBOL (c)->name->data);
14008 }
14009 else if (INTEGERP (c))
14010 {
14011 lisp_modifiers = XINT (c) & ~CHARACTERBITS;
14012 /* Many ascii characters are their own virtual key code. */
14013 vk_code = XINT (c) & CHARACTERBITS;
14014 }
14015
14016 if (vk_code < 0 || vk_code > 255)
14017 return Qnil;
14018
14019 if ((lisp_modifiers & meta_modifier) != 0
14020 && !NILP (Vw32_alt_is_meta))
14021 lisp_modifiers |= alt_modifier;
14022
14023 /* Supply defs missing from mingw32. */
14024 #ifndef MOD_ALT
14025 #define MOD_ALT 0x0001
14026 #define MOD_CONTROL 0x0002
14027 #define MOD_SHIFT 0x0004
14028 #define MOD_WIN 0x0008
14029 #endif
14030
14031 /* Convert lisp modifiers to Windows hot-key form. */
14032 w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0;
14033 w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0;
14034 w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0;
14035 w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0;
14036
14037 return HOTKEY (vk_code, w32_modifiers);
14038 }
14039
14040 DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
14041 Sw32_register_hot_key, 1, 1, 0,
14042 doc: /* Register KEY as a hot-key combination.
14043 Certain key combinations like Alt-Tab are reserved for system use on
14044 Windows, and therefore are normally intercepted by the system. However,
14045 most of these key combinations can be received by registering them as
14046 hot-keys, overriding their special meaning.
14047
14048 KEY must be a one element key definition in vector form that would be
14049 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
14050 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
14051 is always interpreted as the Windows modifier keys.
14052
14053 The return value is the hotkey-id if registered, otherwise nil. */)
14054 (key)
14055 Lisp_Object key;
14056 {
14057 key = w32_parse_hot_key (key);
14058
14059 if (NILP (Fmemq (key, w32_grabbed_keys)))
14060 {
14061 /* Reuse an empty slot if possible. */
14062 Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
14063
14064 /* Safe to add new key to list, even if we have focus. */
14065 if (NILP (item))
14066 w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
14067 else
14068 XSETCAR (item, key);
14069
14070 /* Notify input thread about new hot-key definition, so that it
14071 takes effect without needing to switch focus. */
14072 PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
14073 (WPARAM) key, 0);
14074 }
14075
14076 return key;
14077 }
14078
14079 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
14080 Sw32_unregister_hot_key, 1, 1, 0,
14081 doc: /* Unregister HOTKEY as a hot-key combination. */)
14082 (key)
14083 Lisp_Object key;
14084 {
14085 Lisp_Object item;
14086
14087 if (!INTEGERP (key))
14088 key = w32_parse_hot_key (key);
14089
14090 item = Fmemq (key, w32_grabbed_keys);
14091
14092 if (!NILP (item))
14093 {
14094 /* Notify input thread about hot-key definition being removed, so
14095 that it takes effect without needing focus switch. */
14096 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
14097 (WPARAM) XINT (XCAR (item)), (LPARAM) item))
14098 {
14099 MSG msg;
14100 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
14101 }
14102 return Qt;
14103 }
14104 return Qnil;
14105 }
14106
14107 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
14108 Sw32_registered_hot_keys, 0, 0, 0,
14109 doc: /* Return list of registered hot-key IDs. */)
14110 ()
14111 {
14112 return Fcopy_sequence (w32_grabbed_keys);
14113 }
14114
14115 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
14116 Sw32_reconstruct_hot_key, 1, 1, 0,
14117 doc: /* Convert hot-key ID to a lisp key combination. */)
14118 (hotkeyid)
14119 Lisp_Object hotkeyid;
14120 {
14121 int vk_code, w32_modifiers;
14122 Lisp_Object key;
14123
14124 CHECK_NUMBER (hotkeyid);
14125
14126 vk_code = HOTKEY_VK_CODE (hotkeyid);
14127 w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
14128
14129 if (lispy_function_keys[vk_code])
14130 key = intern (lispy_function_keys[vk_code]);
14131 else
14132 key = make_number (vk_code);
14133
14134 key = Fcons (key, Qnil);
14135 if (w32_modifiers & MOD_SHIFT)
14136 key = Fcons (Qshift, key);
14137 if (w32_modifiers & MOD_CONTROL)
14138 key = Fcons (Qctrl, key);
14139 if (w32_modifiers & MOD_ALT)
14140 key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
14141 if (w32_modifiers & MOD_WIN)
14142 key = Fcons (Qhyper, key);
14143
14144 return key;
14145 }
14146
14147 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
14148 Sw32_toggle_lock_key, 1, 2, 0,
14149 doc: /* Toggle the state of the lock key KEY.
14150 KEY can be `capslock', `kp-numlock', or `scroll'.
14151 If the optional parameter NEW-STATE is a number, then the state of KEY
14152 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
14153 (key, new_state)
14154 Lisp_Object key, new_state;
14155 {
14156 int vk_code;
14157
14158 if (EQ (key, intern ("capslock")))
14159 vk_code = VK_CAPITAL;
14160 else if (EQ (key, intern ("kp-numlock")))
14161 vk_code = VK_NUMLOCK;
14162 else if (EQ (key, intern ("scroll")))
14163 vk_code = VK_SCROLL;
14164 else
14165 return Qnil;
14166
14167 if (!dwWindowsThreadId)
14168 return make_number (w32_console_toggle_lock_key (vk_code, new_state));
14169
14170 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
14171 (WPARAM) vk_code, (LPARAM) new_state))
14172 {
14173 MSG msg;
14174 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
14175 return make_number (msg.wParam);
14176 }
14177 return Qnil;
14178 }
14179 \f
14180 DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
14181 doc: /* Return storage information about the file system FILENAME is on.
14182 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
14183 storage of the file system, FREE is the free storage, and AVAIL is the
14184 storage available to a non-superuser. All 3 numbers are in bytes.
14185 If the underlying system call fails, value is nil. */)
14186 (filename)
14187 Lisp_Object filename;
14188 {
14189 Lisp_Object encoded, value;
14190
14191 CHECK_STRING (filename);
14192 filename = Fexpand_file_name (filename, Qnil);
14193 encoded = ENCODE_FILE (filename);
14194
14195 value = Qnil;
14196
14197 /* Determining the required information on Windows turns out, sadly,
14198 to be more involved than one would hope. The original Win32 api
14199 call for this will return bogus information on some systems, but we
14200 must dynamically probe for the replacement api, since that was
14201 added rather late on. */
14202 {
14203 HMODULE hKernel = GetModuleHandle ("kernel32");
14204 BOOL (*pfn_GetDiskFreeSpaceEx)
14205 (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
14206 = (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceEx");
14207
14208 /* On Windows, we may need to specify the root directory of the
14209 volume holding FILENAME. */
14210 char rootname[MAX_PATH];
14211 char *name = XSTRING (encoded)->data;
14212
14213 /* find the root name of the volume if given */
14214 if (isalpha (name[0]) && name[1] == ':')
14215 {
14216 rootname[0] = name[0];
14217 rootname[1] = name[1];
14218 rootname[2] = '\\';
14219 rootname[3] = 0;
14220 }
14221 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
14222 {
14223 char *str = rootname;
14224 int slashes = 4;
14225 do
14226 {
14227 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
14228 break;
14229 *str++ = *name++;
14230 }
14231 while ( *name );
14232
14233 *str++ = '\\';
14234 *str = 0;
14235 }
14236
14237 if (pfn_GetDiskFreeSpaceEx)
14238 {
14239 LARGE_INTEGER availbytes;
14240 LARGE_INTEGER freebytes;
14241 LARGE_INTEGER totalbytes;
14242
14243 if (pfn_GetDiskFreeSpaceEx(rootname,
14244 &availbytes,
14245 &totalbytes,
14246 &freebytes))
14247 value = list3 (make_float ((double) totalbytes.QuadPart),
14248 make_float ((double) freebytes.QuadPart),
14249 make_float ((double) availbytes.QuadPart));
14250 }
14251 else
14252 {
14253 DWORD sectors_per_cluster;
14254 DWORD bytes_per_sector;
14255 DWORD free_clusters;
14256 DWORD total_clusters;
14257
14258 if (GetDiskFreeSpace(rootname,
14259 &sectors_per_cluster,
14260 &bytes_per_sector,
14261 &free_clusters,
14262 &total_clusters))
14263 value = list3 (make_float ((double) total_clusters
14264 * sectors_per_cluster * bytes_per_sector),
14265 make_float ((double) free_clusters
14266 * sectors_per_cluster * bytes_per_sector),
14267 make_float ((double) free_clusters
14268 * sectors_per_cluster * bytes_per_sector));
14269 }
14270 }
14271
14272 return value;
14273 }
14274 \f
14275 /***********************************************************************
14276 Initialization
14277 ***********************************************************************/
14278
14279 void
14280 syms_of_w32fns ()
14281 {
14282 HMODULE user32_lib = GetModuleHandle ("user32.dll");
14283
14284 /* This is zero if not using MS-Windows. */
14285 w32_in_use = 0;
14286
14287 /* TrackMouseEvent not available in all versions of Windows, so must load
14288 it dynamically. Do it once, here, instead of every time it is used. */
14289 track_mouse_event_fn = GetProcAddress (user32_lib, "TrackMouseEvent");
14290 track_mouse_window = NULL;
14291
14292 /* The section below is built by the lisp expression at the top of the file,
14293 just above where these variables are declared. */
14294 /*&&& init symbols here &&&*/
14295 Qauto_raise = intern ("auto-raise");
14296 staticpro (&Qauto_raise);
14297 Qauto_lower = intern ("auto-lower");
14298 staticpro (&Qauto_lower);
14299 Qbar = intern ("bar");
14300 staticpro (&Qbar);
14301 Qborder_color = intern ("border-color");
14302 staticpro (&Qborder_color);
14303 Qborder_width = intern ("border-width");
14304 staticpro (&Qborder_width);
14305 Qbox = intern ("box");
14306 staticpro (&Qbox);
14307 Qcursor_color = intern ("cursor-color");
14308 staticpro (&Qcursor_color);
14309 Qcursor_type = intern ("cursor-type");
14310 staticpro (&Qcursor_type);
14311 Qgeometry = intern ("geometry");
14312 staticpro (&Qgeometry);
14313 Qicon_left = intern ("icon-left");
14314 staticpro (&Qicon_left);
14315 Qicon_top = intern ("icon-top");
14316 staticpro (&Qicon_top);
14317 Qicon_type = intern ("icon-type");
14318 staticpro (&Qicon_type);
14319 Qicon_name = intern ("icon-name");
14320 staticpro (&Qicon_name);
14321 Qinternal_border_width = intern ("internal-border-width");
14322 staticpro (&Qinternal_border_width);
14323 Qleft = intern ("left");
14324 staticpro (&Qleft);
14325 Qright = intern ("right");
14326 staticpro (&Qright);
14327 Qmouse_color = intern ("mouse-color");
14328 staticpro (&Qmouse_color);
14329 Qnone = intern ("none");
14330 staticpro (&Qnone);
14331 Qparent_id = intern ("parent-id");
14332 staticpro (&Qparent_id);
14333 Qscroll_bar_width = intern ("scroll-bar-width");
14334 staticpro (&Qscroll_bar_width);
14335 Qsuppress_icon = intern ("suppress-icon");
14336 staticpro (&Qsuppress_icon);
14337 Qundefined_color = intern ("undefined-color");
14338 staticpro (&Qundefined_color);
14339 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
14340 staticpro (&Qvertical_scroll_bars);
14341 Qvisibility = intern ("visibility");
14342 staticpro (&Qvisibility);
14343 Qwindow_id = intern ("window-id");
14344 staticpro (&Qwindow_id);
14345 Qx_frame_parameter = intern ("x-frame-parameter");
14346 staticpro (&Qx_frame_parameter);
14347 Qx_resource_name = intern ("x-resource-name");
14348 staticpro (&Qx_resource_name);
14349 Quser_position = intern ("user-position");
14350 staticpro (&Quser_position);
14351 Quser_size = intern ("user-size");
14352 staticpro (&Quser_size);
14353 Qscreen_gamma = intern ("screen-gamma");
14354 staticpro (&Qscreen_gamma);
14355 Qline_spacing = intern ("line-spacing");
14356 staticpro (&Qline_spacing);
14357 Qcenter = intern ("center");
14358 staticpro (&Qcenter);
14359 Qcancel_timer = intern ("cancel-timer");
14360 staticpro (&Qcancel_timer);
14361 /* This is the end of symbol initialization. */
14362
14363 Qhyper = intern ("hyper");
14364 staticpro (&Qhyper);
14365 Qsuper = intern ("super");
14366 staticpro (&Qsuper);
14367 Qmeta = intern ("meta");
14368 staticpro (&Qmeta);
14369 Qalt = intern ("alt");
14370 staticpro (&Qalt);
14371 Qctrl = intern ("ctrl");
14372 staticpro (&Qctrl);
14373 Qcontrol = intern ("control");
14374 staticpro (&Qcontrol);
14375 Qshift = intern ("shift");
14376 staticpro (&Qshift);
14377
14378 /* Text property `display' should be nonsticky by default. */
14379 Vtext_property_default_nonsticky
14380 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
14381
14382
14383 Qlaplace = intern ("laplace");
14384 staticpro (&Qlaplace);
14385 Qemboss = intern ("emboss");
14386 staticpro (&Qemboss);
14387 Qedge_detection = intern ("edge-detection");
14388 staticpro (&Qedge_detection);
14389 Qheuristic = intern ("heuristic");
14390 staticpro (&Qheuristic);
14391 QCmatrix = intern (":matrix");
14392 staticpro (&QCmatrix);
14393 QCcolor_adjustment = intern (":color-adjustment");
14394 staticpro (&QCcolor_adjustment);
14395 QCmask = intern (":mask");
14396 staticpro (&QCmask);
14397
14398 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
14399 staticpro (&Qface_set_after_frame_default);
14400
14401 Fput (Qundefined_color, Qerror_conditions,
14402 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
14403 Fput (Qundefined_color, Qerror_message,
14404 build_string ("Undefined color"));
14405
14406 staticpro (&w32_grabbed_keys);
14407 w32_grabbed_keys = Qnil;
14408
14409 DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
14410 doc: /* An array of color name mappings for windows. */);
14411 Vw32_color_map = Qnil;
14412
14413 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
14414 doc: /* Non-nil if alt key presses are passed on to Windows.
14415 When non-nil, for example, alt pressed and released and then space will
14416 open the System menu. When nil, Emacs silently swallows alt key events. */);
14417 Vw32_pass_alt_to_system = Qnil;
14418
14419 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
14420 doc: /* Non-nil if the alt key is to be considered the same as the meta key.
14421 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta. */);
14422 Vw32_alt_is_meta = Qt;
14423
14424 DEFVAR_INT ("w32-quit-key", &Vw32_quit_key,
14425 doc: /* If non-zero, the virtual key code for an alternative quit key. */);
14426 XSETINT (Vw32_quit_key, 0);
14427
14428 DEFVAR_LISP ("w32-pass-lwindow-to-system",
14429 &Vw32_pass_lwindow_to_system,
14430 doc: /* Non-nil if the left \"Windows\" key is passed on to Windows.
14431 When non-nil, the Start menu is opened by tapping the key. */);
14432 Vw32_pass_lwindow_to_system = Qt;
14433
14434 DEFVAR_LISP ("w32-pass-rwindow-to-system",
14435 &Vw32_pass_rwindow_to_system,
14436 doc: /* Non-nil if the right \"Windows\" key is passed on to Windows.
14437 When non-nil, the Start menu is opened by tapping the key. */);
14438 Vw32_pass_rwindow_to_system = Qt;
14439
14440 DEFVAR_INT ("w32-phantom-key-code",
14441 &Vw32_phantom_key_code,
14442 doc: /* Virtual key code used to generate \"phantom\" key presses.
14443 Value is a number between 0 and 255.
14444
14445 Phantom key presses are generated in order to stop the system from
14446 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
14447 `w32-pass-rwindow-to-system' is nil. */);
14448 /* Although 255 is technically not a valid key code, it works and
14449 means that this hack won't interfere with any real key code. */
14450 Vw32_phantom_key_code = 255;
14451
14452 DEFVAR_LISP ("w32-enable-num-lock",
14453 &Vw32_enable_num_lock,
14454 doc: /* Non-nil if Num Lock should act normally.
14455 Set to nil to see Num Lock as the key `kp-numlock'. */);
14456 Vw32_enable_num_lock = Qt;
14457
14458 DEFVAR_LISP ("w32-enable-caps-lock",
14459 &Vw32_enable_caps_lock,
14460 doc: /* Non-nil if Caps Lock should act normally.
14461 Set to nil to see Caps Lock as the key `capslock'. */);
14462 Vw32_enable_caps_lock = Qt;
14463
14464 DEFVAR_LISP ("w32-scroll-lock-modifier",
14465 &Vw32_scroll_lock_modifier,
14466 doc: /* Modifier to use for the Scroll Lock on state.
14467 The value can be hyper, super, meta, alt, control or shift for the
14468 respective modifier, or nil to see Scroll Lock as the key `scroll'.
14469 Any other value will cause the key to be ignored. */);
14470 Vw32_scroll_lock_modifier = Qt;
14471
14472 DEFVAR_LISP ("w32-lwindow-modifier",
14473 &Vw32_lwindow_modifier,
14474 doc: /* Modifier to use for the left \"Windows\" key.
14475 The value can be hyper, super, meta, alt, control or shift for the
14476 respective modifier, or nil to appear as the key `lwindow'.
14477 Any other value will cause the key to be ignored. */);
14478 Vw32_lwindow_modifier = Qnil;
14479
14480 DEFVAR_LISP ("w32-rwindow-modifier",
14481 &Vw32_rwindow_modifier,
14482 doc: /* Modifier to use for the right \"Windows\" key.
14483 The value can be hyper, super, meta, alt, control or shift for the
14484 respective modifier, or nil to appear as the key `rwindow'.
14485 Any other value will cause the key to be ignored. */);
14486 Vw32_rwindow_modifier = Qnil;
14487
14488 DEFVAR_LISP ("w32-apps-modifier",
14489 &Vw32_apps_modifier,
14490 doc: /* Modifier to use for the \"Apps\" key.
14491 The value can be hyper, super, meta, alt, control or shift for the
14492 respective modifier, or nil to appear as the key `apps'.
14493 Any other value will cause the key to be ignored. */);
14494 Vw32_apps_modifier = Qnil;
14495
14496 DEFVAR_LISP ("w32-enable-synthesized-fonts", &Vw32_enable_synthesized_fonts,
14497 doc: /* Non-nil enables selection of artificially italicized and bold fonts. */);
14498 Vw32_enable_synthesized_fonts = Qnil;
14499
14500 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette,
14501 doc: /* Non-nil enables Windows palette management to map colors exactly. */);
14502 Vw32_enable_palette = Qt;
14503
14504 DEFVAR_INT ("w32-mouse-button-tolerance",
14505 &Vw32_mouse_button_tolerance,
14506 doc: /* Analogue of double click interval for faking middle mouse events.
14507 The value is the minimum time in milliseconds that must elapse between
14508 left/right button down events before they are considered distinct events.
14509 If both mouse buttons are depressed within this interval, a middle mouse
14510 button down event is generated instead. */);
14511 XSETINT (Vw32_mouse_button_tolerance, GetDoubleClickTime () / 2);
14512
14513 DEFVAR_INT ("w32-mouse-move-interval",
14514 &Vw32_mouse_move_interval,
14515 doc: /* Minimum interval between mouse move events.
14516 The value is the minimum time in milliseconds that must elapse between
14517 successive mouse move (or scroll bar drag) events before they are
14518 reported as lisp events. */);
14519 XSETINT (Vw32_mouse_move_interval, 0);
14520
14521 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
14522 &w32_pass_extra_mouse_buttons_to_system,
14523 doc: /* Non-nil if the fourth and fifth mouse buttons are passed to Windows.
14524 Recent versions of Windows support mice with up to five buttons.
14525 Since most applications don't support these extra buttons, most mouse
14526 drivers will allow you to map them to functions at the system level.
14527 If this variable is non-nil, Emacs will pass them on, allowing the
14528 system to handle them. */);
14529 w32_pass_extra_mouse_buttons_to_system = 0;
14530
14531 init_x_parm_symbols ();
14532
14533 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
14534 doc: /* List of directories to search for bitmap files for w32. */);
14535 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
14536
14537 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
14538 doc: /* The shape of the pointer when over text.
14539 Changing the value does not affect existing frames
14540 unless you set the mouse color. */);
14541 Vx_pointer_shape = Qnil;
14542
14543 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
14544 doc: /* The name Emacs uses to look up resources; for internal use only.
14545 `x-get-resource' uses this as the first component of the instance name
14546 when requesting resource values.
14547 Emacs initially sets `x-resource-name' to the name under which Emacs
14548 was invoked, or to the value specified with the `-name' or `-rn'
14549 switches, if present. */);
14550 Vx_resource_name = Qnil;
14551
14552 Vx_nontext_pointer_shape = Qnil;
14553
14554 Vx_mode_pointer_shape = Qnil;
14555
14556 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
14557 doc: /* The shape of the pointer when Emacs is busy.
14558 This variable takes effect when you create a new frame
14559 or when you set the mouse color. */);
14560 Vx_hourglass_pointer_shape = Qnil;
14561
14562 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
14563 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
14564 display_hourglass_p = 1;
14565
14566 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
14567 doc: /* *Seconds to wait before displaying an hourglass pointer.
14568 Value must be an integer or float. */);
14569 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
14570
14571 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
14572 &Vx_sensitive_text_pointer_shape,
14573 doc: /* The shape of the pointer when over mouse-sensitive text.
14574 This variable takes effect when you create a new frame
14575 or when you set the mouse color. */);
14576 Vx_sensitive_text_pointer_shape = Qnil;
14577
14578 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
14579 &Vx_window_horizontal_drag_shape,
14580 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
14581 This variable takes effect when you create a new frame
14582 or when you set the mouse color. */);
14583 Vx_window_horizontal_drag_shape = Qnil;
14584
14585 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
14586 doc: /* A string indicating the foreground color of the cursor box. */);
14587 Vx_cursor_fore_pixel = Qnil;
14588
14589 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
14590 doc: /* Maximum size for tooltips.
14591 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
14592 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
14593
14594 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
14595 doc: /* Non-nil if no window manager is in use.
14596 Emacs doesn't try to figure this out; this is always nil
14597 unless you set it to something else. */);
14598 /* We don't have any way to find this out, so set it to nil
14599 and maybe the user would like to set it to t. */
14600 Vx_no_window_manager = Qnil;
14601
14602 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
14603 &Vx_pixel_size_width_font_regexp,
14604 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
14605
14606 Since Emacs gets width of a font matching with this regexp from
14607 PIXEL_SIZE field of the name, font finding mechanism gets faster for
14608 such a font. This is especially effective for such large fonts as
14609 Chinese, Japanese, and Korean. */);
14610 Vx_pixel_size_width_font_regexp = Qnil;
14611
14612 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
14613 doc: /* Time after which cached images are removed from the cache.
14614 When an image has not been displayed this many seconds, remove it
14615 from the image cache. Value must be an integer or nil with nil
14616 meaning don't clear the cache. */);
14617 Vimage_cache_eviction_delay = make_number (30 * 60);
14618
14619 DEFVAR_LISP ("w32-bdf-filename-alist",
14620 &Vw32_bdf_filename_alist,
14621 doc: /* List of bdf fonts and their corresponding filenames. */);
14622 Vw32_bdf_filename_alist = Qnil;
14623
14624 DEFVAR_BOOL ("w32-strict-fontnames",
14625 &w32_strict_fontnames,
14626 doc: /* Non-nil means only use fonts that are exact matches for those requested.
14627 Default is nil, which allows old fontnames that are not XLFD compliant,
14628 and allows third-party CJK display to work by specifying false charset
14629 fields to trick Emacs into translating to Big5, SJIS etc.
14630 Setting this to t will prevent wrong fonts being selected when
14631 fontsets are automatically created. */);
14632 w32_strict_fontnames = 0;
14633
14634 DEFVAR_BOOL ("w32-strict-painting",
14635 &w32_strict_painting,
14636 doc: /* Non-nil means use strict rules for repainting frames.
14637 Set this to nil to get the old behaviour for repainting; this should
14638 only be necessary if the default setting causes problems. */);
14639 w32_strict_painting = 1;
14640
14641 DEFVAR_LISP ("w32-charset-info-alist",
14642 &Vw32_charset_info_alist,
14643 doc: /* Alist linking Emacs character sets to Windows fonts and codepages.
14644 Each entry should be of the form:
14645
14646 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))
14647
14648 where CHARSET_NAME is a string used in font names to identify the charset,
14649 WINDOWS_CHARSET is a symbol that can be one of:
14650 w32-charset-ansi, w32-charset-default, w32-charset-symbol,
14651 w32-charset-shiftjis, w32-charset-hangeul, w32-charset-gb2312,
14652 w32-charset-chinesebig5,
14653 #ifdef JOHAB_CHARSET
14654 w32-charset-johab, w32-charset-hebrew,
14655 w32-charset-arabic, w32-charset-greek, w32-charset-turkish,
14656 w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,
14657 w32-charset-russian, w32-charset-mac, w32-charset-baltic,
14658 #endif
14659 #ifdef UNICODE_CHARSET
14660 w32-charset-unicode,
14661 #endif
14662 or w32-charset-oem.
14663 CODEPAGE should be an integer specifying the codepage that should be used
14664 to display the character set, t to do no translation and output as Unicode,
14665 or nil to do no translation and output as 8 bit (or multibyte on far-east
14666 versions of Windows) characters. */);
14667 Vw32_charset_info_alist = Qnil;
14668
14669 staticpro (&Qw32_charset_ansi);
14670 Qw32_charset_ansi = intern ("w32-charset-ansi");
14671 staticpro (&Qw32_charset_symbol);
14672 Qw32_charset_symbol = intern ("w32-charset-symbol");
14673 staticpro (&Qw32_charset_shiftjis);
14674 Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
14675 staticpro (&Qw32_charset_hangeul);
14676 Qw32_charset_hangeul = intern ("w32-charset-hangeul");
14677 staticpro (&Qw32_charset_chinesebig5);
14678 Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
14679 staticpro (&Qw32_charset_gb2312);
14680 Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
14681 staticpro (&Qw32_charset_oem);
14682 Qw32_charset_oem = intern ("w32-charset-oem");
14683
14684 #ifdef JOHAB_CHARSET
14685 {
14686 static int w32_extra_charsets_defined = 1;
14687 DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined,
14688 doc: /* Internal variable. */);
14689
14690 staticpro (&Qw32_charset_johab);
14691 Qw32_charset_johab = intern ("w32-charset-johab");
14692 staticpro (&Qw32_charset_easteurope);
14693 Qw32_charset_easteurope = intern ("w32-charset-easteurope");
14694 staticpro (&Qw32_charset_turkish);
14695 Qw32_charset_turkish = intern ("w32-charset-turkish");
14696 staticpro (&Qw32_charset_baltic);
14697 Qw32_charset_baltic = intern ("w32-charset-baltic");
14698 staticpro (&Qw32_charset_russian);
14699 Qw32_charset_russian = intern ("w32-charset-russian");
14700 staticpro (&Qw32_charset_arabic);
14701 Qw32_charset_arabic = intern ("w32-charset-arabic");
14702 staticpro (&Qw32_charset_greek);
14703 Qw32_charset_greek = intern ("w32-charset-greek");
14704 staticpro (&Qw32_charset_hebrew);
14705 Qw32_charset_hebrew = intern ("w32-charset-hebrew");
14706 staticpro (&Qw32_charset_vietnamese);
14707 Qw32_charset_vietnamese = intern ("w32-charset-vietnamese");
14708 staticpro (&Qw32_charset_thai);
14709 Qw32_charset_thai = intern ("w32-charset-thai");
14710 staticpro (&Qw32_charset_mac);
14711 Qw32_charset_mac = intern ("w32-charset-mac");
14712 }
14713 #endif
14714
14715 #ifdef UNICODE_CHARSET
14716 {
14717 static int w32_unicode_charset_defined = 1;
14718 DEFVAR_BOOL ("w32-unicode-charset-defined",
14719 &w32_unicode_charset_defined,
14720 doc: /* Internal variable. */);
14721
14722 staticpro (&Qw32_charset_unicode);
14723 Qw32_charset_unicode = intern ("w32-charset-unicode");
14724 #endif
14725
14726 defsubr (&Sx_get_resource);
14727 #if 0 /* TODO: Port to W32 */
14728 defsubr (&Sx_change_window_property);
14729 defsubr (&Sx_delete_window_property);
14730 defsubr (&Sx_window_property);
14731 #endif
14732 defsubr (&Sxw_display_color_p);
14733 defsubr (&Sx_display_grayscale_p);
14734 defsubr (&Sxw_color_defined_p);
14735 defsubr (&Sxw_color_values);
14736 defsubr (&Sx_server_max_request_size);
14737 defsubr (&Sx_server_vendor);
14738 defsubr (&Sx_server_version);
14739 defsubr (&Sx_display_pixel_width);
14740 defsubr (&Sx_display_pixel_height);
14741 defsubr (&Sx_display_mm_width);
14742 defsubr (&Sx_display_mm_height);
14743 defsubr (&Sx_display_screens);
14744 defsubr (&Sx_display_planes);
14745 defsubr (&Sx_display_color_cells);
14746 defsubr (&Sx_display_visual_class);
14747 defsubr (&Sx_display_backing_store);
14748 defsubr (&Sx_display_save_under);
14749 defsubr (&Sx_parse_geometry);
14750 defsubr (&Sx_create_frame);
14751 defsubr (&Sx_open_connection);
14752 defsubr (&Sx_close_connection);
14753 defsubr (&Sx_display_list);
14754 defsubr (&Sx_synchronize);
14755
14756 /* W32 specific functions */
14757
14758 defsubr (&Sw32_focus_frame);
14759 defsubr (&Sw32_select_font);
14760 defsubr (&Sw32_define_rgb_color);
14761 defsubr (&Sw32_default_color_map);
14762 defsubr (&Sw32_load_color_file);
14763 defsubr (&Sw32_send_sys_command);
14764 defsubr (&Sw32_shell_execute);
14765 defsubr (&Sw32_register_hot_key);
14766 defsubr (&Sw32_unregister_hot_key);
14767 defsubr (&Sw32_registered_hot_keys);
14768 defsubr (&Sw32_reconstruct_hot_key);
14769 defsubr (&Sw32_toggle_lock_key);
14770 defsubr (&Sw32_find_bdf_fonts);
14771
14772 defsubr (&Sfile_system_info);
14773
14774 /* Setting callback functions for fontset handler. */
14775 get_font_info_func = w32_get_font_info;
14776
14777 #if 0 /* This function pointer doesn't seem to be used anywhere.
14778 And the pointer assigned has the wrong type, anyway. */
14779 list_fonts_func = w32_list_fonts;
14780 #endif
14781
14782 load_font_func = w32_load_font;
14783 find_ccl_program_func = w32_find_ccl_program;
14784 query_font_func = w32_query_font;
14785 set_frame_fontset_func = x_set_font;
14786 check_window_system_func = check_w32;
14787
14788 #if 0 /* TODO Image support for W32 */
14789 /* Images. */
14790 Qxbm = intern ("xbm");
14791 staticpro (&Qxbm);
14792 QCtype = intern (":type");
14793 staticpro (&QCtype);
14794 QCconversion = intern (":conversion");
14795 staticpro (&QCconversion);
14796 QCheuristic_mask = intern (":heuristic-mask");
14797 staticpro (&QCheuristic_mask);
14798 QCcolor_symbols = intern (":color-symbols");
14799 staticpro (&QCcolor_symbols);
14800 QCascent = intern (":ascent");
14801 staticpro (&QCascent);
14802 QCmargin = intern (":margin");
14803 staticpro (&QCmargin);
14804 QCrelief = intern (":relief");
14805 staticpro (&QCrelief);
14806 Qpostscript = intern ("postscript");
14807 staticpro (&Qpostscript);
14808 QCloader = intern (":loader");
14809 staticpro (&QCloader);
14810 QCbounding_box = intern (":bounding-box");
14811 staticpro (&QCbounding_box);
14812 QCpt_width = intern (":pt-width");
14813 staticpro (&QCpt_width);
14814 QCpt_height = intern (":pt-height");
14815 staticpro (&QCpt_height);
14816 QCindex = intern (":index");
14817 staticpro (&QCindex);
14818 Qpbm = intern ("pbm");
14819 staticpro (&Qpbm);
14820
14821 #if HAVE_XPM
14822 Qxpm = intern ("xpm");
14823 staticpro (&Qxpm);
14824 #endif
14825
14826 #if HAVE_JPEG
14827 Qjpeg = intern ("jpeg");
14828 staticpro (&Qjpeg);
14829 #endif
14830
14831 #if HAVE_TIFF
14832 Qtiff = intern ("tiff");
14833 staticpro (&Qtiff);
14834 #endif
14835
14836 #if HAVE_GIF
14837 Qgif = intern ("gif");
14838 staticpro (&Qgif);
14839 #endif
14840
14841 #if HAVE_PNG
14842 Qpng = intern ("png");
14843 staticpro (&Qpng);
14844 #endif
14845
14846 defsubr (&Sclear_image_cache);
14847
14848 #if GLYPH_DEBUG
14849 defsubr (&Simagep);
14850 defsubr (&Slookup_image);
14851 #endif
14852 #endif /* TODO */
14853
14854 hourglass_atimer = NULL;
14855 hourglass_shown_p = 0;
14856 defsubr (&Sx_show_tip);
14857 defsubr (&Sx_hide_tip);
14858 tip_timer = Qnil;
14859 staticpro (&tip_timer);
14860 tip_frame = Qnil;
14861 staticpro (&tip_frame);
14862
14863 last_show_tip_args = Qnil;
14864 staticpro (&last_show_tip_args);
14865
14866 defsubr (&Sx_file_dialog);
14867 }
14868
14869
14870 void
14871 init_xfns ()
14872 {
14873 image_types = NULL;
14874 Vimage_types = Qnil;
14875
14876 #if 0 /* TODO : Image support for W32 */
14877 define_image_type (&xbm_type);
14878 define_image_type (&gs_type);
14879 define_image_type (&pbm_type);
14880
14881 #if HAVE_XPM
14882 define_image_type (&xpm_type);
14883 #endif
14884
14885 #if HAVE_JPEG
14886 define_image_type (&jpeg_type);
14887 #endif
14888
14889 #if HAVE_TIFF
14890 define_image_type (&tiff_type);
14891 #endif
14892
14893 #if HAVE_GIF
14894 define_image_type (&gif_type);
14895 #endif
14896
14897 #if HAVE_PNG
14898 define_image_type (&png_type);
14899 #endif
14900 #endif /* TODO */
14901 }
14902
14903 #undef abort
14904
14905 void
14906 w32_abort()
14907 {
14908 int button;
14909 button = MessageBox (NULL,
14910 "A fatal error has occurred!\n\n"
14911 "Select Abort to exit, Retry to debug, Ignore to continue",
14912 "Emacs Abort Dialog",
14913 MB_ICONEXCLAMATION | MB_TASKMODAL
14914 | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
14915 switch (button)
14916 {
14917 case IDRETRY:
14918 DebugBreak ();
14919 break;
14920 case IDIGNORE:
14921 break;
14922 case IDABORT:
14923 default:
14924 abort ();
14925 break;
14926 }
14927 }
14928
14929 /* For convenience when debugging. */
14930 int
14931 w32_last_error()
14932 {
14933 return GetLastError ();
14934 }