(Qforeground_color, Qbackground_color): Declare.
[bpt/emacs.git] / src / w32fns.c
CommitLineData
e9e23e23 1/* Graphical user interface functions for the Microsoft W32 API.
8681157a 2 Copyright (C) 1989, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
ee78dc32
GV
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
ee78dc32
GV
20
21/* Added by Kevin Gallo */
22
ee78dc32 23#include <config.h>
1edf84e7
GV
24
25#include <signal.h>
ee78dc32 26#include <stdio.h>
1edf84e7
GV
27#include <limits.h>
28#include <errno.h>
ee78dc32
GV
29
30#include "lisp.h"
31#include "w32term.h"
32#include "frame.h"
33#include "window.h"
34#include "buffer.h"
35#include "dispextern.h"
36#include "keyboard.h"
37#include "blockinput.h"
38#include "paths.h"
489f9371 39#include "w32heap.h"
ee78dc32
GV
40#include "termhooks.h"
41
42#include <commdlg.h>
43
44extern void abort ();
45extern void free_frame_menubar ();
46extern struct scroll_bar *x_window_to_scroll_bar ();
5ac45f98 47extern int quit_char;
ee78dc32
GV
48
49/* The colormap for converting color names to RGB values */
fbd6baed 50Lisp_Object Vw32_color_map;
ee78dc32 51
da36a4d6 52/* Non nil if alt key presses are passed on to Windows. */
fbd6baed 53Lisp_Object Vw32_pass_alt_to_system;
da36a4d6 54
8c205c63
RS
55/* Non nil if alt key is translated to meta_modifier, nil if it is translated
56 to alt_modifier. */
fbd6baed 57Lisp_Object Vw32_alt_is_meta;
8c205c63 58
da36a4d6
GV
59/* Non nil if left window, right window, and application key events
60 are passed on to Windows. */
fbd6baed 61Lisp_Object Vw32_pass_optional_keys_to_system;
da36a4d6 62
5ac45f98
GV
63/* Switch to control whether we inhibit requests for italicised fonts (which
64 are synthesized, look ugly, and are trashed by cursor movement under NT). */
fbd6baed 65Lisp_Object Vw32_enable_italics;
5ac45f98
GV
66
67/* Enable palette management. */
fbd6baed 68Lisp_Object Vw32_enable_palette;
5ac45f98
GV
69
70/* Control how close left/right button down events must be to
71 be converted to a middle button down event. */
fbd6baed 72Lisp_Object Vw32_mouse_button_tolerance;
5ac45f98 73
84fb1139
KH
74/* Minimum interval between mouse movement (and scroll bar drag)
75 events that are passed on to the event loop. */
fbd6baed 76Lisp_Object Vw32_mouse_move_interval;
84fb1139 77
ee78dc32
GV
78/* The name we're using in resource queries. */
79Lisp_Object Vx_resource_name;
80
81/* Non nil if no window manager is in use. */
82Lisp_Object Vx_no_window_manager;
83
84/* The background and shape of the mouse pointer, and shape when not
85 over text or in the modeline. */
86Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
87/* The shape when over mouse-sensitive text. */
88Lisp_Object Vx_sensitive_text_pointer_shape;
89
90/* Color of chars displayed in cursor box. */
91Lisp_Object Vx_cursor_fore_pixel;
92
1edf84e7
GV
93/* Nonzero if using Windows. */
94static int w32_in_use;
95
ee78dc32
GV
96/* Search path for bitmap files. */
97Lisp_Object Vx_bitmap_file_path;
98
99/* Evaluate this expression to rebuild the section of syms_of_w32fns
100 that initializes and staticpros the symbols declared below. Note
101 that Emacs 18 has a bug that keeps C-x C-e from being able to
102 evaluate this expression.
103
104(progn
105 ;; Accumulate a list of the symbols we want to initialize from the
106 ;; declarations at the top of the file.
107 (goto-char (point-min))
108 (search-forward "/\*&&& symbols declared here &&&*\/\n")
109 (let (symbol-list)
110 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
111 (setq symbol-list
112 (cons (buffer-substring (match-beginning 1) (match-end 1))
113 symbol-list))
114 (forward-line 1))
115 (setq symbol-list (nreverse symbol-list))
116 ;; Delete the section of syms_of_... where we initialize the symbols.
117 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
118 (let ((start (point)))
119 (while (looking-at "^ Q")
120 (forward-line 2))
121 (kill-region start (point)))
122 ;; Write a new symbol initialization section.
123 (while symbol-list
124 (insert (format " %s = intern (\"" (car symbol-list)))
125 (let ((start (point)))
126 (insert (substring (car symbol-list) 1))
127 (subst-char-in-region start (point) ?_ ?-))
128 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
129 (setq symbol-list (cdr symbol-list)))))
130
131 */
132
133/*&&& symbols declared here &&&*/
134Lisp_Object Qauto_raise;
135Lisp_Object Qauto_lower;
136Lisp_Object Qbackground_color;
137Lisp_Object Qbar;
138Lisp_Object Qborder_color;
139Lisp_Object Qborder_width;
140Lisp_Object Qbox;
141Lisp_Object Qcursor_color;
142Lisp_Object Qcursor_type;
ee78dc32
GV
143Lisp_Object Qforeground_color;
144Lisp_Object Qgeometry;
145Lisp_Object Qicon_left;
146Lisp_Object Qicon_top;
147Lisp_Object Qicon_type;
148Lisp_Object Qicon_name;
149Lisp_Object Qinternal_border_width;
150Lisp_Object Qleft;
1026b400 151Lisp_Object Qright;
ee78dc32
GV
152Lisp_Object Qmouse_color;
153Lisp_Object Qnone;
154Lisp_Object Qparent_id;
155Lisp_Object Qscroll_bar_width;
156Lisp_Object Qsuppress_icon;
157Lisp_Object Qtop;
158Lisp_Object Qundefined_color;
159Lisp_Object Qvertical_scroll_bars;
160Lisp_Object Qvisibility;
161Lisp_Object Qwindow_id;
162Lisp_Object Qx_frame_parameter;
163Lisp_Object Qx_resource_name;
164Lisp_Object Quser_position;
165Lisp_Object Quser_size;
166Lisp_Object Qdisplay;
167
5ac45f98
GV
168/* State variables for emulating a three button mouse. */
169#define LMOUSE 1
170#define MMOUSE 2
171#define RMOUSE 4
172
173static int button_state = 0;
fbd6baed 174static W32Msg saved_mouse_button_msg;
84fb1139 175static unsigned mouse_button_timer; /* non-zero when timer is active */
fbd6baed 176static W32Msg saved_mouse_move_msg;
84fb1139
KH
177static unsigned mouse_move_timer;
178
179#define MOUSE_BUTTON_ID 1
180#define MOUSE_MOVE_ID 2
5ac45f98 181
ee78dc32
GV
182/* The below are defined in frame.c. */
183extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
1edf84e7 184extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
ee78dc32
GV
185
186extern Lisp_Object Vwindow_system_version;
187
188extern Lisp_Object last_mouse_scroll_bar;
189extern int last_mouse_scroll_bar_pos;
5ac45f98 190
fbd6baed
GV
191/* From w32term.c. */
192extern Lisp_Object Vw32_num_mouse_buttons;
5ac45f98 193
ee78dc32 194\f
1edf84e7
GV
195/* Error if we are not connected to MS-Windows. */
196void
197check_w32 ()
198{
199 if (! w32_in_use)
200 error ("MS-Windows not in use or not initialized");
201}
202
203/* Nonzero if we can use mouse menus.
204 You should not call this unless HAVE_MENUS is defined. */
205
206int
207have_menus_p ()
208{
209 return w32_in_use;
210}
211
ee78dc32 212/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
fbd6baed 213 and checking validity for W32. */
ee78dc32
GV
214
215FRAME_PTR
216check_x_frame (frame)
217 Lisp_Object frame;
218{
219 FRAME_PTR f;
220
221 if (NILP (frame))
222 f = selected_frame;
223 else
224 {
225 CHECK_LIVE_FRAME (frame, 0);
226 f = XFRAME (frame);
227 }
fbd6baed
GV
228 if (! FRAME_W32_P (f))
229 error ("non-w32 frame used");
ee78dc32
GV
230 return f;
231}
232
233/* Let the user specify an display with a frame.
fbd6baed 234 nil stands for the selected frame--or, if that is not a w32 frame,
ee78dc32
GV
235 the first display on the list. */
236
fbd6baed 237static struct w32_display_info *
ee78dc32
GV
238check_x_display_info (frame)
239 Lisp_Object frame;
240{
241 if (NILP (frame))
242 {
fbd6baed
GV
243 if (FRAME_W32_P (selected_frame))
244 return FRAME_W32_DISPLAY_INFO (selected_frame);
ee78dc32 245 else
fbd6baed 246 return &one_w32_display_info;
ee78dc32
GV
247 }
248 else if (STRINGP (frame))
249 return x_display_info_for_name (frame);
250 else
251 {
252 FRAME_PTR f;
253
254 CHECK_LIVE_FRAME (frame, 0);
255 f = XFRAME (frame);
fbd6baed
GV
256 if (! FRAME_W32_P (f))
257 error ("non-w32 frame used");
258 return FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
259 }
260}
261\f
fbd6baed 262/* Return the Emacs frame-object corresponding to an w32 window.
ee78dc32
GV
263 It could be the frame's main window or an icon window. */
264
265/* This function can be called during GC, so use GC_xxx type test macros. */
266
267struct frame *
268x_window_to_frame (dpyinfo, wdesc)
fbd6baed 269 struct w32_display_info *dpyinfo;
ee78dc32
GV
270 HWND wdesc;
271{
272 Lisp_Object tail, frame;
273 struct frame *f;
274
275 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
276 {
277 frame = XCONS (tail)->car;
278 if (!GC_FRAMEP (frame))
279 continue;
280 f = XFRAME (frame);
281 if (f->output_data.nothing == 1
fbd6baed 282 || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
ee78dc32 283 continue;
fbd6baed 284 if (FRAME_W32_WINDOW (f) == wdesc)
ee78dc32
GV
285 return f;
286 }
287 return 0;
288}
289
290\f
291
292/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
293 id, which is just an int that this section returns. Bitmaps are
294 reference counted so they can be shared among frames.
295
296 Bitmap indices are guaranteed to be > 0, so a negative number can
297 be used to indicate no bitmap.
298
299 If you use x_create_bitmap_from_data, then you must keep track of
300 the bitmaps yourself. That is, creating a bitmap from the same
301 data more than once will not be caught. */
302
303
304/* Functions to access the contents of a bitmap, given an id. */
305
306int
307x_bitmap_height (f, id)
308 FRAME_PTR f;
309 int id;
310{
fbd6baed 311 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
ee78dc32
GV
312}
313
314int
315x_bitmap_width (f, id)
316 FRAME_PTR f;
317 int id;
318{
fbd6baed 319 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
ee78dc32
GV
320}
321
322int
323x_bitmap_pixmap (f, id)
324 FRAME_PTR f;
325 int id;
326{
fbd6baed 327 return (int) FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
ee78dc32
GV
328}
329
330
331/* Allocate a new bitmap record. Returns index of new record. */
332
333static int
334x_allocate_bitmap_record (f)
335 FRAME_PTR f;
336{
fbd6baed 337 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
338 int i;
339
340 if (dpyinfo->bitmaps == NULL)
341 {
342 dpyinfo->bitmaps_size = 10;
343 dpyinfo->bitmaps
fbd6baed 344 = (struct w32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
ee78dc32
GV
345 dpyinfo->bitmaps_last = 1;
346 return 1;
347 }
348
349 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
350 return ++dpyinfo->bitmaps_last;
351
352 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
353 if (dpyinfo->bitmaps[i].refcount == 0)
354 return i + 1;
355
356 dpyinfo->bitmaps_size *= 2;
357 dpyinfo->bitmaps
fbd6baed
GV
358 = (struct w32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
359 dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
ee78dc32
GV
360 return ++dpyinfo->bitmaps_last;
361}
362
363/* Add one reference to the reference count of the bitmap with id ID. */
364
365void
366x_reference_bitmap (f, id)
367 FRAME_PTR f;
368 int id;
369{
fbd6baed 370 ++FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
ee78dc32
GV
371}
372
373/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
374
375int
376x_create_bitmap_from_data (f, bits, width, height)
377 struct frame *f;
378 char *bits;
379 unsigned int width, height;
380{
fbd6baed 381 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
382 Pixmap bitmap;
383 int id;
384
385 bitmap = CreateBitmap (width, height,
fbd6baed
GV
386 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes,
387 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
ee78dc32
GV
388 bits);
389
390 if (! bitmap)
391 return -1;
392
393 id = x_allocate_bitmap_record (f);
394 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
395 dpyinfo->bitmaps[id - 1].file = NULL;
396 dpyinfo->bitmaps[id - 1].hinst = NULL;
397 dpyinfo->bitmaps[id - 1].refcount = 1;
398 dpyinfo->bitmaps[id - 1].depth = 1;
399 dpyinfo->bitmaps[id - 1].height = height;
400 dpyinfo->bitmaps[id - 1].width = width;
401
402 return id;
403}
404
405/* Create bitmap from file FILE for frame F. */
406
407int
408x_create_bitmap_from_file (f, file)
409 struct frame *f;
410 Lisp_Object file;
411{
412 return -1;
413#if 0
fbd6baed 414 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
415 unsigned int width, height;
416 Pixmap bitmap;
417 int xhot, yhot, result, id;
418 Lisp_Object found;
419 int fd;
420 char *filename;
421 HINSTANCE hinst;
422
423 /* Look for an existing bitmap with the same name. */
424 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
425 {
426 if (dpyinfo->bitmaps[id].refcount
427 && dpyinfo->bitmaps[id].file
428 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
429 {
430 ++dpyinfo->bitmaps[id].refcount;
431 return id + 1;
432 }
433 }
434
435 /* Search bitmap-file-path for the file, if appropriate. */
436 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
437 if (fd < 0)
438 return -1;
439 close (fd);
440
441 filename = (char *) XSTRING (found)->data;
442
443 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
444
445 if (hinst == NULL)
446 return -1;
447
448
fbd6baed 449 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
ee78dc32
GV
450 filename, &width, &height, &bitmap, &xhot, &yhot);
451 if (result != BitmapSuccess)
452 return -1;
453
454 id = x_allocate_bitmap_record (f);
455 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
456 dpyinfo->bitmaps[id - 1].refcount = 1;
457 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
458 dpyinfo->bitmaps[id - 1].depth = 1;
459 dpyinfo->bitmaps[id - 1].height = height;
460 dpyinfo->bitmaps[id - 1].width = width;
461 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
462
463 return id;
464#endif
465}
466
467/* Remove reference to bitmap with id number ID. */
468
469int
470x_destroy_bitmap (f, id)
471 FRAME_PTR f;
472 int id;
473{
fbd6baed 474 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
475
476 if (id > 0)
477 {
478 --dpyinfo->bitmaps[id - 1].refcount;
479 if (dpyinfo->bitmaps[id - 1].refcount == 0)
480 {
481 BLOCK_INPUT;
482 DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
483 if (dpyinfo->bitmaps[id - 1].file)
484 {
485 free (dpyinfo->bitmaps[id - 1].file);
486 dpyinfo->bitmaps[id - 1].file = NULL;
487 }
488 UNBLOCK_INPUT;
489 }
490 }
491}
492
493/* Free all the bitmaps for the display specified by DPYINFO. */
494
495static void
496x_destroy_all_bitmaps (dpyinfo)
fbd6baed 497 struct w32_display_info *dpyinfo;
ee78dc32
GV
498{
499 int i;
500 for (i = 0; i < dpyinfo->bitmaps_last; i++)
501 if (dpyinfo->bitmaps[i].refcount > 0)
502 {
503 DeleteObject (dpyinfo->bitmaps[i].pixmap);
504 if (dpyinfo->bitmaps[i].file)
505 free (dpyinfo->bitmaps[i].file);
506 }
507 dpyinfo->bitmaps_last = 0;
508}
509\f
fbd6baed 510/* Connect the frame-parameter names for W32 frames
ee78dc32
GV
511 to the ways of passing the parameter values to the window system.
512
513 The name of a parameter, as a Lisp symbol,
514 has an `x-frame-parameter' property which is an integer in Lisp
515 but can be interpreted as an `enum x_frame_parm' in C. */
516
517enum x_frame_parm
518{
519 X_PARM_FOREGROUND_COLOR,
520 X_PARM_BACKGROUND_COLOR,
521 X_PARM_MOUSE_COLOR,
522 X_PARM_CURSOR_COLOR,
523 X_PARM_BORDER_COLOR,
524 X_PARM_ICON_TYPE,
525 X_PARM_FONT,
526 X_PARM_BORDER_WIDTH,
527 X_PARM_INTERNAL_BORDER_WIDTH,
528 X_PARM_NAME,
529 X_PARM_AUTORAISE,
530 X_PARM_AUTOLOWER,
531 X_PARM_VERT_SCROLL_BAR,
532 X_PARM_VISIBILITY,
533 X_PARM_MENU_BAR_LINES
534};
535
536
537struct x_frame_parm_table
538{
539 char *name;
540 void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
541};
542
543void x_set_foreground_color ();
544void x_set_background_color ();
545void x_set_mouse_color ();
546void x_set_cursor_color ();
547void x_set_border_color ();
548void x_set_cursor_type ();
549void x_set_icon_type ();
550void x_set_icon_name ();
551void x_set_font ();
552void x_set_border_width ();
553void x_set_internal_border_width ();
554void x_explicitly_set_name ();
555void x_set_autoraise ();
556void x_set_autolower ();
557void x_set_vertical_scroll_bars ();
558void x_set_visibility ();
559void x_set_menu_bar_lines ();
560void x_set_scroll_bar_width ();
1edf84e7 561void x_set_title ();
ee78dc32
GV
562void x_set_unsplittable ();
563
564static struct x_frame_parm_table x_frame_parms[] =
565{
1edf84e7
GV
566 "auto-raise", x_set_autoraise,
567 "auto-lower", x_set_autolower,
ee78dc32 568 "background-color", x_set_background_color,
ee78dc32 569 "border-color", x_set_border_color,
1edf84e7
GV
570 "border-width", x_set_border_width,
571 "cursor-color", x_set_cursor_color,
ee78dc32 572 "cursor-type", x_set_cursor_type,
ee78dc32 573 "font", x_set_font,
1edf84e7
GV
574 "foreground-color", x_set_foreground_color,
575 "icon-name", x_set_icon_name,
576 "icon-type", x_set_icon_type,
ee78dc32 577 "internal-border-width", x_set_internal_border_width,
ee78dc32 578 "menu-bar-lines", x_set_menu_bar_lines,
1edf84e7
GV
579 "mouse-color", x_set_mouse_color,
580 "name", x_explicitly_set_name,
ee78dc32 581 "scroll-bar-width", x_set_scroll_bar_width,
1edf84e7 582 "title", x_set_title,
ee78dc32 583 "unsplittable", x_set_unsplittable,
1edf84e7
GV
584 "vertical-scroll-bars", x_set_vertical_scroll_bars,
585 "visibility", x_set_visibility,
ee78dc32
GV
586};
587
588/* Attach the `x-frame-parameter' properties to
fbd6baed 589 the Lisp symbol names of parameters relevant to W32. */
ee78dc32
GV
590
591init_x_parm_symbols ()
592{
593 int i;
594
595 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
596 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
597 make_number (i));
598}
599\f
600/* Change the parameters of FRAME as specified by ALIST.
601 If a parameter is not specially recognized, do nothing;
602 otherwise call the `x_set_...' function for that parameter. */
603
604void
605x_set_frame_parameters (f, alist)
606 FRAME_PTR f;
607 Lisp_Object alist;
608{
609 Lisp_Object tail;
610
611 /* If both of these parameters are present, it's more efficient to
612 set them both at once. So we wait until we've looked at the
613 entire list before we set them. */
b839712d 614 int width, height;
ee78dc32
GV
615
616 /* Same here. */
617 Lisp_Object left, top;
618
619 /* Same with these. */
620 Lisp_Object icon_left, icon_top;
621
622 /* Record in these vectors all the parms specified. */
623 Lisp_Object *parms;
624 Lisp_Object *values;
625 int i;
626 int left_no_change = 0, top_no_change = 0;
627 int icon_left_no_change = 0, icon_top_no_change = 0;
628
629 i = 0;
630 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
631 i++;
632
633 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
634 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
635
636 /* Extract parm names and values into those vectors. */
637
638 i = 0;
639 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
640 {
641 Lisp_Object elt, prop, val;
642
643 elt = Fcar (tail);
644 parms[i] = Fcar (elt);
645 values[i] = Fcdr (elt);
646 i++;
647 }
648
b839712d 649 top = left = Qunbound;
ee78dc32
GV
650 icon_left = icon_top = Qunbound;
651
b839712d
RS
652 /* Provide default values for HEIGHT and WIDTH. */
653 width = FRAME_WIDTH (f);
654 height = FRAME_HEIGHT (f);
655
ee78dc32
GV
656 /* Now process them in reverse of specified order. */
657 for (i--; i >= 0; i--)
658 {
659 Lisp_Object prop, val;
660
661 prop = parms[i];
662 val = values[i];
663
b839712d
RS
664 if (EQ (prop, Qwidth) && NUMBERP (val))
665 width = XFASTINT (val);
666 else if (EQ (prop, Qheight) && NUMBERP (val))
667 height = XFASTINT (val);
ee78dc32
GV
668 else if (EQ (prop, Qtop))
669 top = val;
670 else if (EQ (prop, Qleft))
671 left = val;
672 else if (EQ (prop, Qicon_top))
673 icon_top = val;
674 else if (EQ (prop, Qicon_left))
675 icon_left = val;
676 else
677 {
678 register Lisp_Object param_index, old_value;
679
680 param_index = Fget (prop, Qx_frame_parameter);
681 old_value = get_frame_param (f, prop);
682 store_frame_param (f, prop, val);
683 if (NATNUMP (param_index)
684 && (XFASTINT (param_index)
685 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
3c190163 686 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
ee78dc32
GV
687 }
688 }
689
690 /* Don't die if just one of these was set. */
691 if (EQ (left, Qunbound))
692 {
693 left_no_change = 1;
fbd6baed
GV
694 if (f->output_data.w32->left_pos < 0)
695 left = Fcons (Qplus, Fcons (make_number (f->output_data.w32->left_pos), Qnil));
ee78dc32 696 else
fbd6baed 697 XSETINT (left, f->output_data.w32->left_pos);
ee78dc32
GV
698 }
699 if (EQ (top, Qunbound))
700 {
701 top_no_change = 1;
fbd6baed
GV
702 if (f->output_data.w32->top_pos < 0)
703 top = Fcons (Qplus, Fcons (make_number (f->output_data.w32->top_pos), Qnil));
ee78dc32 704 else
fbd6baed 705 XSETINT (top, f->output_data.w32->top_pos);
ee78dc32
GV
706 }
707
708 /* If one of the icon positions was not set, preserve or default it. */
709 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
710 {
711 icon_left_no_change = 1;
712 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
713 if (NILP (icon_left))
714 XSETINT (icon_left, 0);
715 }
716 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
717 {
718 icon_top_no_change = 1;
719 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
720 if (NILP (icon_top))
721 XSETINT (icon_top, 0);
722 }
723
ee78dc32
GV
724 /* Don't set these parameters unless they've been explicitly
725 specified. The window might be mapped or resized while we're in
726 this function, and we don't want to override that unless the lisp
727 code has asked for it.
728
729 Don't set these parameters unless they actually differ from the
730 window's current parameters; the window may not actually exist
731 yet. */
732 {
733 Lisp_Object frame;
734
735 check_frame_size (f, &height, &width);
736
737 XSETFRAME (frame, f);
738
b839712d
RS
739 if (XINT (width) != FRAME_WIDTH (f)
740 || XINT (height) != FRAME_HEIGHT (f))
741 Fset_frame_size (frame, make_number (width), make_number (height));
ee78dc32
GV
742
743 if ((!NILP (left) || !NILP (top))
744 && ! (left_no_change && top_no_change)
fbd6baed
GV
745 && ! (NUMBERP (left) && XINT (left) == f->output_data.w32->left_pos
746 && NUMBERP (top) && XINT (top) == f->output_data.w32->top_pos))
ee78dc32
GV
747 {
748 int leftpos = 0;
749 int toppos = 0;
750
751 /* Record the signs. */
fbd6baed 752 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32 753 if (EQ (left, Qminus))
fbd6baed 754 f->output_data.w32->size_hint_flags |= XNegative;
ee78dc32
GV
755 else if (INTEGERP (left))
756 {
757 leftpos = XINT (left);
758 if (leftpos < 0)
fbd6baed 759 f->output_data.w32->size_hint_flags |= XNegative;
ee78dc32
GV
760 }
761 else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
762 && CONSP (XCONS (left)->cdr)
763 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
764 {
765 leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
fbd6baed 766 f->output_data.w32->size_hint_flags |= XNegative;
ee78dc32
GV
767 }
768 else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
769 && CONSP (XCONS (left)->cdr)
770 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
771 {
772 leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
773 }
774
775 if (EQ (top, Qminus))
fbd6baed 776 f->output_data.w32->size_hint_flags |= YNegative;
ee78dc32
GV
777 else if (INTEGERP (top))
778 {
779 toppos = XINT (top);
780 if (toppos < 0)
fbd6baed 781 f->output_data.w32->size_hint_flags |= YNegative;
ee78dc32
GV
782 }
783 else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
784 && CONSP (XCONS (top)->cdr)
785 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
786 {
787 toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
fbd6baed 788 f->output_data.w32->size_hint_flags |= YNegative;
ee78dc32
GV
789 }
790 else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
791 && CONSP (XCONS (top)->cdr)
792 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
793 {
794 toppos = XINT (XCONS (XCONS (top)->cdr)->car);
795 }
796
797
798 /* Store the numeric value of the position. */
fbd6baed
GV
799 f->output_data.w32->top_pos = toppos;
800 f->output_data.w32->left_pos = leftpos;
ee78dc32 801
fbd6baed 802 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
803
804 /* Actually set that position, and convert to absolute. */
805 x_set_offset (f, leftpos, toppos, -1);
806 }
807
808 if ((!NILP (icon_left) || !NILP (icon_top))
809 && ! (icon_left_no_change && icon_top_no_change))
810 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
811 }
812}
813
814/* Store the screen positions of frame F into XPTR and YPTR.
815 These are the positions of the containing window manager window,
816 not Emacs's own window. */
817
818void
819x_real_positions (f, xptr, yptr)
820 FRAME_PTR f;
821 int *xptr, *yptr;
822{
823 POINT pt;
3c190163
GV
824
825 {
826 RECT rect;
ee78dc32 827
fbd6baed
GV
828 GetClientRect(FRAME_W32_WINDOW(f), &rect);
829 AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
ee78dc32 830
3c190163
GV
831 pt.x = rect.left;
832 pt.y = rect.top;
833 }
ee78dc32 834
fbd6baed 835 ClientToScreen (FRAME_W32_WINDOW(f), &pt);
ee78dc32
GV
836
837 *xptr = pt.x;
838 *yptr = pt.y;
839}
840
841/* Insert a description of internally-recorded parameters of frame X
842 into the parameter alist *ALISTPTR that is to be given to the user.
fbd6baed 843 Only parameters that are specific to W32
ee78dc32
GV
844 and whose values are not correctly recorded in the frame's
845 param_alist need to be considered here. */
846
847x_report_frame_params (f, alistptr)
848 struct frame *f;
849 Lisp_Object *alistptr;
850{
851 char buf[16];
852 Lisp_Object tem;
853
854 /* Represent negative positions (off the top or left screen edge)
855 in a way that Fmodify_frame_parameters will understand correctly. */
fbd6baed
GV
856 XSETINT (tem, f->output_data.w32->left_pos);
857 if (f->output_data.w32->left_pos >= 0)
ee78dc32
GV
858 store_in_alist (alistptr, Qleft, tem);
859 else
860 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
861
fbd6baed
GV
862 XSETINT (tem, f->output_data.w32->top_pos);
863 if (f->output_data.w32->top_pos >= 0)
ee78dc32
GV
864 store_in_alist (alistptr, Qtop, tem);
865 else
866 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
867
868 store_in_alist (alistptr, Qborder_width,
fbd6baed 869 make_number (f->output_data.w32->border_width));
ee78dc32 870 store_in_alist (alistptr, Qinternal_border_width,
fbd6baed
GV
871 make_number (f->output_data.w32->internal_border_width));
872 sprintf (buf, "%ld", (long) FRAME_W32_WINDOW (f));
ee78dc32
GV
873 store_in_alist (alistptr, Qwindow_id,
874 build_string (buf));
875 store_in_alist (alistptr, Qicon_name, f->icon_name);
876 FRAME_SAMPLE_VISIBILITY (f);
877 store_in_alist (alistptr, Qvisibility,
878 (FRAME_VISIBLE_P (f) ? Qt
879 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
880 store_in_alist (alistptr, Qdisplay,
fbd6baed 881 XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->car);
ee78dc32
GV
882}
883\f
884
fbd6baed 885DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color, Sw32_define_rgb_color, 4, 4, 0,
5ac45f98 886 "Convert RGB numbers to a windows color reference and associate with NAME (a string).\n\
fbd6baed 887This adds or updates a named color to w32-color-map, making it available for use.\n\
5ac45f98
GV
888The original entry's RGB ref is returned, or nil if the entry is new.")
889 (red, green, blue, name)
890 Lisp_Object red, green, blue, name;
ee78dc32 891{
5ac45f98
GV
892 Lisp_Object rgb;
893 Lisp_Object oldrgb = Qnil;
894 Lisp_Object entry;
895
896 CHECK_NUMBER (red, 0);
897 CHECK_NUMBER (green, 0);
898 CHECK_NUMBER (blue, 0);
899 CHECK_STRING (name, 0);
ee78dc32 900
5ac45f98 901 XSET (rgb, Lisp_Int, RGB(XUINT (red), XUINT (green), XUINT (blue)));
ee78dc32 902
5ac45f98 903 BLOCK_INPUT;
ee78dc32 904
fbd6baed
GV
905 /* replace existing entry in w32-color-map or add new entry. */
906 entry = Fassoc (name, Vw32_color_map);
5ac45f98
GV
907 if (NILP (entry))
908 {
909 entry = Fcons (name, rgb);
fbd6baed 910 Vw32_color_map = Fcons (entry, Vw32_color_map);
5ac45f98
GV
911 }
912 else
913 {
914 oldrgb = Fcdr (entry);
915 Fsetcdr (entry, rgb);
916 }
917
918 UNBLOCK_INPUT;
919
920 return (oldrgb);
ee78dc32
GV
921}
922
fbd6baed 923DEFUN ("w32-load-color-file", Fw32_load_color_file, Sw32_load_color_file, 1, 1, 0,
5ac45f98 924 "Create an alist of color entries from an external file (ie. rgb.txt).\n\
fbd6baed 925Assign this value to w32-color-map to replace the existing color map.\n\
5ac45f98
GV
926\
927The file should define one named RGB color per line like so:\
928 R G B name\n\
929where R,G,B are numbers between 0 and 255 and name is an arbitrary string.")
930 (filename)
931 Lisp_Object filename;
932{
933 FILE *fp;
934 Lisp_Object cmap = Qnil;
935 Lisp_Object abspath;
936
937 CHECK_STRING (filename, 0);
938 abspath = Fexpand_file_name (filename, Qnil);
939
940 fp = fopen (XSTRING (filename)->data, "rt");
941 if (fp)
942 {
943 char buf[512];
944 int red, green, blue;
945 int num;
946
947 BLOCK_INPUT;
948
949 while (fgets (buf, sizeof (buf), fp) != NULL) {
950 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
951 {
952 char *name = buf + num;
953 num = strlen (name) - 1;
954 if (name[num] == '\n')
955 name[num] = 0;
956 cmap = Fcons (Fcons (build_string (name),
957 make_number (RGB (red, green, blue))),
958 cmap);
959 }
960 }
961 fclose (fp);
962
963 UNBLOCK_INPUT;
964 }
965
966 return cmap;
967}
ee78dc32 968
fbd6baed 969/* The default colors for the w32 color map */
ee78dc32
GV
970typedef struct colormap_t
971{
972 char *name;
973 COLORREF colorref;
974} colormap_t;
975
fbd6baed 976colormap_t w32_color_map[] =
ee78dc32 977{
1da8a614
GV
978 {"snow" , PALETTERGB (255,250,250)},
979 {"ghost white" , PALETTERGB (248,248,255)},
980 {"GhostWhite" , PALETTERGB (248,248,255)},
981 {"white smoke" , PALETTERGB (245,245,245)},
982 {"WhiteSmoke" , PALETTERGB (245,245,245)},
983 {"gainsboro" , PALETTERGB (220,220,220)},
984 {"floral white" , PALETTERGB (255,250,240)},
985 {"FloralWhite" , PALETTERGB (255,250,240)},
986 {"old lace" , PALETTERGB (253,245,230)},
987 {"OldLace" , PALETTERGB (253,245,230)},
988 {"linen" , PALETTERGB (250,240,230)},
989 {"antique white" , PALETTERGB (250,235,215)},
990 {"AntiqueWhite" , PALETTERGB (250,235,215)},
991 {"papaya whip" , PALETTERGB (255,239,213)},
992 {"PapayaWhip" , PALETTERGB (255,239,213)},
993 {"blanched almond" , PALETTERGB (255,235,205)},
994 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
995 {"bisque" , PALETTERGB (255,228,196)},
996 {"peach puff" , PALETTERGB (255,218,185)},
997 {"PeachPuff" , PALETTERGB (255,218,185)},
998 {"navajo white" , PALETTERGB (255,222,173)},
999 {"NavajoWhite" , PALETTERGB (255,222,173)},
1000 {"moccasin" , PALETTERGB (255,228,181)},
1001 {"cornsilk" , PALETTERGB (255,248,220)},
1002 {"ivory" , PALETTERGB (255,255,240)},
1003 {"lemon chiffon" , PALETTERGB (255,250,205)},
1004 {"LemonChiffon" , PALETTERGB (255,250,205)},
1005 {"seashell" , PALETTERGB (255,245,238)},
1006 {"honeydew" , PALETTERGB (240,255,240)},
1007 {"mint cream" , PALETTERGB (245,255,250)},
1008 {"MintCream" , PALETTERGB (245,255,250)},
1009 {"azure" , PALETTERGB (240,255,255)},
1010 {"alice blue" , PALETTERGB (240,248,255)},
1011 {"AliceBlue" , PALETTERGB (240,248,255)},
1012 {"lavender" , PALETTERGB (230,230,250)},
1013 {"lavender blush" , PALETTERGB (255,240,245)},
1014 {"LavenderBlush" , PALETTERGB (255,240,245)},
1015 {"misty rose" , PALETTERGB (255,228,225)},
1016 {"MistyRose" , PALETTERGB (255,228,225)},
1017 {"white" , PALETTERGB (255,255,255)},
1018 {"black" , PALETTERGB ( 0, 0, 0)},
1019 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1020 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1021 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1022 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1023 {"dim gray" , PALETTERGB (105,105,105)},
1024 {"DimGray" , PALETTERGB (105,105,105)},
1025 {"dim grey" , PALETTERGB (105,105,105)},
1026 {"DimGrey" , PALETTERGB (105,105,105)},
1027 {"slate gray" , PALETTERGB (112,128,144)},
1028 {"SlateGray" , PALETTERGB (112,128,144)},
1029 {"slate grey" , PALETTERGB (112,128,144)},
1030 {"SlateGrey" , PALETTERGB (112,128,144)},
1031 {"light slate gray" , PALETTERGB (119,136,153)},
1032 {"LightSlateGray" , PALETTERGB (119,136,153)},
1033 {"light slate grey" , PALETTERGB (119,136,153)},
1034 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1035 {"gray" , PALETTERGB (190,190,190)},
1036 {"grey" , PALETTERGB (190,190,190)},
1037 {"light grey" , PALETTERGB (211,211,211)},
1038 {"LightGrey" , PALETTERGB (211,211,211)},
1039 {"light gray" , PALETTERGB (211,211,211)},
1040 {"LightGray" , PALETTERGB (211,211,211)},
1041 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1042 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1043 {"navy" , PALETTERGB ( 0, 0,128)},
1044 {"navy blue" , PALETTERGB ( 0, 0,128)},
1045 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1046 {"cornflower blue" , PALETTERGB (100,149,237)},
1047 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1048 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1049 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1050 {"slate blue" , PALETTERGB (106, 90,205)},
1051 {"SlateBlue" , PALETTERGB (106, 90,205)},
1052 {"medium slate blue" , PALETTERGB (123,104,238)},
1053 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1054 {"light slate blue" , PALETTERGB (132,112,255)},
1055 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1056 {"medium blue" , PALETTERGB ( 0, 0,205)},
1057 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1058 {"royal blue" , PALETTERGB ( 65,105,225)},
1059 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1060 {"blue" , PALETTERGB ( 0, 0,255)},
1061 {"dodger blue" , PALETTERGB ( 30,144,255)},
1062 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1063 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1064 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1065 {"sky blue" , PALETTERGB (135,206,235)},
1066 {"SkyBlue" , PALETTERGB (135,206,235)},
1067 {"light sky blue" , PALETTERGB (135,206,250)},
1068 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1069 {"steel blue" , PALETTERGB ( 70,130,180)},
1070 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1071 {"light steel blue" , PALETTERGB (176,196,222)},
1072 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1073 {"light blue" , PALETTERGB (173,216,230)},
1074 {"LightBlue" , PALETTERGB (173,216,230)},
1075 {"powder blue" , PALETTERGB (176,224,230)},
1076 {"PowderBlue" , PALETTERGB (176,224,230)},
1077 {"pale turquoise" , PALETTERGB (175,238,238)},
1078 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1079 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1080 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1081 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1082 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1083 {"turquoise" , PALETTERGB ( 64,224,208)},
1084 {"cyan" , PALETTERGB ( 0,255,255)},
1085 {"light cyan" , PALETTERGB (224,255,255)},
1086 {"LightCyan" , PALETTERGB (224,255,255)},
1087 {"cadet blue" , PALETTERGB ( 95,158,160)},
1088 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1089 {"medium aquamarine" , PALETTERGB (102,205,170)},
1090 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1091 {"aquamarine" , PALETTERGB (127,255,212)},
1092 {"dark green" , PALETTERGB ( 0,100, 0)},
1093 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1094 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1095 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1096 {"dark sea green" , PALETTERGB (143,188,143)},
1097 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1098 {"sea green" , PALETTERGB ( 46,139, 87)},
1099 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1100 {"medium sea green" , PALETTERGB ( 60,179,113)},
1101 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1102 {"light sea green" , PALETTERGB ( 32,178,170)},
1103 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1104 {"pale green" , PALETTERGB (152,251,152)},
1105 {"PaleGreen" , PALETTERGB (152,251,152)},
1106 {"spring green" , PALETTERGB ( 0,255,127)},
1107 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1108 {"lawn green" , PALETTERGB (124,252, 0)},
1109 {"LawnGreen" , PALETTERGB (124,252, 0)},
1110 {"green" , PALETTERGB ( 0,255, 0)},
1111 {"chartreuse" , PALETTERGB (127,255, 0)},
1112 {"medium spring green" , PALETTERGB ( 0,250,154)},
1113 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1114 {"green yellow" , PALETTERGB (173,255, 47)},
1115 {"GreenYellow" , PALETTERGB (173,255, 47)},
1116 {"lime green" , PALETTERGB ( 50,205, 50)},
1117 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1118 {"yellow green" , PALETTERGB (154,205, 50)},
1119 {"YellowGreen" , PALETTERGB (154,205, 50)},
1120 {"forest green" , PALETTERGB ( 34,139, 34)},
1121 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1122 {"olive drab" , PALETTERGB (107,142, 35)},
1123 {"OliveDrab" , PALETTERGB (107,142, 35)},
1124 {"dark khaki" , PALETTERGB (189,183,107)},
1125 {"DarkKhaki" , PALETTERGB (189,183,107)},
1126 {"khaki" , PALETTERGB (240,230,140)},
1127 {"pale goldenrod" , PALETTERGB (238,232,170)},
1128 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1129 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1130 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1131 {"light yellow" , PALETTERGB (255,255,224)},
1132 {"LightYellow" , PALETTERGB (255,255,224)},
1133 {"yellow" , PALETTERGB (255,255, 0)},
1134 {"gold" , PALETTERGB (255,215, 0)},
1135 {"light goldenrod" , PALETTERGB (238,221,130)},
1136 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1137 {"goldenrod" , PALETTERGB (218,165, 32)},
1138 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1139 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1140 {"rosy brown" , PALETTERGB (188,143,143)},
1141 {"RosyBrown" , PALETTERGB (188,143,143)},
1142 {"indian red" , PALETTERGB (205, 92, 92)},
1143 {"IndianRed" , PALETTERGB (205, 92, 92)},
1144 {"saddle brown" , PALETTERGB (139, 69, 19)},
1145 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1146 {"sienna" , PALETTERGB (160, 82, 45)},
1147 {"peru" , PALETTERGB (205,133, 63)},
1148 {"burlywood" , PALETTERGB (222,184,135)},
1149 {"beige" , PALETTERGB (245,245,220)},
1150 {"wheat" , PALETTERGB (245,222,179)},
1151 {"sandy brown" , PALETTERGB (244,164, 96)},
1152 {"SandyBrown" , PALETTERGB (244,164, 96)},
1153 {"tan" , PALETTERGB (210,180,140)},
1154 {"chocolate" , PALETTERGB (210,105, 30)},
1155 {"firebrick" , PALETTERGB (178,34, 34)},
1156 {"brown" , PALETTERGB (165,42, 42)},
1157 {"dark salmon" , PALETTERGB (233,150,122)},
1158 {"DarkSalmon" , PALETTERGB (233,150,122)},
1159 {"salmon" , PALETTERGB (250,128,114)},
1160 {"light salmon" , PALETTERGB (255,160,122)},
1161 {"LightSalmon" , PALETTERGB (255,160,122)},
1162 {"orange" , PALETTERGB (255,165, 0)},
1163 {"dark orange" , PALETTERGB (255,140, 0)},
1164 {"DarkOrange" , PALETTERGB (255,140, 0)},
1165 {"coral" , PALETTERGB (255,127, 80)},
1166 {"light coral" , PALETTERGB (240,128,128)},
1167 {"LightCoral" , PALETTERGB (240,128,128)},
1168 {"tomato" , PALETTERGB (255, 99, 71)},
1169 {"orange red" , PALETTERGB (255, 69, 0)},
1170 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1171 {"red" , PALETTERGB (255, 0, 0)},
1172 {"hot pink" , PALETTERGB (255,105,180)},
1173 {"HotPink" , PALETTERGB (255,105,180)},
1174 {"deep pink" , PALETTERGB (255, 20,147)},
1175 {"DeepPink" , PALETTERGB (255, 20,147)},
1176 {"pink" , PALETTERGB (255,192,203)},
1177 {"light pink" , PALETTERGB (255,182,193)},
1178 {"LightPink" , PALETTERGB (255,182,193)},
1179 {"pale violet red" , PALETTERGB (219,112,147)},
1180 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1181 {"maroon" , PALETTERGB (176, 48, 96)},
1182 {"medium violet red" , PALETTERGB (199, 21,133)},
1183 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1184 {"violet red" , PALETTERGB (208, 32,144)},
1185 {"VioletRed" , PALETTERGB (208, 32,144)},
1186 {"magenta" , PALETTERGB (255, 0,255)},
1187 {"violet" , PALETTERGB (238,130,238)},
1188 {"plum" , PALETTERGB (221,160,221)},
1189 {"orchid" , PALETTERGB (218,112,214)},
1190 {"medium orchid" , PALETTERGB (186, 85,211)},
1191 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1192 {"dark orchid" , PALETTERGB (153, 50,204)},
1193 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1194 {"dark violet" , PALETTERGB (148, 0,211)},
1195 {"DarkViolet" , PALETTERGB (148, 0,211)},
1196 {"blue violet" , PALETTERGB (138, 43,226)},
1197 {"BlueViolet" , PALETTERGB (138, 43,226)},
1198 {"purple" , PALETTERGB (160, 32,240)},
1199 {"medium purple" , PALETTERGB (147,112,219)},
1200 {"MediumPurple" , PALETTERGB (147,112,219)},
1201 {"thistle" , PALETTERGB (216,191,216)},
1202 {"gray0" , PALETTERGB ( 0, 0, 0)},
1203 {"grey0" , PALETTERGB ( 0, 0, 0)},
1204 {"dark grey" , PALETTERGB (169,169,169)},
1205 {"DarkGrey" , PALETTERGB (169,169,169)},
1206 {"dark gray" , PALETTERGB (169,169,169)},
1207 {"DarkGray" , PALETTERGB (169,169,169)},
1208 {"dark blue" , PALETTERGB ( 0, 0,139)},
1209 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1210 {"dark cyan" , PALETTERGB ( 0,139,139)},
1211 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1212 {"dark magenta" , PALETTERGB (139, 0,139)},
1213 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1214 {"dark red" , PALETTERGB (139, 0, 0)},
1215 {"DarkRed" , PALETTERGB (139, 0, 0)},
1216 {"light green" , PALETTERGB (144,238,144)},
1217 {"LightGreen" , PALETTERGB (144,238,144)},
ee78dc32
GV
1218};
1219
fbd6baed 1220DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
ee78dc32
GV
1221 0, 0, 0, "Return the default color map.")
1222 ()
1223{
1224 int i;
fbd6baed 1225 colormap_t *pc = w32_color_map;
ee78dc32
GV
1226 Lisp_Object cmap;
1227
1228 BLOCK_INPUT;
1229
1230 cmap = Qnil;
1231
fbd6baed 1232 for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
ee78dc32
GV
1233 pc++, i++)
1234 cmap = Fcons (Fcons (build_string (pc->name),
1235 make_number (pc->colorref)),
1236 cmap);
1237
1238 UNBLOCK_INPUT;
1239
1240 return (cmap);
1241}
ee78dc32
GV
1242
1243Lisp_Object
fbd6baed 1244w32_to_x_color (rgb)
ee78dc32
GV
1245 Lisp_Object rgb;
1246{
1247 Lisp_Object color;
1248
1249 CHECK_NUMBER (rgb, 0);
1250
1251 BLOCK_INPUT;
1252
fbd6baed 1253 color = Frassq (rgb, Vw32_color_map);
ee78dc32
GV
1254
1255 UNBLOCK_INPUT;
1256
1257 if (!NILP (color))
1258 return (Fcar (color));
1259 else
1260 return Qnil;
1261}
1262
1263COLORREF
fbd6baed 1264x_to_w32_color (colorname)
ee78dc32
GV
1265 char * colorname;
1266{
1267 register Lisp_Object tail, ret = Qnil;
1268
1269 BLOCK_INPUT;
1edf84e7
GV
1270
1271 if (colorname[0] == '#')
1272 {
1273 /* Could be an old-style RGB Device specification. */
1274 char *color;
1275 int size;
1276 color = colorname + 1;
1277
1278 size = strlen(color);
1279 if (size == 3 || size == 6 || size == 9 || size == 12)
1280 {
1281 UINT colorval;
1282 int i, pos;
1283 pos = 0;
1284 size /= 3;
1285 colorval = 0;
1286
1287 for (i = 0; i < 3; i++)
1288 {
1289 char *end;
1290 char t;
1291 unsigned long value;
1292
1293 /* The check for 'x' in the following conditional takes into
1294 account the fact that strtol allows a "0x" in front of
1295 our numbers, and we don't. */
1296 if (!isxdigit(color[0]) || color[1] == 'x')
1297 break;
1298 t = color[size];
1299 color[size] = '\0';
1300 value = strtoul(color, &end, 16);
1301 color[size] = t;
1302 if (errno == ERANGE || end - color != size)
1303 break;
1304 switch (size)
1305 {
1306 case 1:
1307 value = value * 0x10;
1308 break;
1309 case 2:
1310 break;
1311 case 3:
1312 value /= 0x10;
1313 break;
1314 case 4:
1315 value /= 0x100;
1316 break;
1317 }
1318 colorval |= (value << pos);
1319 pos += 0x8;
1320 if (i == 2)
1321 {
1322 UNBLOCK_INPUT;
1323 return (colorval);
1324 }
1325 color = end;
1326 }
1327 }
1328 }
1329 else if (strnicmp(colorname, "rgb:", 4) == 0)
1330 {
1331 char *color;
1332 UINT colorval;
1333 int i, pos;
1334 pos = 0;
1335
1336 colorval = 0;
1337 color = colorname + 4;
1338 for (i = 0; i < 3; i++)
1339 {
1340 char *end;
1341 unsigned long value;
1342
1343 /* The check for 'x' in the following conditional takes into
1344 account the fact that strtol allows a "0x" in front of
1345 our numbers, and we don't. */
1346 if (!isxdigit(color[0]) || color[1] == 'x')
1347 break;
1348 value = strtoul(color, &end, 16);
1349 if (errno == ERANGE)
1350 break;
1351 switch (end - color)
1352 {
1353 case 1:
1354 value = value * 0x10 + value;
1355 break;
1356 case 2:
1357 break;
1358 case 3:
1359 value /= 0x10;
1360 break;
1361 case 4:
1362 value /= 0x100;
1363 break;
1364 default:
1365 value = ULONG_MAX;
1366 }
1367 if (value == ULONG_MAX)
1368 break;
1369 colorval |= (value << pos);
1370 pos += 0x8;
1371 if (i == 2)
1372 {
1373 if (*end != '\0')
1374 break;
1375 UNBLOCK_INPUT;
1376 return (colorval);
1377 }
1378 if (*end != '/')
1379 break;
1380 color = end + 1;
1381 }
1382 }
1383 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1384 {
1385 /* This is an RGB Intensity specification. */
1386 char *color;
1387 UINT colorval;
1388 int i, pos;
1389 pos = 0;
1390
1391 colorval = 0;
1392 color = colorname + 5;
1393 for (i = 0; i < 3; i++)
1394 {
1395 char *end;
1396 double value;
1397 UINT val;
1398
1399 value = strtod(color, &end);
1400 if (errno == ERANGE)
1401 break;
1402 if (value < 0.0 || value > 1.0)
1403 break;
1404 val = (UINT)(0x100 * value);
1405 /* We used 0x100 instead of 0xFF to give an continuous
1406 range between 0.0 and 1.0 inclusive. The next statement
1407 fixes the 1.0 case. */
1408 if (val == 0x100)
1409 val = 0xFF;
1410 colorval |= (val << pos);
1411 pos += 0x8;
1412 if (i == 2)
1413 {
1414 if (*end != '\0')
1415 break;
1416 UNBLOCK_INPUT;
1417 return (colorval);
1418 }
1419 if (*end != '/')
1420 break;
1421 color = end + 1;
1422 }
1423 }
1424 /* I am not going to attempt to handle any of the CIE color schemes
1425 or TekHVC, since I don't know the algorithms for conversion to
1426 RGB. */
ee78dc32 1427
fbd6baed 1428 for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail))
ee78dc32
GV
1429 {
1430 register Lisp_Object elt, tem;
1431
1432 elt = Fcar (tail);
1433 if (!CONSP (elt)) continue;
1434
1435 tem = Fcar (elt);
1436
1437 if (lstrcmpi (XSTRING (tem)->data, colorname) == 0)
1438 {
1439 ret = XUINT(Fcdr (elt));
1440 break;
1441 }
1442
1443 QUIT;
1444 }
1445
1446 UNBLOCK_INPUT;
1447
1448 return ret;
1449}
1450
5ac45f98
GV
1451
1452void
fbd6baed 1453w32_regenerate_palette (FRAME_PTR f)
5ac45f98 1454{
fbd6baed 1455 struct w32_palette_entry * list;
5ac45f98
GV
1456 LOGPALETTE * log_palette;
1457 HPALETTE new_palette;
1458 int i;
1459
1460 /* don't bother trying to create palette if not supported */
fbd6baed 1461 if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
5ac45f98
GV
1462 return;
1463
1464 log_palette = (LOGPALETTE *)
1465 alloca (sizeof (LOGPALETTE) +
fbd6baed 1466 FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
5ac45f98 1467 log_palette->palVersion = 0x300;
fbd6baed 1468 log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
5ac45f98 1469
fbd6baed 1470 list = FRAME_W32_DISPLAY_INFO (f)->color_list;
5ac45f98 1471 for (i = 0;
fbd6baed 1472 i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
5ac45f98
GV
1473 i++, list = list->next)
1474 log_palette->palPalEntry[i] = list->entry;
1475
1476 new_palette = CreatePalette (log_palette);
1477
1478 enter_crit ();
1479
fbd6baed
GV
1480 if (FRAME_W32_DISPLAY_INFO (f)->palette)
1481 DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
1482 FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
5ac45f98
GV
1483
1484 /* Realize display palette and garbage all frames. */
1485 release_frame_dc (f, get_frame_dc (f));
1486
1487 leave_crit ();
1488}
1489
fbd6baed
GV
1490#define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1491#define SET_W32_COLOR(pe, color) \
5ac45f98
GV
1492 do \
1493 { \
1494 pe.peRed = GetRValue (color); \
1495 pe.peGreen = GetGValue (color); \
1496 pe.peBlue = GetBValue (color); \
1497 pe.peFlags = 0; \
1498 } while (0)
1499
1500#if 0
1501/* Keep these around in case we ever want to track color usage. */
1502void
fbd6baed 1503w32_map_color (FRAME_PTR f, COLORREF color)
5ac45f98 1504{
fbd6baed 1505 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
5ac45f98 1506
fbd6baed 1507 if (NILP (Vw32_enable_palette))
5ac45f98
GV
1508 return;
1509
1510 /* check if color is already mapped */
1511 while (list)
1512 {
fbd6baed 1513 if (W32_COLOR (list->entry) == color)
5ac45f98
GV
1514 {
1515 ++list->refcount;
1516 return;
1517 }
1518 list = list->next;
1519 }
1520
1521 /* not already mapped, so add to list and recreate Windows palette */
fbd6baed
GV
1522 list = (struct w32_palette_entry *)
1523 xmalloc (sizeof (struct w32_palette_entry));
1524 SET_W32_COLOR (list->entry, color);
5ac45f98 1525 list->refcount = 1;
fbd6baed
GV
1526 list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
1527 FRAME_W32_DISPLAY_INFO (f)->color_list = list;
1528 FRAME_W32_DISPLAY_INFO (f)->num_colors++;
5ac45f98
GV
1529
1530 /* set flag that palette must be regenerated */
fbd6baed 1531 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
5ac45f98
GV
1532}
1533
1534void
fbd6baed 1535w32_unmap_color (FRAME_PTR f, COLORREF color)
5ac45f98 1536{
fbd6baed
GV
1537 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1538 struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
5ac45f98 1539
fbd6baed 1540 if (NILP (Vw32_enable_palette))
5ac45f98
GV
1541 return;
1542
1543 /* check if color is already mapped */
1544 while (list)
1545 {
fbd6baed 1546 if (W32_COLOR (list->entry) == color)
5ac45f98
GV
1547 {
1548 if (--list->refcount == 0)
1549 {
1550 *prev = list->next;
1551 xfree (list);
fbd6baed 1552 FRAME_W32_DISPLAY_INFO (f)->num_colors--;
5ac45f98
GV
1553 break;
1554 }
1555 else
1556 return;
1557 }
1558 prev = &list->next;
1559 list = list->next;
1560 }
1561
1562 /* set flag that palette must be regenerated */
fbd6baed 1563 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
5ac45f98
GV
1564}
1565#endif
1566
ee78dc32
GV
1567/* Decide if color named COLOR is valid for the display associated with
1568 the selected frame; if so, return the rgb values in COLOR_DEF.
1569 If ALLOC is nonzero, allocate a new colormap cell. */
1570
1571int
1572defined_color (f, color, color_def, alloc)
1573 FRAME_PTR f;
1574 char *color;
1575 COLORREF *color_def;
1576 int alloc;
1577{
1578 register Lisp_Object tem;
3c190163 1579
fbd6baed 1580 tem = x_to_w32_color (color);
3c190163 1581
ee78dc32
GV
1582 if (!NILP (tem))
1583 {
fbd6baed 1584 if (!NILP (Vw32_enable_palette))
5ac45f98 1585 {
fbd6baed
GV
1586 struct w32_palette_entry * entry =
1587 FRAME_W32_DISPLAY_INFO (f)->color_list;
1588 struct w32_palette_entry ** prev =
1589 &FRAME_W32_DISPLAY_INFO (f)->color_list;
5ac45f98
GV
1590
1591 /* check if color is already mapped */
1592 while (entry)
1593 {
fbd6baed 1594 if (W32_COLOR (entry->entry) == XUINT (tem))
5ac45f98
GV
1595 break;
1596 prev = &entry->next;
1597 entry = entry->next;
1598 }
1599
1600 if (entry == NULL && alloc)
1601 {
1602 /* not already mapped, so add to list */
fbd6baed
GV
1603 entry = (struct w32_palette_entry *)
1604 xmalloc (sizeof (struct w32_palette_entry));
1605 SET_W32_COLOR (entry->entry, XUINT (tem));
5ac45f98
GV
1606 entry->next = NULL;
1607 *prev = entry;
fbd6baed 1608 FRAME_W32_DISPLAY_INFO (f)->num_colors++;
5ac45f98
GV
1609
1610 /* set flag that palette must be regenerated */
fbd6baed 1611 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
5ac45f98
GV
1612 }
1613 }
1614 /* Ensure COLORREF value is snapped to nearest color in (default)
1615 palette by simulating the PALETTERGB macro. This works whether
1616 or not the display device has a palette. */
8847d890 1617 *color_def = XUINT (tem) | 0x2000000;
ee78dc32 1618 return 1;
5ac45f98 1619 }
7fb46567 1620 else
3c190163
GV
1621 {
1622 return 0;
1623 }
ee78dc32
GV
1624}
1625
1626/* Given a string ARG naming a color, compute a pixel value from it
1627 suitable for screen F.
1628 If F is not a color screen, return DEF (default) regardless of what
1629 ARG says. */
1630
1631int
1632x_decode_color (f, arg, def)
1633 FRAME_PTR f;
1634 Lisp_Object arg;
1635 int def;
1636{
1637 COLORREF cdef;
1638
1639 CHECK_STRING (arg, 0);
1640
1641 if (strcmp (XSTRING (arg)->data, "black") == 0)
1642 return BLACK_PIX_DEFAULT (f);
1643 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1644 return WHITE_PIX_DEFAULT (f);
1645
fbd6baed 1646 if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
ee78dc32
GV
1647 return def;
1648
1649 /* defined_color is responsible for coping with failures
1650 by looking for a near-miss. */
1651 if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
1652 return cdef;
1653
1654 /* defined_color failed; return an ultimate default. */
1655 return def;
1656}
1657\f
1658/* Functions called only from `x_set_frame_param'
1659 to set individual parameters.
1660
fbd6baed 1661 If FRAME_W32_WINDOW (f) is 0,
ee78dc32
GV
1662 the frame is being created and its window does not exist yet.
1663 In that case, just record the parameter's new value
1664 in the standard place; do not attempt to change the window. */
1665
1666void
1667x_set_foreground_color (f, arg, oldval)
1668 struct frame *f;
1669 Lisp_Object arg, oldval;
1670{
fbd6baed 1671 f->output_data.w32->foreground_pixel
ee78dc32 1672 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
5ac45f98 1673
fbd6baed 1674 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32
GV
1675 {
1676 recompute_basic_faces (f);
1677 if (FRAME_VISIBLE_P (f))
1678 redraw_frame (f);
1679 }
1680}
1681
1682void
1683x_set_background_color (f, arg, oldval)
1684 struct frame *f;
1685 Lisp_Object arg, oldval;
1686{
1687 Pixmap temp;
1688 int mask;
1689
fbd6baed 1690 f->output_data.w32->background_pixel
ee78dc32
GV
1691 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1692
fbd6baed 1693 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32 1694 {
fbd6baed 1695 SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX, f->output_data.w32->background_pixel);
ee78dc32
GV
1696
1697 recompute_basic_faces (f);
1698
1699 if (FRAME_VISIBLE_P (f))
1700 redraw_frame (f);
1701 }
1702}
1703
1704void
1705x_set_mouse_color (f, arg, oldval)
1706 struct frame *f;
1707 Lisp_Object arg, oldval;
1708{
1709#if 0
1710 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1711#endif
dfc465d3 1712 int count;
ee78dc32
GV
1713 int mask_color;
1714
1715 if (!EQ (Qnil, arg))
fbd6baed 1716 f->output_data.w32->mouse_pixel
ee78dc32 1717 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
fbd6baed 1718 mask_color = f->output_data.w32->background_pixel;
ee78dc32 1719 /* No invisible pointers. */
fbd6baed
GV
1720 if (mask_color == f->output_data.w32->mouse_pixel
1721 && mask_color == f->output_data.w32->background_pixel)
1722 f->output_data.w32->mouse_pixel = f->output_data.w32->foreground_pixel;
ee78dc32
GV
1723
1724#if 0
1725 BLOCK_INPUT;
1726
1727 /* It's not okay to crash if the user selects a screwy cursor. */
fadca6c6 1728 count = x_catch_errors (FRAME_W32_DISPLAY (f));
ee78dc32
GV
1729
1730 if (!EQ (Qnil, Vx_pointer_shape))
1731 {
1732 CHECK_NUMBER (Vx_pointer_shape, 0);
fbd6baed 1733 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
ee78dc32
GV
1734 }
1735 else
fbd6baed
GV
1736 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1737 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
ee78dc32
GV
1738
1739 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1740 {
1741 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
fbd6baed 1742 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
ee78dc32
GV
1743 XINT (Vx_nontext_pointer_shape));
1744 }
1745 else
fbd6baed
GV
1746 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
1747 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
ee78dc32
GV
1748
1749 if (!EQ (Qnil, Vx_mode_pointer_shape))
1750 {
1751 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
fbd6baed 1752 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
ee78dc32
GV
1753 XINT (Vx_mode_pointer_shape));
1754 }
1755 else
fbd6baed
GV
1756 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1757 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
ee78dc32
GV
1758
1759 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1760 {
1761 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1762 cross_cursor
fbd6baed 1763 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
ee78dc32
GV
1764 XINT (Vx_sensitive_text_pointer_shape));
1765 }
1766 else
fbd6baed 1767 cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
ee78dc32
GV
1768
1769 /* Check and report errors with the above calls. */
fbd6baed 1770 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
fadca6c6 1771 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
ee78dc32
GV
1772
1773 {
1774 XColor fore_color, back_color;
1775
fbd6baed 1776 fore_color.pixel = f->output_data.w32->mouse_pixel;
ee78dc32 1777 back_color.pixel = mask_color;
fbd6baed
GV
1778 XQueryColor (FRAME_W32_DISPLAY (f),
1779 DefaultColormap (FRAME_W32_DISPLAY (f),
1780 DefaultScreen (FRAME_W32_DISPLAY (f))),
ee78dc32 1781 &fore_color);
fbd6baed
GV
1782 XQueryColor (FRAME_W32_DISPLAY (f),
1783 DefaultColormap (FRAME_W32_DISPLAY (f),
1784 DefaultScreen (FRAME_W32_DISPLAY (f))),
ee78dc32 1785 &back_color);
fbd6baed 1786 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
ee78dc32 1787 &fore_color, &back_color);
fbd6baed 1788 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
ee78dc32 1789 &fore_color, &back_color);
fbd6baed 1790 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
ee78dc32 1791 &fore_color, &back_color);
fbd6baed 1792 XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
ee78dc32
GV
1793 &fore_color, &back_color);
1794 }
1795
fbd6baed 1796 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32 1797 {
fbd6baed 1798 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
ee78dc32
GV
1799 }
1800
fbd6baed
GV
1801 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
1802 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
1803 f->output_data.w32->text_cursor = cursor;
1804
1805 if (nontext_cursor != f->output_data.w32->nontext_cursor
1806 && f->output_data.w32->nontext_cursor != 0)
1807 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
1808 f->output_data.w32->nontext_cursor = nontext_cursor;
1809
1810 if (mode_cursor != f->output_data.w32->modeline_cursor
1811 && f->output_data.w32->modeline_cursor != 0)
1812 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
1813 f->output_data.w32->modeline_cursor = mode_cursor;
1814 if (cross_cursor != f->output_data.w32->cross_cursor
1815 && f->output_data.w32->cross_cursor != 0)
1816 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
1817 f->output_data.w32->cross_cursor = cross_cursor;
1818
1819 XFlush (FRAME_W32_DISPLAY (f));
ee78dc32
GV
1820 UNBLOCK_INPUT;
1821#endif
1822}
1823
1824void
1825x_set_cursor_color (f, arg, oldval)
1826 struct frame *f;
1827 Lisp_Object arg, oldval;
1828{
1829 unsigned long fore_pixel;
1830
1831 if (!EQ (Vx_cursor_fore_pixel, Qnil))
1832 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1833 WHITE_PIX_DEFAULT (f));
1834 else
fbd6baed
GV
1835 fore_pixel = f->output_data.w32->background_pixel;
1836 f->output_data.w32->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
ee78dc32
GV
1837
1838 /* Make sure that the cursor color differs from the background color. */
fbd6baed 1839 if (f->output_data.w32->cursor_pixel == f->output_data.w32->background_pixel)
ee78dc32 1840 {
fbd6baed
GV
1841 f->output_data.w32->cursor_pixel = f->output_data.w32->mouse_pixel;
1842 if (f->output_data.w32->cursor_pixel == fore_pixel)
1843 fore_pixel = f->output_data.w32->background_pixel;
ee78dc32 1844 }
fbd6baed 1845 f->output_data.w32->cursor_foreground_pixel = fore_pixel;
ee78dc32 1846
fbd6baed 1847 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32
GV
1848 {
1849 if (FRAME_VISIBLE_P (f))
1850 {
1851 x_display_cursor (f, 0);
1852 x_display_cursor (f, 1);
1853 }
1854 }
1855}
1856
1857/* Set the border-color of frame F to value described by ARG.
1858 ARG can be a string naming a color.
1859 The border-color is used for the border that is drawn by the server.
1860 Note that this does not fully take effect if done before
1861 F has a window; it must be redone when the window is created. */
1862
1863void
1864x_set_border_color (f, arg, oldval)
1865 struct frame *f;
1866 Lisp_Object arg, oldval;
1867{
1868 unsigned char *str;
1869 int pix;
1870
1871 CHECK_STRING (arg, 0);
1872 str = XSTRING (arg)->data;
1873
1874 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1875
1876 x_set_border_pixel (f, pix);
1877}
1878
1879/* Set the border-color of frame F to pixel value PIX.
1880 Note that this does not fully take effect if done before
1881 F has an window. */
1882
1883x_set_border_pixel (f, pix)
1884 struct frame *f;
1885 int pix;
1886{
fbd6baed 1887 f->output_data.w32->border_pixel = pix;
ee78dc32 1888
fbd6baed 1889 if (FRAME_W32_WINDOW (f) != 0 && f->output_data.w32->border_width > 0)
ee78dc32
GV
1890 {
1891 if (FRAME_VISIBLE_P (f))
1892 redraw_frame (f);
1893 }
1894}
1895
1896void
1897x_set_cursor_type (f, arg, oldval)
1898 FRAME_PTR f;
1899 Lisp_Object arg, oldval;
1900{
1901 if (EQ (arg, Qbar))
1902 {
1903 FRAME_DESIRED_CURSOR (f) = bar_cursor;
fbd6baed 1904 f->output_data.w32->cursor_width = 2;
ee78dc32
GV
1905 }
1906 else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
1907 && INTEGERP (XCONS (arg)->cdr))
1908 {
1909 FRAME_DESIRED_CURSOR (f) = bar_cursor;
fbd6baed 1910 f->output_data.w32->cursor_width = XINT (XCONS (arg)->cdr);
ee78dc32
GV
1911 }
1912 else
1913 /* Treat anything unknown as "box cursor".
1914 It was bad to signal an error; people have trouble fixing
1915 .Xdefaults with Emacs, when it has something bad in it. */
1916 FRAME_DESIRED_CURSOR (f) = filled_box_cursor;
1917
1918 /* Make sure the cursor gets redrawn. This is overkill, but how
1919 often do people change cursor types? */
1920 update_mode_lines++;
1921}
1922
1923void
1924x_set_icon_type (f, arg, oldval)
1925 struct frame *f;
1926 Lisp_Object arg, oldval;
1927{
1928#if 0
1929 Lisp_Object tem;
1930 int result;
1931
1932 if (STRINGP (arg))
1933 {
1934 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1935 return;
1936 }
1937 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1938 return;
1939
1940 BLOCK_INPUT;
1941 if (NILP (arg))
1942 result = x_text_icon (f,
1943 (char *) XSTRING ((!NILP (f->icon_name)
1944 ? f->icon_name
1945 : f->name))->data);
1946 else
1947 result = x_bitmap_icon (f, arg);
1948
1949 if (result)
1950 {
1951 UNBLOCK_INPUT;
1952 error ("No icon window available");
1953 }
1954
1955 /* If the window was unmapped (and its icon was mapped),
1956 the new icon is not mapped, so map the window in its stead. */
1957 if (FRAME_VISIBLE_P (f))
1958 {
1959#ifdef USE_X_TOOLKIT
fbd6baed 1960 XtPopup (f->output_data.w32->widget, XtGrabNone);
ee78dc32 1961#endif
fbd6baed 1962 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
ee78dc32
GV
1963 }
1964
fbd6baed 1965 XFlush (FRAME_W32_DISPLAY (f));
ee78dc32
GV
1966 UNBLOCK_INPUT;
1967#endif
1968}
1969
1970/* Return non-nil if frame F wants a bitmap icon. */
1971
1972Lisp_Object
1973x_icon_type (f)
1974 FRAME_PTR f;
1975{
1976 Lisp_Object tem;
1977
1978 tem = assq_no_quit (Qicon_type, f->param_alist);
1979 if (CONSP (tem))
1980 return XCONS (tem)->cdr;
1981 else
1982 return Qnil;
1983}
1984
1985void
1986x_set_icon_name (f, arg, oldval)
1987 struct frame *f;
1988 Lisp_Object arg, oldval;
1989{
1990 Lisp_Object tem;
1991 int result;
1992
1993 if (STRINGP (arg))
1994 {
1995 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1996 return;
1997 }
1998 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1999 return;
2000
2001 f->icon_name = arg;
2002
2003#if 0
fbd6baed 2004 if (f->output_data.w32->icon_bitmap != 0)
ee78dc32
GV
2005 return;
2006
2007 BLOCK_INPUT;
2008
2009 result = x_text_icon (f,
1edf84e7 2010 (char *) XSTRING ((!NILP (f->icon_name)
ee78dc32 2011 ? f->icon_name
1edf84e7
GV
2012 : !NILP (f->title)
2013 ? f->title
ee78dc32
GV
2014 : f->name))->data);
2015
2016 if (result)
2017 {
2018 UNBLOCK_INPUT;
2019 error ("No icon window available");
2020 }
2021
2022 /* If the window was unmapped (and its icon was mapped),
2023 the new icon is not mapped, so map the window in its stead. */
2024 if (FRAME_VISIBLE_P (f))
2025 {
2026#ifdef USE_X_TOOLKIT
fbd6baed 2027 XtPopup (f->output_data.w32->widget, XtGrabNone);
ee78dc32 2028#endif
fbd6baed 2029 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
ee78dc32
GV
2030 }
2031
fbd6baed 2032 XFlush (FRAME_W32_DISPLAY (f));
ee78dc32
GV
2033 UNBLOCK_INPUT;
2034#endif
2035}
2036
2037extern Lisp_Object x_new_font ();
2038
2039void
2040x_set_font (f, arg, oldval)
2041 struct frame *f;
2042 Lisp_Object arg, oldval;
2043{
2044 Lisp_Object result;
2045
2046 CHECK_STRING (arg, 1);
2047
2048 BLOCK_INPUT;
2049 result = x_new_font (f, XSTRING (arg)->data);
2050 UNBLOCK_INPUT;
2051
2052 if (EQ (result, Qnil))
2053 error ("Font \"%s\" is not defined", XSTRING (arg)->data);
2054 else if (EQ (result, Qt))
2055 error ("the characters of the given font have varying widths");
2056 else if (STRINGP (result))
2057 {
2058 recompute_basic_faces (f);
2059 store_frame_param (f, Qfont, result);
2060 }
2061 else
2062 abort ();
2063}
2064
2065void
2066x_set_border_width (f, arg, oldval)
2067 struct frame *f;
2068 Lisp_Object arg, oldval;
2069{
2070 CHECK_NUMBER (arg, 0);
2071
fbd6baed 2072 if (XINT (arg) == f->output_data.w32->border_width)
ee78dc32
GV
2073 return;
2074
fbd6baed 2075 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32
GV
2076 error ("Cannot change the border width of a window");
2077
fbd6baed 2078 f->output_data.w32->border_width = XINT (arg);
ee78dc32
GV
2079}
2080
2081void
2082x_set_internal_border_width (f, arg, oldval)
2083 struct frame *f;
2084 Lisp_Object arg, oldval;
2085{
2086 int mask;
fbd6baed 2087 int old = f->output_data.w32->internal_border_width;
ee78dc32
GV
2088
2089 CHECK_NUMBER (arg, 0);
fbd6baed
GV
2090 f->output_data.w32->internal_border_width = XINT (arg);
2091 if (f->output_data.w32->internal_border_width < 0)
2092 f->output_data.w32->internal_border_width = 0;
ee78dc32 2093
fbd6baed 2094 if (f->output_data.w32->internal_border_width == old)
ee78dc32
GV
2095 return;
2096
fbd6baed 2097 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32
GV
2098 {
2099 BLOCK_INPUT;
2100 x_set_window_size (f, 0, f->width, f->height);
2101 UNBLOCK_INPUT;
2102 SET_FRAME_GARBAGED (f);
2103 }
2104}
2105
2106void
2107x_set_visibility (f, value, oldval)
2108 struct frame *f;
2109 Lisp_Object value, oldval;
2110{
2111 Lisp_Object frame;
2112 XSETFRAME (frame, f);
2113
2114 if (NILP (value))
2115 Fmake_frame_invisible (frame, Qt);
2116 else if (EQ (value, Qicon))
2117 Ficonify_frame (frame);
2118 else
2119 Fmake_frame_visible (frame);
2120}
2121
2122void
2123x_set_menu_bar_lines (f, value, oldval)
2124 struct frame *f;
2125 Lisp_Object value, oldval;
2126{
2127 int nlines;
2128 int olines = FRAME_MENU_BAR_LINES (f);
2129
2130 /* Right now, menu bars don't work properly in minibuf-only frames;
2131 most of the commands try to apply themselves to the minibuffer
2132 frame itslef, and get an error because you can't switch buffers
2133 in or split the minibuffer window. */
2134 if (FRAME_MINIBUF_ONLY_P (f))
2135 return;
2136
2137 if (INTEGERP (value))
2138 nlines = XINT (value);
2139 else
2140 nlines = 0;
2141
2142 FRAME_MENU_BAR_LINES (f) = 0;
2143 if (nlines)
2144 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2145 else
2146 {
2147 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2148 free_frame_menubar (f);
2149 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1edf84e7
GV
2150
2151 /* Adjust the frame size so that the client (text) dimensions
2152 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2153 set correctly. */
2154 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
ee78dc32
GV
2155 }
2156}
2157
2158/* Change the name of frame F to NAME. If NAME is nil, set F's name to
fbd6baed 2159 w32_id_name.
ee78dc32
GV
2160
2161 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2162 name; if NAME is a string, set F's name to NAME and set
2163 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2164
2165 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2166 suggesting a new name, which lisp code should override; if
2167 F->explicit_name is set, ignore the new name; otherwise, set it. */
2168
2169void
2170x_set_name (f, name, explicit)
2171 struct frame *f;
2172 Lisp_Object name;
2173 int explicit;
2174{
2175 /* Make sure that requests from lisp code override requests from
2176 Emacs redisplay code. */
2177 if (explicit)
2178 {
2179 /* If we're switching from explicit to implicit, we had better
2180 update the mode lines and thereby update the title. */
2181 if (f->explicit_name && NILP (name))
2182 update_mode_lines = 1;
2183
2184 f->explicit_name = ! NILP (name);
2185 }
2186 else if (f->explicit_name)
2187 return;
2188
fbd6baed 2189 /* If NAME is nil, set the name to the w32_id_name. */
ee78dc32
GV
2190 if (NILP (name))
2191 {
2192 /* Check for no change needed in this very common case
2193 before we do any consing. */
fbd6baed 2194 if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
ee78dc32
GV
2195 XSTRING (f->name)->data))
2196 return;
fbd6baed 2197 name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
ee78dc32
GV
2198 }
2199 else
2200 CHECK_STRING (name, 0);
2201
2202 /* Don't change the name if it's already NAME. */
2203 if (! NILP (Fstring_equal (name, f->name)))
2204 return;
2205
1edf84e7
GV
2206 f->name = name;
2207
2208 /* For setting the frame title, the title parameter should override
2209 the name parameter. */
2210 if (! NILP (f->title))
2211 name = f->title;
2212
fbd6baed 2213 if (FRAME_W32_WINDOW (f))
ee78dc32
GV
2214 {
2215 BLOCK_INPUT;
fbd6baed 2216 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
ee78dc32
GV
2217 UNBLOCK_INPUT;
2218 }
ee78dc32
GV
2219}
2220
2221/* This function should be called when the user's lisp code has
2222 specified a name for the frame; the name will override any set by the
2223 redisplay code. */
2224void
2225x_explicitly_set_name (f, arg, oldval)
2226 FRAME_PTR f;
2227 Lisp_Object arg, oldval;
2228{
2229 x_set_name (f, arg, 1);
2230}
2231
2232/* This function should be called by Emacs redisplay code to set the
2233 name; names set this way will never override names set by the user's
2234 lisp code. */
2235void
2236x_implicitly_set_name (f, arg, oldval)
2237 FRAME_PTR f;
2238 Lisp_Object arg, oldval;
2239{
2240 x_set_name (f, arg, 0);
2241}
1edf84e7
GV
2242\f
2243/* Change the title of frame F to NAME.
2244 If NAME is nil, use the frame name as the title.
2245
2246 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2247 name; if NAME is a string, set F's name to NAME and set
2248 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2249
2250 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2251 suggesting a new name, which lisp code should override; if
2252 F->explicit_name is set, ignore the new name; otherwise, set it. */
ee78dc32 2253
1edf84e7
GV
2254void
2255x_set_title (f, name)
2256 struct frame *f;
2257 Lisp_Object name;
2258{
2259 /* Don't change the title if it's already NAME. */
2260 if (EQ (name, f->title))
2261 return;
2262
2263 update_mode_lines = 1;
2264
2265 f->title = name;
2266
2267 if (NILP (name))
2268 name = f->name;
2269
2270 if (FRAME_W32_WINDOW (f))
2271 {
2272 BLOCK_INPUT;
2273 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
2274 UNBLOCK_INPUT;
2275 }
2276}
2277\f
ee78dc32
GV
2278void
2279x_set_autoraise (f, arg, oldval)
2280 struct frame *f;
2281 Lisp_Object arg, oldval;
2282{
2283 f->auto_raise = !EQ (Qnil, arg);
2284}
2285
2286void
2287x_set_autolower (f, arg, oldval)
2288 struct frame *f;
2289 Lisp_Object arg, oldval;
2290{
2291 f->auto_lower = !EQ (Qnil, arg);
2292}
2293
2294void
2295x_set_unsplittable (f, arg, oldval)
2296 struct frame *f;
2297 Lisp_Object arg, oldval;
2298{
2299 f->no_split = !NILP (arg);
2300}
2301
2302void
2303x_set_vertical_scroll_bars (f, arg, oldval)
2304 struct frame *f;
2305 Lisp_Object arg, oldval;
2306{
1026b400
RS
2307 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2308 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2309 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2310 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
ee78dc32 2311 {
1026b400
RS
2312 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = NILP (arg) ?
2313 vertical_scroll_bar_none :
2314 EQ (Qright, arg)
2315 ? vertical_scroll_bar_right
2316 : vertical_scroll_bar_left;
ee78dc32
GV
2317
2318 /* We set this parameter before creating the window for the
2319 frame, so we can get the geometry right from the start.
2320 However, if the window hasn't been created yet, we shouldn't
2321 call x_set_window_size. */
fbd6baed 2322 if (FRAME_W32_WINDOW (f))
ee78dc32
GV
2323 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2324 }
2325}
2326
2327void
2328x_set_scroll_bar_width (f, arg, oldval)
2329 struct frame *f;
2330 Lisp_Object arg, oldval;
2331{
2332 if (NILP (arg))
2333 {
2334 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2335 FRAME_SCROLL_BAR_COLS (f) = 2;
2336 }
2337 else if (INTEGERP (arg) && XINT (arg) > 0
2338 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2339 {
fbd6baed 2340 int wid = FONT_WIDTH (f->output_data.w32->font);
ee78dc32
GV
2341 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2342 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
fbd6baed 2343 if (FRAME_W32_WINDOW (f))
ee78dc32
GV
2344 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2345 }
2346}
2347\f
2348/* Subroutines of creating an frame. */
2349
2350/* Make sure that Vx_resource_name is set to a reasonable value.
2351 Fix it up, or set it to `emacs' if it is too hopeless. */
2352
2353static void
2354validate_x_resource_name ()
2355{
2356 int len;
2357 /* Number of valid characters in the resource name. */
2358 int good_count = 0;
2359 /* Number of invalid characters in the resource name. */
2360 int bad_count = 0;
2361 Lisp_Object new;
2362 int i;
2363
2364 if (STRINGP (Vx_resource_name))
2365 {
2366 unsigned char *p = XSTRING (Vx_resource_name)->data;
2367 int i;
2368
2369 len = XSTRING (Vx_resource_name)->size;
2370
2371 /* Only letters, digits, - and _ are valid in resource names.
2372 Count the valid characters and count the invalid ones. */
2373 for (i = 0; i < len; i++)
2374 {
2375 int c = p[i];
2376 if (! ((c >= 'a' && c <= 'z')
2377 || (c >= 'A' && c <= 'Z')
2378 || (c >= '0' && c <= '9')
2379 || c == '-' || c == '_'))
2380 bad_count++;
2381 else
2382 good_count++;
2383 }
2384 }
2385 else
2386 /* Not a string => completely invalid. */
2387 bad_count = 5, good_count = 0;
2388
2389 /* If name is valid already, return. */
2390 if (bad_count == 0)
2391 return;
2392
2393 /* If name is entirely invalid, or nearly so, use `emacs'. */
2394 if (good_count == 0
2395 || (good_count == 1 && bad_count > 0))
2396 {
2397 Vx_resource_name = build_string ("emacs");
2398 return;
2399 }
2400
2401 /* Name is partly valid. Copy it and replace the invalid characters
2402 with underscores. */
2403
2404 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2405
2406 for (i = 0; i < len; i++)
2407 {
2408 int c = XSTRING (new)->data[i];
2409 if (! ((c >= 'a' && c <= 'z')
2410 || (c >= 'A' && c <= 'Z')
2411 || (c >= '0' && c <= '9')
2412 || c == '-' || c == '_'))
2413 XSTRING (new)->data[i] = '_';
2414 }
2415}
2416
2417
2418extern char *x_get_string_resource ();
2419
2420DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2421 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2422This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2423class, where INSTANCE is the name under which Emacs was invoked, or\n\
2424the name specified by the `-name' or `-rn' command-line arguments.\n\
2425\n\
2426The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2427class, respectively. You must specify both of them or neither.\n\
2428If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2429and the class is `Emacs.CLASS.SUBCLASS'.")
2430 (attribute, class, component, subclass)
2431 Lisp_Object attribute, class, component, subclass;
2432{
2433 register char *value;
2434 char *name_key;
2435 char *class_key;
2436
2437 CHECK_STRING (attribute, 0);
2438 CHECK_STRING (class, 0);
2439
2440 if (!NILP (component))
2441 CHECK_STRING (component, 1);
2442 if (!NILP (subclass))
2443 CHECK_STRING (subclass, 2);
2444 if (NILP (component) != NILP (subclass))
2445 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2446
2447 validate_x_resource_name ();
2448
2449 /* Allocate space for the components, the dots which separate them,
2450 and the final '\0'. Make them big enough for the worst case. */
2451 name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
2452 + (STRINGP (component)
2453 ? XSTRING (component)->size : 0)
2454 + XSTRING (attribute)->size
2455 + 3);
2456
2457 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2458 + XSTRING (class)->size
2459 + (STRINGP (subclass)
2460 ? XSTRING (subclass)->size : 0)
2461 + 3);
2462
2463 /* Start with emacs.FRAMENAME for the name (the specific one)
2464 and with `Emacs' for the class key (the general one). */
2465 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2466 strcpy (class_key, EMACS_CLASS);
2467
2468 strcat (class_key, ".");
2469 strcat (class_key, XSTRING (class)->data);
2470
2471 if (!NILP (component))
2472 {
2473 strcat (class_key, ".");
2474 strcat (class_key, XSTRING (subclass)->data);
2475
2476 strcat (name_key, ".");
2477 strcat (name_key, XSTRING (component)->data);
2478 }
2479
2480 strcat (name_key, ".");
2481 strcat (name_key, XSTRING (attribute)->data);
2482
2483 value = x_get_string_resource (Qnil,
2484 name_key, class_key);
2485
2486 if (value != (char *) 0)
2487 return build_string (value);
2488 else
2489 return Qnil;
2490}
2491
2492/* Used when C code wants a resource value. */
2493
2494char *
2495x_get_resource_string (attribute, class)
2496 char *attribute, *class;
2497{
2498 register char *value;
2499 char *name_key;
2500 char *class_key;
2501
2502 /* Allocate space for the components, the dots which separate them,
2503 and the final '\0'. */
2504 name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
2505 + strlen (attribute) + 2);
2506 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2507 + strlen (class) + 2);
2508
2509 sprintf (name_key, "%s.%s",
2510 XSTRING (Vinvocation_name)->data,
2511 attribute);
2512 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2513
2514 return x_get_string_resource (selected_frame,
2515 name_key, class_key);
2516}
2517
2518/* Types we might convert a resource string into. */
2519enum resource_types
2520 {
2521 number, boolean, string, symbol
2522 };
2523
2524/* Return the value of parameter PARAM.
2525
2526 First search ALIST, then Vdefault_frame_alist, then the X defaults
2527 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2528
2529 Convert the resource to the type specified by desired_type.
2530
2531 If no default is specified, return Qunbound. If you call
2532 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2533 and don't let it get stored in any Lisp-visible variables! */
2534
2535static Lisp_Object
2536x_get_arg (alist, param, attribute, class, type)
2537 Lisp_Object alist, param;
2538 char *attribute;
2539 char *class;
2540 enum resource_types type;
2541{
2542 register Lisp_Object tem;
2543
2544 tem = Fassq (param, alist);
2545 if (EQ (tem, Qnil))
2546 tem = Fassq (param, Vdefault_frame_alist);
2547 if (EQ (tem, Qnil))
2548 {
2549
2550 if (attribute)
2551 {
2552 tem = Fx_get_resource (build_string (attribute),
2553 build_string (class),
2554 Qnil, Qnil);
2555
2556 if (NILP (tem))
2557 return Qunbound;
2558
2559 switch (type)
2560 {
2561 case number:
2562 return make_number (atoi (XSTRING (tem)->data));
2563
2564 case boolean:
2565 tem = Fdowncase (tem);
2566 if (!strcmp (XSTRING (tem)->data, "on")
2567 || !strcmp (XSTRING (tem)->data, "true"))
2568 return Qt;
2569 else
2570 return Qnil;
2571
2572 case string:
2573 return tem;
2574
2575 case symbol:
2576 /* As a special case, we map the values `true' and `on'
2577 to Qt, and `false' and `off' to Qnil. */
2578 {
2579 Lisp_Object lower;
2580 lower = Fdowncase (tem);
2581 if (!strcmp (XSTRING (lower)->data, "on")
2582 || !strcmp (XSTRING (lower)->data, "true"))
2583 return Qt;
2584 else if (!strcmp (XSTRING (lower)->data, "off")
2585 || !strcmp (XSTRING (lower)->data, "false"))
2586 return Qnil;
2587 else
2588 return Fintern (tem, Qnil);
2589 }
2590
2591 default:
2592 abort ();
2593 }
2594 }
2595 else
2596 return Qunbound;
2597 }
2598 return Fcdr (tem);
2599}
2600
2601/* Record in frame F the specified or default value according to ALIST
2602 of the parameter named PARAM (a Lisp symbol).
2603 If no value is specified for PARAM, look for an X default for XPROP
2604 on the frame named NAME.
2605 If that is not found either, use the value DEFLT. */
2606
2607static Lisp_Object
2608x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2609 struct frame *f;
2610 Lisp_Object alist;
2611 Lisp_Object prop;
2612 Lisp_Object deflt;
2613 char *xprop;
2614 char *xclass;
2615 enum resource_types type;
2616{
2617 Lisp_Object tem;
2618
2619 tem = x_get_arg (alist, prop, xprop, xclass, type);
2620 if (EQ (tem, Qunbound))
2621 tem = deflt;
2622 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2623 return tem;
2624}
2625\f
2626DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2627 "Parse an X-style geometry string STRING.\n\
2628Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2629The properties returned may include `top', `left', `height', and `width'.\n\
2630The value of `left' or `top' may be an integer,\n\
2631or a list (+ N) meaning N pixels relative to top/left corner,\n\
2632or a list (- N) meaning -N pixels relative to bottom/right corner.")
2633 (string)
2634 Lisp_Object string;
2635{
2636 int geometry, x, y;
2637 unsigned int width, height;
2638 Lisp_Object result;
2639
2640 CHECK_STRING (string, 0);
2641
2642 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2643 &x, &y, &width, &height);
2644
2645 result = Qnil;
2646 if (geometry & XValue)
2647 {
2648 Lisp_Object element;
2649
2650 if (x >= 0 && (geometry & XNegative))
2651 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2652 else if (x < 0 && ! (geometry & XNegative))
2653 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2654 else
2655 element = Fcons (Qleft, make_number (x));
2656 result = Fcons (element, result);
2657 }
2658
2659 if (geometry & YValue)
2660 {
2661 Lisp_Object element;
2662
2663 if (y >= 0 && (geometry & YNegative))
2664 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2665 else if (y < 0 && ! (geometry & YNegative))
2666 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2667 else
2668 element = Fcons (Qtop, make_number (y));
2669 result = Fcons (element, result);
2670 }
2671
2672 if (geometry & WidthValue)
2673 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2674 if (geometry & HeightValue)
2675 result = Fcons (Fcons (Qheight, make_number (height)), result);
2676
2677 return result;
2678}
2679
2680/* Calculate the desired size and position of this window,
2681 and return the flags saying which aspects were specified.
2682
2683 This function does not make the coordinates positive. */
2684
2685#define DEFAULT_ROWS 40
2686#define DEFAULT_COLS 80
2687
2688static int
2689x_figure_window_size (f, parms)
2690 struct frame *f;
2691 Lisp_Object parms;
2692{
2693 register Lisp_Object tem0, tem1, tem2;
2694 int height, width, left, top;
2695 register int geometry;
2696 long window_prompting = 0;
2697
2698 /* Default values if we fall through.
2699 Actually, if that happens we should get
2700 window manager prompting. */
1026b400 2701 SET_FRAME_WIDTH (f, DEFAULT_COLS);
ee78dc32
GV
2702 f->height = DEFAULT_ROWS;
2703 /* Window managers expect that if program-specified
2704 positions are not (0,0), they're intentional, not defaults. */
fbd6baed
GV
2705 f->output_data.w32->top_pos = 0;
2706 f->output_data.w32->left_pos = 0;
ee78dc32
GV
2707
2708 tem0 = x_get_arg (parms, Qheight, 0, 0, number);
2709 tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
2710 tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
2711 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2712 {
2713 if (!EQ (tem0, Qunbound))
2714 {
2715 CHECK_NUMBER (tem0, 0);
2716 f->height = XINT (tem0);
2717 }
2718 if (!EQ (tem1, Qunbound))
2719 {
2720 CHECK_NUMBER (tem1, 0);
1026b400 2721 SET_FRAME_WIDTH (f, XINT (tem1));
ee78dc32
GV
2722 }
2723 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2724 window_prompting |= USSize;
2725 else
2726 window_prompting |= PSize;
2727 }
2728
fbd6baed 2729 f->output_data.w32->vertical_scroll_bar_extra
ee78dc32
GV
2730 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2731 ? 0
2732 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2733 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
fbd6baed
GV
2734 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
2735 f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2736 f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
ee78dc32
GV
2737
2738 tem0 = x_get_arg (parms, Qtop, 0, 0, number);
2739 tem1 = x_get_arg (parms, Qleft, 0, 0, number);
2740 tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
2741 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2742 {
2743 if (EQ (tem0, Qminus))
2744 {
fbd6baed 2745 f->output_data.w32->top_pos = 0;
ee78dc32
GV
2746 window_prompting |= YNegative;
2747 }
2748 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
2749 && CONSP (XCONS (tem0)->cdr)
2750 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2751 {
fbd6baed 2752 f->output_data.w32->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
ee78dc32
GV
2753 window_prompting |= YNegative;
2754 }
2755 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
2756 && CONSP (XCONS (tem0)->cdr)
2757 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2758 {
fbd6baed 2759 f->output_data.w32->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
ee78dc32
GV
2760 }
2761 else if (EQ (tem0, Qunbound))
fbd6baed 2762 f->output_data.w32->top_pos = 0;
ee78dc32
GV
2763 else
2764 {
2765 CHECK_NUMBER (tem0, 0);
fbd6baed
GV
2766 f->output_data.w32->top_pos = XINT (tem0);
2767 if (f->output_data.w32->top_pos < 0)
ee78dc32
GV
2768 window_prompting |= YNegative;
2769 }
2770
2771 if (EQ (tem1, Qminus))
2772 {
fbd6baed 2773 f->output_data.w32->left_pos = 0;
ee78dc32
GV
2774 window_prompting |= XNegative;
2775 }
2776 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
2777 && CONSP (XCONS (tem1)->cdr)
2778 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2779 {
fbd6baed 2780 f->output_data.w32->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
ee78dc32
GV
2781 window_prompting |= XNegative;
2782 }
2783 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
2784 && CONSP (XCONS (tem1)->cdr)
2785 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2786 {
fbd6baed 2787 f->output_data.w32->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
ee78dc32
GV
2788 }
2789 else if (EQ (tem1, Qunbound))
fbd6baed 2790 f->output_data.w32->left_pos = 0;
ee78dc32
GV
2791 else
2792 {
2793 CHECK_NUMBER (tem1, 0);
fbd6baed
GV
2794 f->output_data.w32->left_pos = XINT (tem1);
2795 if (f->output_data.w32->left_pos < 0)
ee78dc32
GV
2796 window_prompting |= XNegative;
2797 }
2798
2799 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2800 window_prompting |= USPosition;
2801 else
2802 window_prompting |= PPosition;
2803 }
2804
2805 return window_prompting;
2806}
2807
2808\f
2809
fbd6baed 2810extern LRESULT CALLBACK w32_wnd_proc ();
ee78dc32
GV
2811
2812BOOL
fbd6baed 2813w32_init_class (hinst)
ee78dc32
GV
2814 HINSTANCE hinst;
2815{
2816 WNDCLASS wc;
2817
5ac45f98 2818 wc.style = CS_HREDRAW | CS_VREDRAW;
fbd6baed 2819 wc.lpfnWndProc = (WNDPROC) w32_wnd_proc;
ee78dc32
GV
2820 wc.cbClsExtra = 0;
2821 wc.cbWndExtra = WND_EXTRA_BYTES;
2822 wc.hInstance = hinst;
2823 wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
2824 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
2825 wc.hbrBackground = NULL; // GetStockObject (WHITE_BRUSH);
2826 wc.lpszMenuName = NULL;
2827 wc.lpszClassName = EMACS_CLASS;
2828
2829 return (RegisterClass (&wc));
2830}
2831
2832HWND
fbd6baed 2833w32_createscrollbar (f, bar)
ee78dc32
GV
2834 struct frame *f;
2835 struct scroll_bar * bar;
2836{
2837 return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
2838 /* Position and size of scroll bar. */
2839 XINT(bar->left), XINT(bar->top),
2840 XINT(bar->width), XINT(bar->height),
fbd6baed 2841 FRAME_W32_WINDOW (f),
ee78dc32
GV
2842 NULL,
2843 hinst,
2844 NULL));
2845}
2846
2847void
fbd6baed 2848w32_createwindow (f)
ee78dc32
GV
2849 struct frame *f;
2850{
2851 HWND hwnd;
1edf84e7
GV
2852 RECT rect;
2853
2854 rect.left = rect.top = 0;
2855 rect.right = PIXEL_WIDTH (f);
2856 rect.bottom = PIXEL_HEIGHT (f);
2857
2858 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
2859 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32
GV
2860
2861 /* Do first time app init */
2862
2863 if (!hprevinst)
2864 {
fbd6baed 2865 w32_init_class (hinst);
ee78dc32
GV
2866 }
2867
1edf84e7
GV
2868 FRAME_W32_WINDOW (f) = hwnd
2869 = CreateWindow (EMACS_CLASS,
2870 f->namebuf,
2871 f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
2872 f->output_data.w32->left_pos,
2873 f->output_data.w32->top_pos,
2874 rect.right - rect.left,
2875 rect.bottom - rect.top,
2876 NULL,
2877 NULL,
2878 hinst,
2879 NULL);
2880
ee78dc32
GV
2881 if (hwnd)
2882 {
1edf84e7
GV
2883 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
2884 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
2885 SetWindowLong (hwnd, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
2886 SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
fbd6baed 2887 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, f->output_data.w32->background_pixel);
ee78dc32 2888
5ac45f98
GV
2889 /* Do this to discard the default setting specified by our parent. */
2890 ShowWindow (hwnd, SW_HIDE);
3c190163 2891 }
3c190163
GV
2892}
2893
fbd6baed 2894/* Convert between the modifier bits W32 uses and the modifier bits
ee78dc32
GV
2895 Emacs uses. */
2896unsigned int
fbd6baed 2897w32_get_modifiers ()
ee78dc32
GV
2898{
2899 return (((GetKeyState (VK_SHIFT)&0x8000) ? shift_modifier : 0) |
2900 ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier : 0) |
8c205c63 2901 ((GetKeyState (VK_MENU)&0x8000) ?
fbd6baed 2902 ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
ee78dc32
GV
2903}
2904
2905void
2906my_post_msg (wmsg, hwnd, msg, wParam, lParam)
fbd6baed 2907 W32Msg * wmsg;
ee78dc32
GV
2908 HWND hwnd;
2909 UINT msg;
2910 WPARAM wParam;
2911 LPARAM lParam;
2912{
2913 wmsg->msg.hwnd = hwnd;
2914 wmsg->msg.message = msg;
2915 wmsg->msg.wParam = wParam;
2916 wmsg->msg.lParam = lParam;
2917 wmsg->msg.time = GetMessageTime ();
2918
2919 post_msg (wmsg);
2920}
2921
e9e23e23 2922/* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
a1a80b40
GV
2923 between left and right keys as advertised. We test for this
2924 support dynamically, and set a flag when the support is absent. If
2925 absent, we keep track of the left and right control and alt keys
2926 ourselves. This is particularly necessary on keyboards that rely
2927 upon the AltGr key, which is represented as having the left control
2928 and right alt keys pressed. For these keyboards, we need to know
2929 when the left alt key has been pressed in addition to the AltGr key
2930 so that we can properly support M-AltGr-key sequences (such as M-@
2931 on Swedish keyboards). */
2932
2933#define EMACS_LCONTROL 0
2934#define EMACS_RCONTROL 1
2935#define EMACS_LMENU 2
2936#define EMACS_RMENU 3
2937
2938static int modifiers[4];
2939static int modifiers_recorded;
2940static int modifier_key_support_tested;
2941
2942static void
2943test_modifier_support (unsigned int wparam)
2944{
2945 unsigned int l, r;
2946
2947 if (wparam != VK_CONTROL && wparam != VK_MENU)
2948 return;
2949 if (wparam == VK_CONTROL)
2950 {
2951 l = VK_LCONTROL;
2952 r = VK_RCONTROL;
2953 }
2954 else
2955 {
2956 l = VK_LMENU;
2957 r = VK_RMENU;
2958 }
2959 if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
2960 modifiers_recorded = 1;
2961 else
2962 modifiers_recorded = 0;
2963 modifier_key_support_tested = 1;
2964}
2965
2966static void
2967record_keydown (unsigned int wparam, unsigned int lparam)
2968{
2969 int i;
2970
2971 if (!modifier_key_support_tested)
2972 test_modifier_support (wparam);
2973
2974 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
2975 return;
2976
2977 if (wparam == VK_CONTROL)
2978 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
2979 else
2980 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
2981
2982 modifiers[i] = 1;
2983}
2984
2985static void
2986record_keyup (unsigned int wparam, unsigned int lparam)
2987{
2988 int i;
2989
2990 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
2991 return;
2992
2993 if (wparam == VK_CONTROL)
2994 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
2995 else
2996 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
2997
2998 modifiers[i] = 0;
2999}
3000
da36a4d6
GV
3001/* Emacs can lose focus while a modifier key has been pressed. When
3002 it regains focus, be conservative and clear all modifiers since
3003 we cannot reconstruct the left and right modifier state. */
3004static void
3005reset_modifiers ()
3006{
8681157a
RS
3007 SHORT ctrl, alt;
3008
da36a4d6
GV
3009 if (!modifiers_recorded)
3010 return;
8681157a
RS
3011
3012 ctrl = GetAsyncKeyState (VK_CONTROL);
3013 alt = GetAsyncKeyState (VK_MENU);
3014
3015 if (ctrl == 0 || alt == 0)
3016 /* Emacs doesn't have keyboard focus. Do nothing. */
3017 return;
3018
3019 if (!(ctrl & 0x08000))
3020 /* Clear any recorded control modifier state. */
3021 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3022
3023 if (!(alt & 0x08000))
3024 /* Clear any recorded alt modifier state. */
3025 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3026
3027 /* Otherwise, leave the modifier state as it was when Emacs lost
3028 keyboard focus. */
da36a4d6
GV
3029}
3030
7830e24b
RS
3031/* Synchronize modifier state with what is reported with the current
3032 keystroke. Even if we cannot distinguish between left and right
3033 modifier keys, we know that, if no modifiers are set, then neither
3034 the left or right modifier should be set. */
3035static void
3036sync_modifiers ()
3037{
3038 if (!modifiers_recorded)
3039 return;
3040
3041 if (!(GetKeyState (VK_CONTROL) & 0x8000))
3042 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
3043
3044 if (!(GetKeyState (VK_MENU) & 0x8000))
3045 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
3046}
3047
a1a80b40
GV
3048static int
3049modifier_set (int vkey)
3050{
891560d6
KH
3051 if (vkey == VK_CAPITAL)
3052 return (GetKeyState (vkey) & 0x1);
a1a80b40
GV
3053 if (!modifiers_recorded)
3054 return (GetKeyState (vkey) & 0x8000);
3055
3056 switch (vkey)
3057 {
3058 case VK_LCONTROL:
3059 return modifiers[EMACS_LCONTROL];
3060 case VK_RCONTROL:
3061 return modifiers[EMACS_RCONTROL];
3062 case VK_LMENU:
3063 return modifiers[EMACS_LMENU];
3064 case VK_RMENU:
3065 return modifiers[EMACS_RMENU];
a1a80b40
GV
3066 default:
3067 break;
3068 }
3069 return (GetKeyState (vkey) & 0x8000);
3070}
3071
3072/* We map the VK_* modifiers into console modifier constants
3073 so that we can use the same routines to handle both console
3074 and window input. */
3075
3076static int
3077construct_modifiers (unsigned int wparam, unsigned int lparam)
3078{
3079 int mods;
3080
3081 if (wparam != VK_CONTROL && wparam != VK_MENU)
3082 mods = GetLastError ();
3083
3084 mods = 0;
3085 mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
3086 mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
3087 mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
3088 mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
3089 mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
3090 mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
3091
3092 return mods;
3093}
3094
da36a4d6
GV
3095static unsigned int
3096map_keypad_keys (unsigned int wparam, unsigned int lparam)
3097{
3098 unsigned int extended = (lparam & 0x1000000L);
3099
3100 if (wparam < VK_CLEAR || wparam > VK_DELETE)
3101 return wparam;
3102
3103 if (wparam == VK_RETURN)
3104 return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
3105
3106 if (wparam >= VK_PRIOR && wparam <= VK_DOWN)
3107 return (!extended ? (VK_NUMPAD_PRIOR + (wparam - VK_PRIOR)) : wparam);
3108
3109 if (wparam == VK_INSERT || wparam == VK_DELETE)
3110 return (!extended ? (VK_NUMPAD_INSERT + (wparam - VK_INSERT)) : wparam);
3111
3112 if (wparam == VK_CLEAR)
3113 return (!extended ? VK_NUMPAD_CLEAR : wparam);
3114
3115 return wparam;
3116}
3117
5ac45f98
GV
3118/* Main message dispatch loop. */
3119
1edf84e7
GV
3120static void
3121w32_msg_pump (deferred_msg * msg_buf)
5ac45f98
GV
3122{
3123 MSG msg;
3124
5ac45f98
GV
3125 while (GetMessage (&msg, NULL, 0, 0))
3126 {
3127 if (msg.hwnd == NULL)
3128 {
3129 switch (msg.message)
3130 {
5ac45f98 3131 case WM_EMACS_CREATEWINDOW:
fbd6baed 3132 w32_createwindow ((struct frame *) msg.wParam);
1edf84e7
GV
3133 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3134 abort ();
5ac45f98 3135 break;
1edf84e7
GV
3136 default:
3137 /* No need to be so draconian! */
3138 /* abort (); */
3139 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
5ac45f98
GV
3140 }
3141 }
3142 else
3143 {
3144 DispatchMessage (&msg);
3145 }
1edf84e7
GV
3146
3147 /* Exit nested loop when our deferred message has completed. */
3148 if (msg_buf->completed)
3149 break;
5ac45f98 3150 }
1edf84e7
GV
3151}
3152
3153deferred_msg * deferred_msg_head;
3154
3155static deferred_msg *
3156find_deferred_msg (HWND hwnd, UINT msg)
3157{
3158 deferred_msg * item;
3159
3160 /* Don't actually need synchronization for read access, since
3161 modification of single pointer is always atomic. */
3162 /* enter_crit (); */
3163
3164 for (item = deferred_msg_head; item != NULL; item = item->next)
3165 if (item->w32msg.msg.hwnd == hwnd
3166 && item->w32msg.msg.message == msg)
3167 break;
3168
3169 /* leave_crit (); */
3170
3171 return item;
3172}
3173
3174static LRESULT
3175send_deferred_msg (deferred_msg * msg_buf,
3176 HWND hwnd,
3177 UINT msg,
3178 WPARAM wParam,
3179 LPARAM lParam)
3180{
3181 /* Only input thread can send deferred messages. */
3182 if (GetCurrentThreadId () != dwWindowsThreadId)
3183 abort ();
3184
3185 /* It is an error to send a message that is already deferred. */
3186 if (find_deferred_msg (hwnd, msg) != NULL)
3187 abort ();
3188
3189 /* Enforced synchronization is not needed because this is the only
3190 function that alters deferred_msg_head, and the following critical
3191 section is guaranteed to only be serially reentered (since only the
3192 input thread can call us). */
3193
3194 /* enter_crit (); */
3195
3196 msg_buf->completed = 0;
3197 msg_buf->next = deferred_msg_head;
3198 deferred_msg_head = msg_buf;
3199 my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam);
3200
3201 /* leave_crit (); */
3202
3203 /* Start a new nested message loop to process other messages until
3204 this one is completed. */
3205 w32_msg_pump (msg_buf);
3206
3207 deferred_msg_head = msg_buf->next;
3208
3209 return msg_buf->result;
3210}
3211
3212void
3213complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
3214{
3215 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
3216
3217 if (msg_buf == NULL)
3218 abort ();
3219
3220 msg_buf->result = result;
3221 msg_buf->completed = 1;
3222
3223 /* Ensure input thread is woken so it notices the completion. */
3224 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
3225}
3226
3227
3228DWORD
3229w32_msg_worker (dw)
3230 DWORD dw;
3231{
3232 MSG msg;
3233 deferred_msg dummy_buf;
3234
3235 /* Ensure our message queue is created */
3236
3237 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
5ac45f98 3238
1edf84e7
GV
3239 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3240 abort ();
3241
3242 memset (&dummy_buf, 0, sizeof (dummy_buf));
3243 dummy_buf.w32msg.msg.hwnd = NULL;
3244 dummy_buf.w32msg.msg.message = WM_NULL;
3245
3246 /* This is the inital message loop which should only exit when the
3247 application quits. */
3248 w32_msg_pump (&dummy_buf);
3249
3250 return 0;
5ac45f98
GV
3251}
3252
ee78dc32
GV
3253/* Main window procedure */
3254
3255extern char *lispy_function_keys[];
3256
3257LRESULT CALLBACK
fbd6baed 3258w32_wnd_proc (hwnd, msg, wParam, lParam)
ee78dc32
GV
3259 HWND hwnd;
3260 UINT msg;
3261 WPARAM wParam;
3262 LPARAM lParam;
3263{
3264 struct frame *f;
fbd6baed
GV
3265 struct w32_display_info *dpyinfo = &one_w32_display_info;
3266 W32Msg wmsg;
84fb1139
KH
3267 int windows_translate;
3268
a6085637
KH
3269 /* Note that it is okay to call x_window_to_frame, even though we are
3270 not running in the main lisp thread, because frame deletion
3271 requires the lisp thread to synchronize with this thread. Thus, if
3272 a frame struct is returned, it can be used without concern that the
3273 lisp thread might make it disappear while we are using it.
3274
3275 NB. Walking the frame list in this thread is safe (as long as
3276 writes of Lisp_Object slots are atomic, which they are on Windows).
3277 Although delete-frame can destructively modify the frame list while
3278 we are walking it, a garbage collection cannot occur until after
3279 delete-frame has synchronized with this thread.
3280
3281 It is also safe to use functions that make GDI calls, such as
fbd6baed 3282 w32_clear_rect, because these functions must obtain a DC handle
a6085637
KH
3283 from the frame struct using get_frame_dc which is thread-aware. */
3284
ee78dc32
GV
3285 switch (msg)
3286 {
3287 case WM_ERASEBKGND:
a6085637
KH
3288 f = x_window_to_frame (dpyinfo, hwnd);
3289 if (f)
3290 {
3291 GetUpdateRect (hwnd, &wmsg.rect, FALSE);
fbd6baed 3292 w32_clear_rect (f, NULL, &wmsg.rect);
a6085637 3293 }
5ac45f98
GV
3294 return 1;
3295 case WM_PALETTECHANGED:
3296 /* ignore our own changes */
3297 if ((HWND)wParam != hwnd)
3298 {
a6085637
KH
3299 f = x_window_to_frame (dpyinfo, hwnd);
3300 if (f)
3301 /* get_frame_dc will realize our palette and force all
3302 frames to be redrawn if needed. */
3303 release_frame_dc (f, get_frame_dc (f));
5ac45f98
GV
3304 }
3305 return 0;
ee78dc32
GV
3306 case WM_PAINT:
3307 {
3308 PAINTSTRUCT paintStruct;
5ac45f98
GV
3309
3310 enter_crit ();
ee78dc32
GV
3311 BeginPaint (hwnd, &paintStruct);
3312 wmsg.rect = paintStruct.rcPaint;
3313 EndPaint (hwnd, &paintStruct);
5ac45f98
GV
3314 leave_crit ();
3315
ee78dc32
GV
3316 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3317
3318 return (0);
3319 }
a1a80b40
GV
3320
3321 case WM_KEYUP:
3322 case WM_SYSKEYUP:
3323 record_keyup (wParam, lParam);
3324 goto dflt;
3325
ee78dc32
GV
3326 case WM_KEYDOWN:
3327 case WM_SYSKEYDOWN:
7830e24b
RS
3328 /* Synchronize modifiers with current keystroke. */
3329 sync_modifiers ();
3330
a1a80b40
GV
3331 record_keydown (wParam, lParam);
3332
da36a4d6 3333 wParam = map_keypad_keys (wParam, lParam);
84fb1139
KH
3334
3335 windows_translate = 0;
a1a80b40 3336 switch (wParam) {
da36a4d6
GV
3337 case VK_LWIN:
3338 case VK_RWIN:
3339 case VK_APPS:
3340 /* More support for these keys will likely be necessary. */
fbd6baed 3341 if (!NILP (Vw32_pass_optional_keys_to_system))
84fb1139 3342 windows_translate = 1;
da36a4d6
GV
3343 break;
3344 case VK_MENU:
fbd6baed 3345 if (NILP (Vw32_pass_alt_to_system))
da36a4d6 3346 return 0;
84fb1139
KH
3347 windows_translate = 1;
3348 break;
da36a4d6
GV
3349 case VK_CONTROL:
3350 case VK_CAPITAL:
3351 case VK_SHIFT:
8681157a
RS
3352 case VK_NUMLOCK:
3353 case VK_SCROLL:
84fb1139
KH
3354 windows_translate = 1;
3355 break;
a1a80b40 3356 default:
da36a4d6
GV
3357 /* If not defined as a function key, change it to a WM_CHAR message. */
3358 if (lispy_function_keys[wParam] == 0)
3359 msg = WM_CHAR;
3c190163 3360 break;
a1a80b40
GV
3361 }
3362
84fb1139
KH
3363 if (windows_translate)
3364 {
e9e23e23 3365 MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
84fb1139 3366
e9e23e23
GV
3367 windows_msg.time = GetMessageTime ();
3368 TranslateMessage (&windows_msg);
84fb1139
KH
3369 goto dflt;
3370 }
3371
ee78dc32
GV
3372 /* Fall through */
3373
3374 case WM_SYSCHAR:
3375 case WM_CHAR:
a1a80b40 3376 wmsg.dwModifiers = construct_modifiers (wParam, lParam);
da36a4d6 3377
3d32fc48 3378#if 1
3aef7b4e
GV
3379 /* Detect quit_char and set quit-flag directly. Note that we
3380 still need to post a message to ensure the main thread will be
3381 woken up if blocked in sys_select(), but we do NOT want to post
3382 the quit_char message itself (because it will usually be as if
3383 the user had typed quit_char twice). Instead, we post a dummy
3384 message that has no particular effect. */
5ac45f98
GV
3385 {
3386 int c = wParam;
3387 if (isalpha (c) && (wmsg.dwModifiers == LEFT_CTRL_PRESSED
3388 || wmsg.dwModifiers == RIGHT_CTRL_PRESSED))
3389 c = make_ctrl_char (c) & 0377;
3390 if (c == quit_char)
3aef7b4e
GV
3391 {
3392 Vquit_flag = Qt;
3393
3394 /* The choice of message is somewhat arbitrary, as long as
3395 the main thread handler just ignores it. */
3396 msg = WM_QUIT;
3397 }
5ac45f98 3398 }
4ba07e88
GV
3399#endif
3400
3aef7b4e
GV
3401 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3402
ee78dc32 3403 break;
da36a4d6 3404
5ac45f98
GV
3405 /* Simulate middle mouse button events when left and right buttons
3406 are used together, but only if user has two button mouse. */
ee78dc32 3407 case WM_LBUTTONDOWN:
5ac45f98 3408 case WM_RBUTTONDOWN:
fbd6baed 3409 if (XINT (Vw32_num_mouse_buttons) == 3)
5ac45f98
GV
3410 goto handle_plain_button;
3411
3412 {
3413 int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
3414 int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
3415
3cb20f4a
RS
3416 if (button_state & this)
3417 return 0;
5ac45f98
GV
3418
3419 if (button_state == 0)
3420 SetCapture (hwnd);
3421
3422 button_state |= this;
3423
3424 if (button_state & other)
3425 {
84fb1139 3426 if (mouse_button_timer)
5ac45f98 3427 {
84fb1139
KH
3428 KillTimer (hwnd, mouse_button_timer);
3429 mouse_button_timer = 0;
5ac45f98
GV
3430
3431 /* Generate middle mouse event instead. */
3432 msg = WM_MBUTTONDOWN;
3433 button_state |= MMOUSE;
3434 }
3435 else if (button_state & MMOUSE)
3436 {
3437 /* Ignore button event if we've already generated a
3438 middle mouse down event. This happens if the
3439 user releases and press one of the two buttons
3440 after we've faked a middle mouse event. */
3441 return 0;
3442 }
3443 else
3444 {
3445 /* Flush out saved message. */
84fb1139 3446 post_msg (&saved_mouse_button_msg);
5ac45f98 3447 }
fbd6baed 3448 wmsg.dwModifiers = w32_get_modifiers ();
5ac45f98
GV
3449 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3450
3451 /* Clear message buffer. */
84fb1139 3452 saved_mouse_button_msg.msg.hwnd = 0;
5ac45f98
GV
3453 }
3454 else
3455 {
3456 /* Hold onto message for now. */
84fb1139 3457 mouse_button_timer =
fbd6baed 3458 SetTimer (hwnd, MOUSE_BUTTON_ID, XINT (Vw32_mouse_button_tolerance), NULL);
84fb1139
KH
3459 saved_mouse_button_msg.msg.hwnd = hwnd;
3460 saved_mouse_button_msg.msg.message = msg;
3461 saved_mouse_button_msg.msg.wParam = wParam;
3462 saved_mouse_button_msg.msg.lParam = lParam;
3463 saved_mouse_button_msg.msg.time = GetMessageTime ();
fbd6baed 3464 saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
5ac45f98
GV
3465 }
3466 }
3467 return 0;
3468
ee78dc32 3469 case WM_LBUTTONUP:
5ac45f98 3470 case WM_RBUTTONUP:
fbd6baed 3471 if (XINT (Vw32_num_mouse_buttons) == 3)
5ac45f98
GV
3472 goto handle_plain_button;
3473
3474 {
3475 int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
3476 int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
3477
3cb20f4a
RS
3478 if ((button_state & this) == 0)
3479 return 0;
5ac45f98
GV
3480
3481 button_state &= ~this;
3482
3483 if (button_state & MMOUSE)
3484 {
3485 /* Only generate event when second button is released. */
3486 if ((button_state & other) == 0)
3487 {
3488 msg = WM_MBUTTONUP;
3489 button_state &= ~MMOUSE;
3490
3491 if (button_state) abort ();
3492 }
3493 else
3494 return 0;
3495 }
3496 else
3497 {
3498 /* Flush out saved message if necessary. */
84fb1139 3499 if (saved_mouse_button_msg.msg.hwnd)
5ac45f98 3500 {
84fb1139 3501 post_msg (&saved_mouse_button_msg);
5ac45f98
GV
3502 }
3503 }
fbd6baed 3504 wmsg.dwModifiers = w32_get_modifiers ();
5ac45f98
GV
3505 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3506
3507 /* Always clear message buffer and cancel timer. */
84fb1139
KH
3508 saved_mouse_button_msg.msg.hwnd = 0;
3509 KillTimer (hwnd, mouse_button_timer);
3510 mouse_button_timer = 0;
5ac45f98
GV
3511
3512 if (button_state == 0)
3513 ReleaseCapture ();
3514 }
3515 return 0;
3516
ee78dc32
GV
3517 case WM_MBUTTONDOWN:
3518 case WM_MBUTTONUP:
5ac45f98 3519 handle_plain_button:
ee78dc32
GV
3520 {
3521 BOOL up;
1edf84e7 3522 int button;
ee78dc32 3523
1edf84e7 3524 if (parse_button (msg, &button, &up))
ee78dc32
GV
3525 {
3526 if (up) ReleaseCapture ();
3527 else SetCapture (hwnd);
1edf84e7
GV
3528 button = (button == 0) ? LMOUSE :
3529 ((button == 1) ? MMOUSE : RMOUSE);
3530 if (up)
3531 button_state &= ~button;
3532 else
3533 button_state |= button;
ee78dc32
GV
3534 }
3535 }
3536
fbd6baed 3537 wmsg.dwModifiers = w32_get_modifiers ();
ee78dc32 3538 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
5ac45f98
GV
3539 return 0;
3540
84fb1139 3541 case WM_VSCROLL:
5ac45f98 3542 case WM_MOUSEMOVE:
fbd6baed 3543 if (XINT (Vw32_mouse_move_interval) <= 0
84fb1139
KH
3544 || (msg == WM_MOUSEMOVE && button_state == 0))
3545 {
fbd6baed 3546 wmsg.dwModifiers = w32_get_modifiers ();
84fb1139
KH
3547 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3548 return 0;
3549 }
3550
3551 /* Hang onto mouse move and scroll messages for a bit, to avoid
3552 sending such events to Emacs faster than it can process them.
3553 If we get more events before the timer from the first message
3554 expires, we just replace the first message. */
3555
3556 if (saved_mouse_move_msg.msg.hwnd == 0)
3557 mouse_move_timer =
fbd6baed 3558 SetTimer (hwnd, MOUSE_MOVE_ID, XINT (Vw32_mouse_move_interval), NULL);
84fb1139
KH
3559
3560 /* Hold onto message for now. */
3561 saved_mouse_move_msg.msg.hwnd = hwnd;
3562 saved_mouse_move_msg.msg.message = msg;
3563 saved_mouse_move_msg.msg.wParam = wParam;
3564 saved_mouse_move_msg.msg.lParam = lParam;
3565 saved_mouse_move_msg.msg.time = GetMessageTime ();
fbd6baed 3566 saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
84fb1139
KH
3567
3568 return 0;
3569
1edf84e7
GV
3570 case WM_MOUSEWHEEL:
3571 wmsg.dwModifiers = w32_get_modifiers ();
3572 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3573 return 0;
3574
84fb1139
KH
3575 case WM_TIMER:
3576 /* Flush out saved messages if necessary. */
3577 if (wParam == mouse_button_timer)
5ac45f98 3578 {
84fb1139
KH
3579 if (saved_mouse_button_msg.msg.hwnd)
3580 {
3581 post_msg (&saved_mouse_button_msg);
3582 saved_mouse_button_msg.msg.hwnd = 0;
3583 }
3584 KillTimer (hwnd, mouse_button_timer);
3585 mouse_button_timer = 0;
3586 }
3587 else if (wParam == mouse_move_timer)
3588 {
3589 if (saved_mouse_move_msg.msg.hwnd)
3590 {
3591 post_msg (&saved_mouse_move_msg);
3592 saved_mouse_move_msg.msg.hwnd = 0;
3593 }
3594 KillTimer (hwnd, mouse_move_timer);
3595 mouse_move_timer = 0;
5ac45f98 3596 }
5ac45f98 3597 return 0;
84fb1139
KH
3598
3599 case WM_NCACTIVATE:
3600 /* Windows doesn't send us focus messages when putting up and
e9e23e23 3601 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
84fb1139
KH
3602 The only indication we get that something happened is receiving
3603 this message afterwards. So this is a good time to reset our
3604 keyboard modifiers' state. */
3605 reset_modifiers ();
3606 goto dflt;
da36a4d6 3607
1edf84e7
GV
3608 case WM_INITMENU:
3609 /* We must ensure menu bar is fully constructed and up to date
3610 before allowing user interaction with it. To achieve this
3611 we send this message to the lisp thread and wait for a
3612 reply (whose value is not actually needed) to indicate that
3613 the menu bar is now ready for use, so we can now return.
3614
3615 To remain responsive in the meantime, we enter a nested message
3616 loop that can process all other messages.
3617
3618 However, we skip all this if the message results from calling
3619 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3620 thread a message because it is blocked on us at this point. We
3621 set menubar_active before calling TrackPopupMenu to indicate
3622 this (there is no possibility of confusion with real menubar
3623 being active). */
3624
3625 f = x_window_to_frame (dpyinfo, hwnd);
3626 if (f
3627 && (f->output_data.w32->menubar_active
3628 /* We can receive this message even in the absence of a
3629 menubar (ie. when the system menu is activated) - in this
3630 case we do NOT want to forward the message, otherwise it
3631 will cause the menubar to suddenly appear when the user
3632 had requested it to be turned off! */
3633 || f->output_data.w32->menubar_widget == NULL))
3634 return 0;
3635
3636 {
3637 deferred_msg msg_buf;
3638
3639 /* Detect if message has already been deferred; in this case
3640 we cannot return any sensible value to ignore this. */
3641 if (find_deferred_msg (hwnd, msg) != NULL)
3642 abort ();
3643
3644 return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
3645 }
3646
3647 case WM_EXITMENULOOP:
3648 f = x_window_to_frame (dpyinfo, hwnd);
3649
3650 /* Indicate that menubar can be modified again. */
3651 if (f)
3652 f->output_data.w32->menubar_active = 0;
3653 goto dflt;
3654
3655#if 0
3656 /* Still not right - can't distinguish between clicks in the
3657 client area of the frame from clicks forwarded from the scroll
3658 bars - may have to hook WM_NCHITTEST to remember the mouse
3659 position and then check if it is in the client area ourselves. */
3660 case WM_MOUSEACTIVATE:
3661 /* Discard the mouse click that activates a frame, allowing the
3662 user to click anywhere without changing point (or worse!).
3663 Don't eat mouse clicks on scrollbars though!! */
3664 if (LOWORD (lParam) == HTCLIENT )
3665 return MA_ACTIVATEANDEAT;
3666 goto dflt;
3667#endif
3668
3669 case WM_ACTIVATE:
3670 case WM_ACTIVATEAPP:
3671 case WM_WINDOWPOSCHANGED:
3672 case WM_SHOWWINDOW:
3673 /* Inform lisp thread that a frame might have just been obscured
3674 or exposed, so should recheck visibility of all frames. */
3675 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3676 goto dflt;
3677
da36a4d6
GV
3678 case WM_SETFOCUS:
3679 reset_modifiers ();
8681157a 3680 case WM_KILLFOCUS:
ee78dc32
GV
3681 case WM_MOVE:
3682 case WM_SIZE:
ee78dc32 3683 case WM_COMMAND:
fbd6baed 3684 wmsg.dwModifiers = w32_get_modifiers ();
ee78dc32
GV
3685 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3686 goto dflt;
8847d890
RS
3687
3688 case WM_CLOSE:
fbd6baed 3689 wmsg.dwModifiers = w32_get_modifiers ();
8847d890
RS
3690 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3691 return 0;
3692
ee78dc32
GV
3693 case WM_WINDOWPOSCHANGING:
3694 {
3695 WINDOWPLACEMENT wp;
3696 LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
1edf84e7
GV
3697
3698 wp.length = sizeof (WINDOWPLACEMENT);
ee78dc32
GV
3699 GetWindowPlacement (hwnd, &wp);
3700
1edf84e7 3701 if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0)
ee78dc32
GV
3702 {
3703 RECT rect;
3704 int wdiff;
3705 int hdiff;
1edf84e7
GV
3706 DWORD font_width;
3707 DWORD line_height;
3708 DWORD internal_border;
3709 DWORD scrollbar_extra;
ee78dc32
GV
3710 RECT wr;
3711
5ac45f98 3712 wp.length = sizeof(wp);
ee78dc32
GV
3713 GetWindowRect (hwnd, &wr);
3714
3c190163 3715 enter_crit ();
ee78dc32 3716
1edf84e7
GV
3717 font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
3718 line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
3719 internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
3720 scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
ee78dc32 3721
3c190163 3722 leave_crit ();
ee78dc32
GV
3723
3724 memset (&rect, 0, sizeof (rect));
3725 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
3726 GetMenu (hwnd) != NULL);
3727
1edf84e7
GV
3728 /* Force width and height of client area to be exact
3729 multiples of the character cell dimensions. */
3730 wdiff = (lppos->cx - (rect.right - rect.left)
3731 - 2 * internal_border - scrollbar_extra)
3732 % font_width;
3733 hdiff = (lppos->cy - (rect.bottom - rect.top)
3734 - 2 * internal_border)
3735 % line_height;
ee78dc32
GV
3736
3737 if (wdiff || hdiff)
3738 {
3739 /* For right/bottom sizing we can just fix the sizes.
3740 However for top/left sizing we will need to fix the X
3741 and Y positions as well. */
3742
3743 lppos->cx -= wdiff;
3744 lppos->cy -= hdiff;
3745
3746 if (wp.showCmd != SW_SHOWMAXIMIZED
1edf84e7 3747 && (lppos->flags & SWP_NOMOVE) == 0)
ee78dc32
GV
3748 {
3749 if (lppos->x != wr.left || lppos->y != wr.top)
3750 {
3751 lppos->x += wdiff;
3752 lppos->y += hdiff;
3753 }
3754 else
3755 {
3756 lppos->flags |= SWP_NOMOVE;
3757 }
3758 }
3759
1edf84e7 3760 return 0;
ee78dc32
GV
3761 }
3762 }
3763 }
ee78dc32
GV
3764
3765 goto dflt;
1edf84e7
GV
3766
3767 case WM_EMACS_CREATESCROLLBAR:
3768 return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
3769 (struct scroll_bar *) lParam);
3770
5ac45f98 3771 case WM_EMACS_SHOWWINDOW:
1edf84e7
GV
3772 return ShowWindow ((HWND) wParam, (WPARAM) lParam);
3773
5ac45f98
GV
3774 case WM_EMACS_SETWINDOWPOS:
3775 {
1edf84e7
GV
3776 WINDOWPOS * pos = (WINDOWPOS *) wParam;
3777 return SetWindowPos (hwnd, pos->hwndInsertAfter,
5ac45f98
GV
3778 pos->x, pos->y, pos->cx, pos->cy, pos->flags);
3779 }
1edf84e7 3780
ee78dc32 3781 case WM_EMACS_DESTROYWINDOW:
1edf84e7
GV
3782 return DestroyWindow ((HWND) wParam);
3783
3784 case WM_EMACS_TRACKPOPUPMENU:
3785 {
3786 UINT flags;
3787 POINT *pos;
3788 int retval;
3789 pos = (POINT *)lParam;
3790 flags = TPM_CENTERALIGN;
3791 if (button_state & LMOUSE)
3792 flags |= TPM_LEFTBUTTON;
3793 else if (button_state & RMOUSE)
3794 flags |= TPM_RIGHTBUTTON;
3795
3796 /* Use menubar_active to indicate that WM_INITMENU is from
3797 TrackPopupMenu below, and should be ignored. */
3798 f = x_window_to_frame (dpyinfo, hwnd);
3799 if (f)
3800 f->output_data.w32->menubar_active = 1;
3801
3802 if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
3803 0, hwnd, NULL))
3804 {
3805 MSG amsg;
3806 /* Eat any mouse messages during popupmenu */
3807 while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
3808 PM_REMOVE));
3809 /* Get the menu selection, if any */
3810 if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE))
3811 {
3812 retval = LOWORD (amsg.wParam);
3813 }
3814 else
3815 {
3816 retval = 0;
3817 }
3818 button_state = 0;
3819
3820 /* Remember we did a SetCapture on the initial mouse down
3821 event, but window focus will usually have changed to the
3822 popup menu before we released the mouse button. For
3823 safety, we make sure the capture is cancelled now. */
3824 ReleaseCapture ();
3825 }
3826 else
3827 {
3828 retval = -1;
3829 }
3830
3831 return retval;
3832 }
3833
ee78dc32
GV
3834 default:
3835 dflt:
3836 return DefWindowProc (hwnd, msg, wParam, lParam);
3837 }
3838
1edf84e7
GV
3839
3840 /* The most common default return code for handled messages is 0. */
3841 return 0;
ee78dc32
GV
3842}
3843
3844void
3845my_create_window (f)
3846 struct frame * f;
3847{
3848 MSG msg;
3849
1edf84e7
GV
3850 if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
3851 abort ();
ee78dc32
GV
3852 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
3853}
3854
fbd6baed 3855/* Create and set up the w32 window for frame F. */
ee78dc32
GV
3856
3857static void
fbd6baed 3858w32_window (f, window_prompting, minibuffer_only)
ee78dc32
GV
3859 struct frame *f;
3860 long window_prompting;
3861 int minibuffer_only;
3862{
3863 BLOCK_INPUT;
3864
3865 /* Use the resource name as the top-level window name
3866 for looking up resources. Make a non-Lisp copy
3867 for the window manager, so GC relocation won't bother it.
3868
3869 Elsewhere we specify the window name for the window manager. */
3870
3871 {
3872 char *str = (char *) XSTRING (Vx_resource_name)->data;
3873 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3874 strcpy (f->namebuf, str);
3875 }
3876
3877 my_create_window (f);
3878
3879 validate_x_resource_name ();
3880
3881 /* x_set_name normally ignores requests to set the name if the
3882 requested name is the same as the current name. This is the one
3883 place where that assumption isn't correct; f->name is set, but
3884 the server hasn't been told. */
3885 {
3886 Lisp_Object name;
3887 int explicit = f->explicit_name;
3888
3889 f->explicit_name = 0;
3890 name = f->name;
3891 f->name = Qnil;
3892 x_set_name (f, name, explicit);
3893 }
3894
3895 UNBLOCK_INPUT;
3896
3897 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3898 initialize_frame_menubar (f);
3899
fbd6baed 3900 if (FRAME_W32_WINDOW (f) == 0)
ee78dc32
GV
3901 error ("Unable to create window");
3902}
3903
3904/* Handle the icon stuff for this window. Perhaps later we might
3905 want an x_set_icon_position which can be called interactively as
3906 well. */
3907
3908static void
3909x_icon (f, parms)
3910 struct frame *f;
3911 Lisp_Object parms;
3912{
3913 Lisp_Object icon_x, icon_y;
3914
e9e23e23 3915 /* Set the position of the icon. Note that Windows 95 groups all
ee78dc32
GV
3916 icons in the tray. */
3917 icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
3918 icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
3919 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3920 {
3921 CHECK_NUMBER (icon_x, 0);
3922 CHECK_NUMBER (icon_y, 0);
3923 }
3924 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3925 error ("Both left and top icon corners of icon must be specified");
3926
3927 BLOCK_INPUT;
3928
3929 if (! EQ (icon_x, Qunbound))
3930 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3931
1edf84e7
GV
3932#if 0 /* TODO */
3933 /* Start up iconic or window? */
3934 x_wm_set_window_state
3935 (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
3936 ? IconicState
3937 : NormalState));
3938
3939 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3940 ? f->icon_name
3941 : f->name))->data);
3942#endif
3943
ee78dc32
GV
3944 UNBLOCK_INPUT;
3945}
3946
3947DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3948 1, 1, 0,
3949 "Make a new window, which is called a \"frame\" in Emacs terms.\n\
3950Returns an Emacs frame object.\n\
3951ALIST is an alist of frame parameters.\n\
3952If the parameters specify that the frame should not have a minibuffer,\n\
3953and do not specify a specific minibuffer window to use,\n\
3954then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3955be shared by the new frame.\n\
3956\n\
3957This function is an internal primitive--use `make-frame' instead.")
3958 (parms)
3959 Lisp_Object parms;
3960{
3961 struct frame *f;
3962 Lisp_Object frame, tem;
3963 Lisp_Object name;
3964 int minibuffer_only = 0;
3965 long window_prompting = 0;
3966 int width, height;
3967 int count = specpdl_ptr - specpdl;
1edf84e7 3968 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
ee78dc32 3969 Lisp_Object display;
fbd6baed 3970 struct w32_display_info *dpyinfo;
ee78dc32
GV
3971 Lisp_Object parent;
3972 struct kboard *kb;
3973
3974 /* Use this general default value to start with
3975 until we know if this frame has a specified name. */
3976 Vx_resource_name = Vinvocation_name;
3977
3978 display = x_get_arg (parms, Qdisplay, 0, 0, string);
3979 if (EQ (display, Qunbound))
3980 display = Qnil;
3981 dpyinfo = check_x_display_info (display);
3982#ifdef MULTI_KBOARD
3983 kb = dpyinfo->kboard;
3984#else
3985 kb = &the_only_kboard;
3986#endif
3987
1edf84e7 3988 name = x_get_arg (parms, Qname, "name", "Name", string);
ee78dc32
GV
3989 if (!STRINGP (name)
3990 && ! EQ (name, Qunbound)
3991 && ! NILP (name))
3992 error ("Invalid frame name--not a string or nil");
3993
3994 if (STRINGP (name))
3995 Vx_resource_name = name;
3996
3997 /* See if parent window is specified. */
3998 parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
3999 if (EQ (parent, Qunbound))
4000 parent = Qnil;
4001 if (! NILP (parent))
4002 CHECK_NUMBER (parent, 0);
4003
1edf84e7
GV
4004 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4005 /* No need to protect DISPLAY because that's not used after passing
4006 it to make_frame_without_minibuffer. */
4007 frame = Qnil;
4008 GCPRO4 (parms, parent, name, frame);
ee78dc32
GV
4009 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
4010 if (EQ (tem, Qnone) || NILP (tem))
4011 f = make_frame_without_minibuffer (Qnil, kb, display);
4012 else if (EQ (tem, Qonly))
4013 {
4014 f = make_minibuffer_frame ();
4015 minibuffer_only = 1;
4016 }
4017 else if (WINDOWP (tem))
4018 f = make_frame_without_minibuffer (tem, kb, display);
4019 else
4020 f = make_frame (1);
4021
1edf84e7
GV
4022 XSETFRAME (frame, f);
4023
ee78dc32
GV
4024 /* Note that Windows does support scroll bars. */
4025 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
5ac45f98
GV
4026 /* By default, make scrollbars the system standard width. */
4027 f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL);
ee78dc32 4028
fbd6baed
GV
4029 f->output_method = output_w32;
4030 f->output_data.w32 = (struct w32_output *) xmalloc (sizeof (struct w32_output));
4031 bzero (f->output_data.w32, sizeof (struct w32_output));
ee78dc32 4032
1edf84e7
GV
4033 f->icon_name
4034 = x_get_arg (parms, Qicon_name, "iconName", "Title", string);
4035 if (! STRINGP (f->icon_name))
4036 f->icon_name = Qnil;
4037
fbd6baed 4038/* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
ee78dc32
GV
4039#ifdef MULTI_KBOARD
4040 FRAME_KBOARD (f) = kb;
4041#endif
4042
4043 /* Specify the parent under which to make this window. */
4044
4045 if (!NILP (parent))
4046 {
fbd6baed
GV
4047 f->output_data.w32->parent_desc = (Window) parent;
4048 f->output_data.w32->explicit_parent = 1;
ee78dc32
GV
4049 }
4050 else
4051 {
fbd6baed
GV
4052 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
4053 f->output_data.w32->explicit_parent = 0;
ee78dc32
GV
4054 }
4055
4056 /* Note that the frame has no physical cursor right now. */
4057 f->phys_cursor_x = -1;
4058
4059 /* Set the name; the functions to which we pass f expect the name to
4060 be set. */
4061 if (EQ (name, Qunbound) || NILP (name))
4062 {
fbd6baed 4063 f->name = build_string (dpyinfo->w32_id_name);
ee78dc32
GV
4064 f->explicit_name = 0;
4065 }
4066 else
4067 {
4068 f->name = name;
4069 f->explicit_name = 1;
4070 /* use the frame's title when getting resources for this frame. */
4071 specbind (Qx_resource_name, name);
4072 }
4073
4074 /* Extract the window parameters from the supplied values
4075 that are needed to determine window geometry. */
4076 {
4077 Lisp_Object font;
4078
4079 font = x_get_arg (parms, Qfont, "font", "Font", string);
4080 BLOCK_INPUT;
4081 /* First, try whatever font the caller has specified. */
4082 if (STRINGP (font))
4083 font = x_new_font (f, XSTRING (font)->data);
ee78dc32
GV
4084 /* Try out a font which we hope has bold and italic variations. */
4085 if (!STRINGP (font))
1edf84e7 4086 font = x_new_font (f, "-*-Courier New-normal-r-*-*-13-97-*-*-c-*-*-ansi-");
ee78dc32 4087 if (! STRINGP (font))
1edf84e7 4088 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-97-*-*-c-*-*-ansi-");
ee78dc32
GV
4089 /* If those didn't work, look for something which will at least work. */
4090 if (! STRINGP (font))
1edf84e7 4091 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-13-97-*-*-c-*-*-ansi-");
ee78dc32
GV
4092 UNBLOCK_INPUT;
4093 if (! STRINGP (font))
1edf84e7 4094 font = build_string ("Fixedsys");
ee78dc32
GV
4095
4096 x_default_parameter (f, parms, Qfont, font,
4097 "font", "Font", string);
4098 }
4099
4100 x_default_parameter (f, parms, Qborder_width, make_number (2),
4101 "borderwidth", "BorderWidth", number);
4102 /* This defaults to 2 in order to match xterm. We recognize either
4103 internalBorderWidth or internalBorder (which is what xterm calls
4104 it). */
4105 if (NILP (Fassq (Qinternal_border_width, parms)))
4106 {
4107 Lisp_Object value;
4108
4109 value = x_get_arg (parms, Qinternal_border_width,
4110 "internalBorder", "BorderWidth", number);
4111 if (! EQ (value, Qunbound))
4112 parms = Fcons (Fcons (Qinternal_border_width, value),
4113 parms);
4114 }
1edf84e7 4115 /* Default internalBorderWidth to 0 on Windows to match other programs. */
ee78dc32
GV
4116 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
4117 "internalBorderWidth", "BorderWidth", number);
4118 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
4119 "verticalScrollBars", "ScrollBars", boolean);
4120
4121 /* Also do the stuff which must be set before the window exists. */
4122 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4123 "foreground", "Foreground", string);
4124 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4125 "background", "Background", string);
4126 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4127 "pointerColor", "Foreground", string);
4128 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4129 "cursorColor", "Foreground", string);
4130 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4131 "borderColor", "BorderColor", string);
4132
4133 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4134 "menuBar", "MenuBar", number);
4135 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4136 "scrollBarWidth", "ScrollBarWidth", number);
1edf84e7
GV
4137 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4138 "bufferPredicate", "BufferPredicate", symbol);
4139 x_default_parameter (f, parms, Qtitle, Qnil,
4140 "title", "Title", string);
ee78dc32 4141
fbd6baed
GV
4142 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
4143 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
ee78dc32
GV
4144 window_prompting = x_figure_window_size (f, parms);
4145
4146 if (window_prompting & XNegative)
4147 {
4148 if (window_prompting & YNegative)
fbd6baed 4149 f->output_data.w32->win_gravity = SouthEastGravity;
ee78dc32 4150 else
fbd6baed 4151 f->output_data.w32->win_gravity = NorthEastGravity;
ee78dc32
GV
4152 }
4153 else
4154 {
4155 if (window_prompting & YNegative)
fbd6baed 4156 f->output_data.w32->win_gravity = SouthWestGravity;
ee78dc32 4157 else
fbd6baed 4158 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
4159 }
4160
fbd6baed 4161 f->output_data.w32->size_hint_flags = window_prompting;
ee78dc32 4162
fbd6baed 4163 w32_window (f, window_prompting, minibuffer_only);
ee78dc32
GV
4164 x_icon (f, parms);
4165 init_frame_faces (f);
4166
4167 /* We need to do this after creating the window, so that the
4168 icon-creation functions can say whose icon they're describing. */
4169 x_default_parameter (f, parms, Qicon_type, Qnil,
4170 "bitmapIcon", "BitmapIcon", symbol);
4171
4172 x_default_parameter (f, parms, Qauto_raise, Qnil,
4173 "autoRaise", "AutoRaiseLower", boolean);
4174 x_default_parameter (f, parms, Qauto_lower, Qnil,
4175 "autoLower", "AutoRaiseLower", boolean);
4176 x_default_parameter (f, parms, Qcursor_type, Qbox,
4177 "cursorType", "CursorType", symbol);
4178
4179 /* Dimensions, especially f->height, must be done via change_frame_size.
4180 Change will not be effected unless different from the current
4181 f->height. */
4182 width = f->width;
4183 height = f->height;
1026b400
RS
4184 f->height = 0;
4185 SET_FRAME_WIDTH (f, 0);
ee78dc32
GV
4186 change_frame_size (f, height, width, 1, 0);
4187
4188 /* Tell the server what size and position, etc, we want,
4189 and how badly we want them. */
4190 BLOCK_INPUT;
4191 x_wm_set_size_hint (f, window_prompting, 0);
4192 UNBLOCK_INPUT;
4193
4194 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
4195 f->no_split = minibuffer_only || EQ (tem, Qt);
4196
4197 UNGCPRO;
4198
4199 /* It is now ok to make the frame official
4200 even if we get an error below.
4201 And the frame needs to be on Vframe_list
4202 or making it visible won't work. */
4203 Vframe_list = Fcons (frame, Vframe_list);
4204
4205 /* Now that the frame is official, it counts as a reference to
4206 its display. */
fbd6baed 4207 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
ee78dc32
GV
4208
4209 /* Make the window appear on the frame and enable display,
4210 unless the caller says not to. However, with explicit parent,
4211 Emacs cannot control visibility, so don't try. */
fbd6baed 4212 if (! f->output_data.w32->explicit_parent)
ee78dc32
GV
4213 {
4214 Lisp_Object visibility;
4215
4216 visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
4217 if (EQ (visibility, Qunbound))
4218 visibility = Qt;
4219
4220 if (EQ (visibility, Qicon))
4221 x_iconify_frame (f);
4222 else if (! NILP (visibility))
4223 x_make_frame_visible (f);
4224 else
4225 /* Must have been Qnil. */
4226 ;
4227 }
4228
4229 return unbind_to (count, frame);
4230}
4231
4232/* FRAME is used only to get a handle on the X display. We don't pass the
4233 display info directly because we're called from frame.c, which doesn't
4234 know about that structure. */
4235Lisp_Object
4236x_get_focus_frame (frame)
4237 struct frame *frame;
4238{
fbd6baed 4239 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
ee78dc32 4240 Lisp_Object xfocus;
fbd6baed 4241 if (! dpyinfo->w32_focus_frame)
ee78dc32
GV
4242 return Qnil;
4243
fbd6baed 4244 XSETFRAME (xfocus, dpyinfo->w32_focus_frame);
ee78dc32
GV
4245 return xfocus;
4246}
1edf84e7
GV
4247
4248DEFUN ("w32-focus-frame", Fw32_focus_frame, Sw32_focus_frame, 1, 1, 0,
4249 "Give FRAME input focus, raising to foreground if necessary.")
4250 (frame)
4251 Lisp_Object frame;
4252{
4253 x_focus_on_frame (check_x_frame (frame));
4254 return Qnil;
4255}
4256
ee78dc32 4257\f
5ac45f98 4258XFontStruct *
fbd6baed
GV
4259w32_load_font (dpyinfo,name)
4260struct w32_display_info *dpyinfo;
3c190163 4261char * name;
ee78dc32
GV
4262{
4263 XFontStruct * font = NULL;
4264 BOOL ok;
5ac45f98 4265
3c190163
GV
4266 {
4267 LOGFONT lf;
5ac45f98 4268
fbd6baed 4269 if (!name || !x_to_w32_font (name, &lf))
3c190163 4270 return (NULL);
5ac45f98 4271
3c190163 4272 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
5ac45f98 4273
3c190163 4274 if (!font) return (NULL);
5ac45f98 4275
3c190163 4276 BLOCK_INPUT;
5ac45f98
GV
4277
4278 font->hfont = CreateFontIndirect (&lf);
ee78dc32 4279 }
ee78dc32 4280
5ac45f98
GV
4281 if (font->hfont == NULL)
4282 {
4283 ok = FALSE;
4284 }
4285 else
4286 {
4287 HDC hdc;
4288 HANDLE oldobj;
4289
4290 hdc = GetDC (dpyinfo->root_window);
4291 oldobj = SelectObject (hdc, font->hfont);
4292 ok = GetTextMetrics (hdc, &font->tm);
4293 SelectObject (hdc, oldobj);
4294 ReleaseDC (dpyinfo->root_window, hdc);
4295 }
4296
ee78dc32 4297 UNBLOCK_INPUT;
5ac45f98 4298
ee78dc32 4299 if (ok) return (font);
5ac45f98 4300
fbd6baed 4301 w32_unload_font (dpyinfo, font);
ee78dc32
GV
4302 return (NULL);
4303}
4304
4305void
fbd6baed
GV
4306w32_unload_font (dpyinfo, font)
4307 struct w32_display_info *dpyinfo;
ee78dc32
GV
4308 XFontStruct * font;
4309{
4310 if (font)
4311 {
3c190163 4312 if (font->hfont) DeleteObject(font->hfont);
ee78dc32
GV
4313 xfree (font);
4314 }
4315}
4316
fbd6baed 4317/* The font conversion stuff between x and w32 */
ee78dc32
GV
4318
4319/* X font string is as follows (from faces.el)
4320 * (let ((- "[-?]")
4321 * (foundry "[^-]+")
4322 * (family "[^-]+")
4323 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
4324 * (weight\? "\\([^-]*\\)") ; 1
4325 * (slant "\\([ior]\\)") ; 2
4326 * (slant\? "\\([^-]?\\)") ; 2
4327 * (swidth "\\([^-]*\\)") ; 3
4328 * (adstyle "[^-]*") ; 4
4329 * (pixelsize "[0-9]+")
4330 * (pointsize "[0-9][0-9]+")
4331 * (resx "[0-9][0-9]+")
4332 * (resy "[0-9][0-9]+")
4333 * (spacing "[cmp?*]")
4334 * (avgwidth "[0-9]+")
4335 * (registry "[^-]+")
4336 * (encoding "[^-]+")
4337 * )
4338 * (setq x-font-regexp
4339 * (concat "\\`\\*?[-?*]"
4340 * foundry - family - weight\? - slant\? - swidth - adstyle -
4341 * pixelsize - pointsize - resx - resy - spacing - registry -
4342 * encoding "[-?*]\\*?\\'"
4343 * ))
4344 * (setq x-font-regexp-head
4345 * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
4346 * "\\([-*?]\\|\\'\\)"))
4347 * (setq x-font-regexp-slant (concat - slant -))
4348 * (setq x-font-regexp-weight (concat - weight -))
4349 * nil)
4350 */
4351
4352#define FONT_START "[-?]"
4353#define FONT_FOUNDRY "[^-]+"
4354#define FONT_FAMILY "\\([^-]+\\)" /* 1 */
4355#define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
4356#define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
4357#define FONT_SLANT "\\([ior]\\)" /* 3 */
4358#define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
4359#define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
4360#define FONT_ADSTYLE "[^-]*"
4361#define FONT_PIXELSIZE "[^-]*"
4362#define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
4363#define FONT_RESX "[0-9][0-9]+"
4364#define FONT_RESY "[0-9][0-9]+"
4365#define FONT_SPACING "[cmp?*]"
4366#define FONT_AVGWIDTH "[0-9]+"
4367#define FONT_REGISTRY "[^-]+"
4368#define FONT_ENCODING "[^-]+"
4369
4370#define FONT_REGEXP ("\\`\\*?[-?*]" \
4371 FONT_FOUNDRY "-" \
4372 FONT_FAMILY "-" \
4373 FONT_WEIGHT_Q "-" \
4374 FONT_SLANT_Q "-" \
4375 FONT_SWIDTH "-" \
4376 FONT_ADSTYLE "-" \
4377 FONT_PIXELSIZE "-" \
4378 FONT_POINTSIZE "-" \
4379 "[-?*]\\|\\'")
4380
4381#define FONT_REGEXP_HEAD ("\\`[-?*]" \
4382 FONT_FOUNDRY "-" \
4383 FONT_FAMILY "-" \
4384 FONT_WEIGHT_Q "-" \
4385 FONT_SLANT_Q \
4386 "\\([-*?]\\|\\'\\)")
4387
4388#define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
4389#define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
4390
4391LONG
fbd6baed 4392x_to_w32_weight (lpw)
ee78dc32
GV
4393 char * lpw;
4394{
4395 if (!lpw) return (FW_DONTCARE);
5ac45f98
GV
4396
4397 if (stricmp (lpw,"heavy") == 0) return FW_HEAVY;
4398 else if (stricmp (lpw,"extrabold") == 0) return FW_EXTRABOLD;
4399 else if (stricmp (lpw,"bold") == 0) return FW_BOLD;
4400 else if (stricmp (lpw,"demibold") == 0) return FW_SEMIBOLD;
1edf84e7 4401 else if (stricmp (lpw,"semibold") == 0) return FW_SEMIBOLD;
5ac45f98
GV
4402 else if (stricmp (lpw,"medium") == 0) return FW_MEDIUM;
4403 else if (stricmp (lpw,"normal") == 0) return FW_NORMAL;
4404 else if (stricmp (lpw,"light") == 0) return FW_LIGHT;
4405 else if (stricmp (lpw,"extralight") == 0) return FW_EXTRALIGHT;
4406 else if (stricmp (lpw,"thin") == 0) return FW_THIN;
ee78dc32 4407 else
5ac45f98 4408 return FW_DONTCARE;
ee78dc32
GV
4409}
4410
5ac45f98 4411
ee78dc32 4412char *
fbd6baed 4413w32_to_x_weight (fnweight)
ee78dc32
GV
4414 int fnweight;
4415{
5ac45f98
GV
4416 if (fnweight >= FW_HEAVY) return "heavy";
4417 if (fnweight >= FW_EXTRABOLD) return "extrabold";
4418 if (fnweight >= FW_BOLD) return "bold";
4419 if (fnweight >= FW_SEMIBOLD) return "semibold";
4420 if (fnweight >= FW_MEDIUM) return "medium";
4421 if (fnweight >= FW_NORMAL) return "normal";
4422 if (fnweight >= FW_LIGHT) return "light";
4423 if (fnweight >= FW_EXTRALIGHT) return "extralight";
4424 if (fnweight >= FW_THIN) return "thin";
4425 else
4426 return "*";
4427}
4428
4429LONG
fbd6baed 4430x_to_w32_charset (lpcs)
5ac45f98
GV
4431 char * lpcs;
4432{
4433 if (!lpcs) return (0);
4434
4435 if (stricmp (lpcs,"ansi") == 0) return ANSI_CHARSET;
4436 else if (stricmp (lpcs,"iso8859-1") == 0) return ANSI_CHARSET;
4437 else if (stricmp (lpcs,"iso8859") == 0) return ANSI_CHARSET;
4438 else if (stricmp (lpcs,"oem") == 0) return OEM_CHARSET;
4439#ifdef UNICODE_CHARSET
4440 else if (stricmp (lpcs,"unicode") == 0) return UNICODE_CHARSET;
4441 else if (stricmp (lpcs,"iso10646") == 0) return UNICODE_CHARSET;
4442#endif
1edf84e7 4443 else if (lpcs[0] == '#') return atoi (lpcs + 1);
5ac45f98 4444 else
1edf84e7 4445 return DEFAULT_CHARSET;
5ac45f98
GV
4446}
4447
4448char *
fbd6baed 4449w32_to_x_charset (fncharset)
5ac45f98
GV
4450 int fncharset;
4451{
1edf84e7
GV
4452 static char buf[16];
4453
5ac45f98
GV
4454 switch (fncharset)
4455 {
4456 case ANSI_CHARSET: return "ansi";
4457 case OEM_CHARSET: return "oem";
4458 case SYMBOL_CHARSET: return "symbol";
4459#ifdef UNICODE_CHARSET
4460 case UNICODE_CHARSET: return "unicode";
4461#endif
4462 }
1edf84e7
GV
4463 /* Encode numerical value of unknown charset. */
4464 sprintf (buf, "#%u", fncharset);
4465 return buf;
ee78dc32
GV
4466}
4467
4468BOOL
fbd6baed 4469w32_to_x_font (lplogfont, lpxstr, len)
ee78dc32
GV
4470 LOGFONT * lplogfont;
4471 char * lpxstr;
4472 int len;
4473{
3cb20f4a
RS
4474 char height_pixels[8];
4475 char height_dpi[8];
4476 char width_pixels[8];
4477
4478 if (!lpxstr) abort ();
ee78dc32 4479
3cb20f4a
RS
4480 if (!lplogfont)
4481 return FALSE;
4482
4483 if (lplogfont->lfHeight)
ee78dc32 4484 {
3cb20f4a
RS
4485 sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
4486 sprintf (height_dpi, "%u",
fbd6baed 4487 (abs (lplogfont->lfHeight) * 720) / one_w32_display_info.height_in);
5ac45f98
GV
4488 }
4489 else
ee78dc32 4490 {
3cb20f4a
RS
4491 strcpy (height_pixels, "*");
4492 strcpy (height_dpi, "*");
ee78dc32 4493 }
3cb20f4a
RS
4494 if (lplogfont->lfWidth)
4495 sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
4496 else
4497 strcpy (width_pixels, "*");
4498
4499 _snprintf (lpxstr, len - 1,
4500 "-*-%s-%s-%c-*-*-%s-%s-*-*-%c-%s-*-%s-",
4501 lplogfont->lfFaceName,
fbd6baed 4502 w32_to_x_weight (lplogfont->lfWeight),
3cb20f4a
RS
4503 lplogfont->lfItalic?'i':'r',
4504 height_pixels,
4505 height_dpi,
4506 ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH) ? 'p' : 'c',
4507 width_pixels,
fbd6baed 4508 w32_to_x_charset (lplogfont->lfCharSet)
3cb20f4a
RS
4509 );
4510
ee78dc32
GV
4511 lpxstr[len - 1] = 0; /* just to be sure */
4512 return (TRUE);
4513}
4514
4515BOOL
fbd6baed 4516x_to_w32_font (lpxstr, lplogfont)
ee78dc32
GV
4517 char * lpxstr;
4518 LOGFONT * lplogfont;
4519{
4520 if (!lplogfont) return (FALSE);
4521
4522 memset (lplogfont, 0, sizeof (*lplogfont));
5ac45f98 4523
771c47d5 4524#if 1
ee78dc32
GV
4525 lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
4526 lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
4527 lplogfont->lfQuality = DEFAULT_QUALITY;
5ac45f98
GV
4528#else
4529 /* go for maximum quality */
4530 lplogfont->lfOutPrecision = OUT_STROKE_PRECIS;
4531 lplogfont->lfClipPrecision = CLIP_STROKE_PRECIS;
4532 lplogfont->lfQuality = PROOF_QUALITY;
4533#endif
4534
4535 if (!lpxstr)
4536 return FALSE;
4537
4538 /* Provide a simple escape mechanism for specifying Windows font names
4539 * directly -- if font spec does not beginning with '-', assume this
4540 * format:
4541 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
4542 */
ee78dc32 4543
5ac45f98
GV
4544 if (*lpxstr == '-')
4545 {
4546 int fields;
4547 char name[50], weight[20], slant, pitch, pixels[10], height[10], width[10], remainder[20];
4548 char * encoding;
4549
4550 fields = sscanf (lpxstr,
4551 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%*[^-]-%c-%9[^-]-%19s",
4552 name, weight, &slant, pixels, height, &pitch, width, remainder);
4553
4554 if (fields == EOF) return (FALSE);
4555
4556 if (fields > 0 && name[0] != '*')
4557 {
4558 strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
4559 lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
4560 }
4561 else
4562 {
4563 lplogfont->lfFaceName[0] = 0;
4564 }
4565
4566 fields--;
4567
fbd6baed 4568 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
5ac45f98
GV
4569
4570 fields--;
4571
fbd6baed 4572 if (!NILP (Vw32_enable_italics))
5ac45f98
GV
4573 lplogfont->lfItalic = (fields > 0 && slant == 'i');
4574
4575 fields--;
4576
4577 if (fields > 0 && pixels[0] != '*')
4578 lplogfont->lfHeight = atoi (pixels);
4579
4580 fields--;
4581
4582 if (fields > 0 && lplogfont->lfHeight == 0 && height[0] != '*')
4583 lplogfont->lfHeight = (atoi (height)
fbd6baed 4584 * one_w32_display_info.height_in) / 720;
5ac45f98
GV
4585
4586 fields--;
4587
4588 lplogfont->lfPitchAndFamily =
4589 (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
4590
4591 fields--;
4592
4593 if (fields > 0 && width[0] != '*')
4594 lplogfont->lfWidth = atoi (width) / 10;
4595
4596 fields--;
4597
4598 /* Not all font specs include the registry field, so we allow for an
4599 optional registry field before the encoding when parsing
4600 remainder. Also we strip the trailing '-' if present. */
3c190163 4601 {
5ac45f98
GV
4602 int len = strlen (remainder);
4603 if (len > 0 && remainder[len-1] == '-')
4604 remainder[len-1] = 0;
ee78dc32 4605 }
5ac45f98
GV
4606 encoding = remainder;
4607 if (strncmp (encoding, "*-", 2) == 0)
4608 encoding += 2;
fbd6baed 4609 lplogfont->lfCharSet = x_to_w32_charset (fields > 0 ? encoding : "");
5ac45f98
GV
4610 }
4611 else
4612 {
4613 int fields;
4614 char name[100], height[10], width[10], weight[20];
a1a80b40 4615
5ac45f98
GV
4616 fields = sscanf (lpxstr,
4617 "%99[^:]:%9[^:]:%9[^:]:%19s",
4618 name, height, width, weight);
4619
4620 if (fields == EOF) return (FALSE);
4621
4622 if (fields > 0)
4623 {
4624 strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
4625 lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
4626 }
4627 else
4628 {
4629 lplogfont->lfFaceName[0] = 0;
4630 }
4631
4632 fields--;
4633
4634 if (fields > 0)
4635 lplogfont->lfHeight = atoi (height);
4636
4637 fields--;
4638
4639 if (fields > 0)
4640 lplogfont->lfWidth = atoi (width);
4641
4642 fields--;
4643
fbd6baed 4644 lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
5ac45f98
GV
4645 }
4646
4647 /* This makes TrueType fonts work better. */
4648 lplogfont->lfHeight = - abs (lplogfont->lfHeight);
ee78dc32
GV
4649
4650 return (TRUE);
4651}
4652
4653BOOL
fbd6baed 4654w32_font_match (lpszfont1, lpszfont2)
ee78dc32
GV
4655 char * lpszfont1;
4656 char * lpszfont2;
4657{
4658 char * s1 = lpszfont1, *e1;
4659 char * s2 = lpszfont2, *e2;
4660
4661 if (s1 == NULL || s2 == NULL) return (FALSE);
4662
4663 if (*s1 == '-') s1++;
4664 if (*s2 == '-') s2++;
4665
4666 while (1)
4667 {
4668 int len1, len2;
4669
4670 e1 = strchr (s1, '-');
4671 e2 = strchr (s2, '-');
4672
4673 if (e1 == NULL || e2 == NULL) return (TRUE);
4674
4675 len1 = e1 - s1;
4676 len2 = e2 - s2;
4677
4678 if (*s1 != '*' && *s2 != '*'
4679 && (len1 != len2 || strnicmp (s1, s2, len1) != 0))
4680 return (FALSE);
4681
4682 s1 = e1 + 1;
4683 s2 = e2 + 1;
4684 }
4685}
4686
4687typedef struct enumfont_t
4688{
4689 HDC hdc;
4690 int numFonts;
3cb20f4a 4691 LOGFONT logfont;
ee78dc32
GV
4692 XFontStruct *size_ref;
4693 Lisp_Object *pattern;
4694 Lisp_Object *head;
4695 Lisp_Object *tail;
4696} enumfont_t;
4697
4698int CALLBACK
4699enum_font_cb2 (lplf, lptm, FontType, lpef)
4700 ENUMLOGFONT * lplf;
4701 NEWTEXTMETRIC * lptm;
4702 int FontType;
4703 enumfont_t * lpef;
4704{
1edf84e7 4705 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline)
ee78dc32
GV
4706 return (1);
4707
4708 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */
4709 {
4710 char buf[100];
4711
3cb20f4a
RS
4712 if (!NILP (*(lpef->pattern)) && FontType == TRUETYPE_FONTTYPE)
4713 {
4714 lplf->elfLogFont.lfHeight = lpef->logfont.lfHeight;
4715 lplf->elfLogFont.lfWidth = lpef->logfont.lfWidth;
4716 }
4717
fbd6baed 4718 if (!w32_to_x_font (lplf, buf, 100)) return (0);
ee78dc32 4719
fbd6baed 4720 if (NILP (*(lpef->pattern)) || w32_font_match (buf, XSTRING (*(lpef->pattern))->data))
ee78dc32
GV
4721 {
4722 *lpef->tail = Fcons (build_string (buf), Qnil);
4723 lpef->tail = &XCONS (*lpef->tail)->cdr;
4724 lpef->numFonts++;
4725 }
4726 }
4727
4728 return (1);
4729}
4730
4731int CALLBACK
4732enum_font_cb1 (lplf, lptm, FontType, lpef)
4733 ENUMLOGFONT * lplf;
4734 NEWTEXTMETRIC * lptm;
4735 int FontType;
4736 enumfont_t * lpef;
4737{
4738 return EnumFontFamilies (lpef->hdc,
4739 lplf->elfLogFont.lfFaceName,
4740 (FONTENUMPROC) enum_font_cb2,
4741 (LPARAM) lpef);
4742}
4743
4744
4745DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 3, 0,
4746 "Return a list of the names of available fonts matching PATTERN.\n\
4747If optional arguments FACE and FRAME are specified, return only fonts\n\
4748the same size as FACE on FRAME.\n\
4749\n\
4750PATTERN is a string, perhaps with wildcard characters;\n\
4751 the * character matches any substring, and\n\
4752 the ? character matches any single character.\n\
4753 PATTERN is case-insensitive.\n\
4754FACE is a face name--a symbol.\n\
4755\n\
4756The return value is a list of strings, suitable as arguments to\n\
4757set-face-font.\n\
4758\n\
4759Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
4760even if they match PATTERN and FACE.")
4761 (pattern, face, frame)
4762 Lisp_Object pattern, face, frame;
4763{
4764 int num_fonts;
4765 char **names;
4766 XFontStruct *info;
4767 XFontStruct *size_ref;
4768 Lisp_Object namelist;
4769 Lisp_Object list;
4770 FRAME_PTR f;
4771 enumfont_t ef;
4772
4773 CHECK_STRING (pattern, 0);
4774 if (!NILP (face))
4775 CHECK_SYMBOL (face, 1);
4776
4777 f = check_x_frame (frame);
4778
4779 /* Determine the width standard for comparison with the fonts we find. */
4780
4781 if (NILP (face))
4782 size_ref = 0;
4783 else
4784 {
4785 int face_id;
4786
4787 /* Don't die if we get called with a terminal frame. */
fbd6baed
GV
4788 if (! FRAME_W32_P (f))
4789 error ("non-w32 frame used in `x-list-fonts'");
ee78dc32
GV
4790
4791 face_id = face_name_id_number (f, face);
4792
4793 if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
4794 || FRAME_PARAM_FACES (f) [face_id] == 0)
fbd6baed 4795 size_ref = f->output_data.w32->font;
ee78dc32
GV
4796 else
4797 {
4798 size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
4799 if (size_ref == (XFontStruct *) (~0))
fbd6baed 4800 size_ref = f->output_data.w32->font;
ee78dc32
GV
4801 }
4802 }
4803
4804 /* See if we cached the result for this particular query. */
4805 list = Fassoc (pattern,
fbd6baed 4806 XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->cdr);
ee78dc32
GV
4807
4808 /* We have info in the cache for this PATTERN. */
4809 if (!NILP (list))
4810 {
4811 Lisp_Object tem, newlist;
4812
4813 /* We have info about this pattern. */
4814 list = XCONS (list)->cdr;
4815
4816 if (size_ref == 0)
4817 return list;
4818
4819 BLOCK_INPUT;
4820
4821 /* Filter the cached info and return just the fonts that match FACE. */
4822 newlist = Qnil;
4823 for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
4824 {
4825 XFontStruct *thisinfo;
4826
fbd6baed 4827 thisinfo = w32_load_font (FRAME_W32_DISPLAY_INFO (f), XSTRING (XCONS (tem)->car)->data);
ee78dc32
GV
4828
4829 if (thisinfo && same_size_fonts (thisinfo, size_ref))
4830 newlist = Fcons (XCONS (tem)->car, newlist);
4831
fbd6baed 4832 w32_unload_font (FRAME_W32_DISPLAY_INFO (f), thisinfo);
ee78dc32
GV
4833 }
4834
4835 UNBLOCK_INPUT;
4836
4837 return newlist;
4838 }
4839
4840 BLOCK_INPUT;
4841
4842 namelist = Qnil;
4843 ef.pattern = &pattern;
4844 ef.tail = ef.head = &namelist;
4845 ef.numFonts = 0;
fbd6baed 4846 x_to_w32_font (STRINGP (pattern) ? XSTRING (pattern)->data : NULL, &ef.logfont);
ee78dc32
GV
4847
4848 {
fbd6baed 4849 ef.hdc = GetDC (FRAME_W32_WINDOW (f));
ee78dc32
GV
4850
4851 EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1, (LPARAM)&ef);
4852
fbd6baed 4853 ReleaseDC (FRAME_W32_WINDOW (f), ef.hdc);
ee78dc32
GV
4854 }
4855
4856 UNBLOCK_INPUT;
4857
4858 if (ef.numFonts)
4859 {
4860 int i;
4861 Lisp_Object cur;
4862
4863 /* Make a list of all the fonts we got back.
4864 Store that in the font cache for the display. */
fbd6baed 4865 XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->cdr
ee78dc32 4866 = Fcons (Fcons (pattern, namelist),
fbd6baed 4867 XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->cdr);
ee78dc32
GV
4868
4869 /* Make a list of the fonts that have the right width. */
4870 list = Qnil;
4871 cur=namelist;
4872 for (i = 0; i < ef.numFonts; i++)
4873 {
4874 int keeper;
4875
4876 if (!size_ref)
4877 keeper = 1;
4878 else
4879 {
4880 XFontStruct *thisinfo;
4881
4882 BLOCK_INPUT;
fbd6baed 4883 thisinfo = w32_load_font (FRAME_W32_DISPLAY_INFO (f), XSTRING (Fcar (cur))->data);
ee78dc32
GV
4884
4885 keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
4886
fbd6baed 4887 w32_unload_font (FRAME_W32_DISPLAY_INFO (f), thisinfo);
ee78dc32
GV
4888
4889 UNBLOCK_INPUT;
4890 }
4891 if (keeper)
4892 list = Fcons (build_string (XSTRING (Fcar (cur))->data), list);
4893
4894 cur = Fcdr (cur);
4895 }
4896 list = Fnreverse (list);
4897 }
4898
4899 return list;
4900}
4901\f
4902DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
4903 "Return non-nil if color COLOR is supported on frame FRAME.\n\
4904If FRAME is omitted or nil, use the selected frame.")
4905 (color, frame)
4906 Lisp_Object color, frame;
4907{
4908 COLORREF foo;
4909 FRAME_PTR f = check_x_frame (frame);
4910
4911 CHECK_STRING (color, 1);
4912
4913 if (defined_color (f, XSTRING (color)->data, &foo, 0))
4914 return Qt;
4915 else
4916 return Qnil;
4917}
4918
4919DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
4920 "Return a description of the color named COLOR on frame FRAME.\n\
4921The value is a list of integer RGB values--(RED GREEN BLUE).\n\
4922These values appear to range from 0 to 65280 or 65535, depending\n\
4923on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
4924If FRAME is omitted or nil, use the selected frame.")
4925 (color, frame)
4926 Lisp_Object color, frame;
4927{
4928 COLORREF foo;
4929 FRAME_PTR f = check_x_frame (frame);
4930
4931 CHECK_STRING (color, 1);
4932
4933 if (defined_color (f, XSTRING (color)->data, &foo, 0))
4934 {
4935 Lisp_Object rgb[3];
4936
1edf84e7
GV
4937 rgb[0] = make_number ((GetRValue (foo) << 8) | GetRValue (foo));
4938 rgb[1] = make_number ((GetGValue (foo) << 8) | GetGValue (foo));
4939 rgb[2] = make_number ((GetBValue (foo) << 8) | GetBValue (foo));
ee78dc32
GV
4940 return Flist (3, rgb);
4941 }
4942 else
4943 return Qnil;
4944}
4945
4946DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
4947 "Return t if the X display supports color.\n\
4948The optional argument DISPLAY specifies which display to ask about.\n\
4949DISPLAY should be either a frame or a display name (a string).\n\
4950If omitted or nil, that stands for the selected frame's display.")
4951 (display)
4952 Lisp_Object display;
4953{
fbd6baed 4954 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
4955
4956 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
4957 return Qnil;
4958
4959 return Qt;
4960}
4961
4962DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4963 0, 1, 0,
4964 "Return t if the X display supports shades of gray.\n\
4965Note that color displays do support shades of gray.\n\
4966The optional argument DISPLAY specifies which display to ask about.\n\
4967DISPLAY should be either a frame or a display name (a string).\n\
4968If omitted or nil, that stands for the selected frame's display.")
4969 (display)
4970 Lisp_Object display;
4971{
fbd6baed 4972 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
4973
4974 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
4975 return Qnil;
4976
4977 return Qt;
4978}
4979
4980DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4981 0, 1, 0,
4982 "Returns the width in pixels of the X display DISPLAY.\n\
4983The optional argument DISPLAY specifies which display to ask about.\n\
4984DISPLAY should be either a frame or a display name (a string).\n\
4985If omitted or nil, that stands for the selected frame's display.")
4986 (display)
4987 Lisp_Object display;
4988{
fbd6baed 4989 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
4990
4991 return make_number (dpyinfo->width);
4992}
4993
4994DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4995 Sx_display_pixel_height, 0, 1, 0,
4996 "Returns the height in pixels of the X display DISPLAY.\n\
4997The optional argument DISPLAY specifies which display to ask about.\n\
4998DISPLAY should be either a frame or a display name (a string).\n\
4999If omitted or nil, that stands for the selected frame's display.")
5000 (display)
5001 Lisp_Object display;
5002{
fbd6baed 5003 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5004
5005 return make_number (dpyinfo->height);
5006}
5007
5008DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
5009 0, 1, 0,
5010 "Returns the number of bitplanes of the display DISPLAY.\n\
5011The optional argument DISPLAY specifies which display to ask about.\n\
5012DISPLAY should be either a frame or a display name (a string).\n\
5013If omitted or nil, that stands for the selected frame's display.")
5014 (display)
5015 Lisp_Object display;
5016{
fbd6baed 5017 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5018
5019 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
5020}
5021
5022DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
5023 0, 1, 0,
5024 "Returns the number of color cells of the display DISPLAY.\n\
5025The optional argument DISPLAY specifies which display to ask about.\n\
5026DISPLAY should be either a frame or a display name (a string).\n\
5027If omitted or nil, that stands for the selected frame's display.")
5028 (display)
5029 Lisp_Object display;
5030{
fbd6baed 5031 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5032 HDC hdc;
5033 int cap;
5034
5ac45f98
GV
5035 hdc = GetDC (dpyinfo->root_window);
5036 if (dpyinfo->has_palette)
5037 cap = GetDeviceCaps (hdc,SIZEPALETTE);
5038 else
5039 cap = GetDeviceCaps (hdc,NUMCOLORS);
ee78dc32
GV
5040
5041 ReleaseDC (dpyinfo->root_window, hdc);
5042
5043 return make_number (cap);
5044}
5045
5046DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
5047 Sx_server_max_request_size,
5048 0, 1, 0,
5049 "Returns the maximum request size of the server of display DISPLAY.\n\
5050The optional argument DISPLAY specifies which display to ask about.\n\
5051DISPLAY should be either a frame or a display name (a string).\n\
5052If omitted or nil, that stands for the selected frame's display.")
5053 (display)
5054 Lisp_Object display;
5055{
fbd6baed 5056 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5057
5058 return make_number (1);
5059}
5060
5061DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
fbd6baed 5062 "Returns the vendor ID string of the W32 system (Microsoft).\n\
ee78dc32
GV
5063The optional argument DISPLAY specifies which display to ask about.\n\
5064DISPLAY should be either a frame or a display name (a string).\n\
5065If omitted or nil, that stands for the selected frame's display.")
5066 (display)
5067 Lisp_Object display;
5068{
fbd6baed 5069 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5070 char *vendor = "Microsoft Corp.";
5071
5072 if (! vendor) vendor = "";
5073 return build_string (vendor);
5074}
5075
5076DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
5077 "Returns the version numbers of the server of display DISPLAY.\n\
5078The value is a list of three integers: the major and minor\n\
5079version numbers, and the vendor-specific release\n\
5080number. See also the function `x-server-vendor'.\n\n\
5081The optional argument DISPLAY specifies which display to ask about.\n\
5082DISPLAY should be either a frame or a display name (a string).\n\
5083If omitted or nil, that stands for the selected frame's display.")
5084 (display)
5085 Lisp_Object display;
5086{
fbd6baed 5087 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32 5088
fbd6baed
GV
5089 return Fcons (make_number (w32_major_version),
5090 Fcons (make_number (w32_minor_version), Qnil));
ee78dc32
GV
5091}
5092
5093DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
5094 "Returns the number of screens on the server of display DISPLAY.\n\
5095The optional argument DISPLAY specifies which display to ask about.\n\
5096DISPLAY should be either a frame or a display name (a string).\n\
5097If omitted or nil, that stands for the selected frame's display.")
5098 (display)
5099 Lisp_Object display;
5100{
fbd6baed 5101 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5102
5103 return make_number (1);
5104}
5105
5106DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
5107 "Returns the height in millimeters of the X display DISPLAY.\n\
5108The optional argument DISPLAY specifies which display to ask about.\n\
5109DISPLAY should be either a frame or a display name (a string).\n\
5110If omitted or nil, that stands for the selected frame's display.")
5111 (display)
5112 Lisp_Object display;
5113{
fbd6baed 5114 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5115 HDC hdc;
5116 int cap;
5117
5ac45f98 5118 hdc = GetDC (dpyinfo->root_window);
3c190163 5119
ee78dc32 5120 cap = GetDeviceCaps (hdc, VERTSIZE);
3c190163 5121
ee78dc32
GV
5122 ReleaseDC (dpyinfo->root_window, hdc);
5123
5124 return make_number (cap);
5125}
5126
5127DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
5128 "Returns the width in millimeters of the X display DISPLAY.\n\
5129The optional argument DISPLAY specifies which display to ask about.\n\
5130DISPLAY should be either a frame or a display name (a string).\n\
5131If omitted or nil, that stands for the selected frame's display.")
5132 (display)
5133 Lisp_Object display;
5134{
fbd6baed 5135 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5136
5137 HDC hdc;
5138 int cap;
5139
5ac45f98 5140 hdc = GetDC (dpyinfo->root_window);
3c190163 5141
ee78dc32 5142 cap = GetDeviceCaps (hdc, HORZSIZE);
3c190163 5143
ee78dc32
GV
5144 ReleaseDC (dpyinfo->root_window, hdc);
5145
5146 return make_number (cap);
5147}
5148
5149DEFUN ("x-display-backing-store", Fx_display_backing_store,
5150 Sx_display_backing_store, 0, 1, 0,
5151 "Returns an indication of whether display DISPLAY does backing store.\n\
5152The value may be `always', `when-mapped', or `not-useful'.\n\
5153The optional argument DISPLAY specifies which display to ask about.\n\
5154DISPLAY should be either a frame or a display name (a string).\n\
5155If omitted or nil, that stands for the selected frame's display.")
5156 (display)
5157 Lisp_Object display;
5158{
5159 return intern ("not-useful");
5160}
5161
5162DEFUN ("x-display-visual-class", Fx_display_visual_class,
5163 Sx_display_visual_class, 0, 1, 0,
5164 "Returns the visual class of the display DISPLAY.\n\
5165The value is one of the symbols `static-gray', `gray-scale',\n\
5166`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
5167The optional argument DISPLAY specifies which display to ask about.\n\
5168DISPLAY should be either a frame or a display name (a string).\n\
5169If omitted or nil, that stands for the selected frame's display.")
5170 (display)
5171 Lisp_Object display;
5172{
fbd6baed 5173 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5174
5175#if 0
5176 switch (dpyinfo->visual->class)
5177 {
5178 case StaticGray: return (intern ("static-gray"));
5179 case GrayScale: return (intern ("gray-scale"));
5180 case StaticColor: return (intern ("static-color"));
5181 case PseudoColor: return (intern ("pseudo-color"));
5182 case TrueColor: return (intern ("true-color"));
5183 case DirectColor: return (intern ("direct-color"));
5184 default:
5185 error ("Display has an unknown visual class");
5186 }
5187#endif
5188
5189 error ("Display has an unknown visual class");
5190}
5191
5192DEFUN ("x-display-save-under", Fx_display_save_under,
5193 Sx_display_save_under, 0, 1, 0,
5194 "Returns t if the display DISPLAY supports the save-under feature.\n\
5195The optional argument DISPLAY specifies which display to ask about.\n\
5196DISPLAY should be either a frame or a display name (a string).\n\
5197If omitted or nil, that stands for the selected frame's display.")
5198 (display)
5199 Lisp_Object display;
5200{
fbd6baed 5201 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5202
5203 return Qnil;
5204}
5205\f
5206int
5207x_pixel_width (f)
5208 register struct frame *f;
5209{
5210 return PIXEL_WIDTH (f);
5211}
5212
5213int
5214x_pixel_height (f)
5215 register struct frame *f;
5216{
5217 return PIXEL_HEIGHT (f);
5218}
5219
5220int
5221x_char_width (f)
5222 register struct frame *f;
5223{
fbd6baed 5224 return FONT_WIDTH (f->output_data.w32->font);
ee78dc32
GV
5225}
5226
5227int
5228x_char_height (f)
5229 register struct frame *f;
5230{
fbd6baed 5231 return f->output_data.w32->line_height;
ee78dc32
GV
5232}
5233
5234int
5235x_screen_planes (frame)
5236 Lisp_Object frame;
5237{
fbd6baed
GV
5238 return (FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes *
5239 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits);
ee78dc32
GV
5240}
5241\f
5242/* Return the display structure for the display named NAME.
5243 Open a new connection if necessary. */
5244
fbd6baed 5245struct w32_display_info *
ee78dc32
GV
5246x_display_info_for_name (name)
5247 Lisp_Object name;
5248{
5249 Lisp_Object names;
fbd6baed 5250 struct w32_display_info *dpyinfo;
ee78dc32
GV
5251
5252 CHECK_STRING (name, 0);
5253
fbd6baed 5254 for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
ee78dc32
GV
5255 dpyinfo;
5256 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
5257 {
5258 Lisp_Object tem;
5259 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
5260 if (!NILP (tem))
5261 return dpyinfo;
5262 }
5263
5264 /* Use this general default value to start with. */
5265 Vx_resource_name = Vinvocation_name;
5266
5267 validate_x_resource_name ();
5268
fbd6baed 5269 dpyinfo = w32_term_init (name, (unsigned char *)0,
ee78dc32
GV
5270 (char *) XSTRING (Vx_resource_name)->data);
5271
5272 if (dpyinfo == 0)
5273 error ("Cannot connect to server %s", XSTRING (name)->data);
5274
1edf84e7 5275 w32_in_use = 1;
ee78dc32
GV
5276 XSETFASTINT (Vwindow_system_version, 3);
5277
5278 return dpyinfo;
5279}
5280
5281DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5282 1, 3, 0, "Open a connection to a server.\n\
5283DISPLAY is the name of the display to connect to.\n\
5284Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5285If the optional third arg MUST-SUCCEED is non-nil,\n\
5286terminate Emacs if we can't open the connection.")
5287 (display, xrm_string, must_succeed)
5288 Lisp_Object display, xrm_string, must_succeed;
5289{
5290 unsigned int n_planes;
5291 unsigned char *xrm_option;
fbd6baed 5292 struct w32_display_info *dpyinfo;
ee78dc32
GV
5293
5294 CHECK_STRING (display, 0);
5295 if (! NILP (xrm_string))
5296 CHECK_STRING (xrm_string, 1);
5297
1edf84e7
GV
5298 if (! EQ (Vwindow_system, intern ("w32")))
5299 error ("Not using Microsoft Windows");
5300
5ac45f98
GV
5301 /* Allow color mapping to be defined externally; first look in user's
5302 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
5303 {
5304 Lisp_Object color_file;
5305 struct gcpro gcpro1;
5306
5307 color_file = build_string("~/rgb.txt");
5308
5309 GCPRO1 (color_file);
5310
5311 if (NILP (Ffile_readable_p (color_file)))
5312 color_file =
5313 Fexpand_file_name (build_string ("rgb.txt"),
5314 Fsymbol_value (intern ("data-directory")));
5315
fbd6baed 5316 Vw32_color_map = Fw32_load_color_file (color_file);
5ac45f98
GV
5317
5318 UNGCPRO;
5319 }
fbd6baed
GV
5320 if (NILP (Vw32_color_map))
5321 Vw32_color_map = Fw32_default_color_map ();
ee78dc32
GV
5322
5323 if (! NILP (xrm_string))
5324 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5325 else
5326 xrm_option = (unsigned char *) 0;
5327
5328 /* Use this general default value to start with. */
5ac45f98
GV
5329 /* First remove .exe suffix from invocation-name - it looks ugly. */
5330 {
5331 char basename[ MAX_PATH ], *str;
5332
5333 strcpy (basename, XSTRING (Vinvocation_name)->data);
5334 str = strrchr (basename, '.');
5335 if (str) *str = 0;
5336 Vinvocation_name = build_string (basename);
5337 }
ee78dc32
GV
5338 Vx_resource_name = Vinvocation_name;
5339
5340 validate_x_resource_name ();
5341
5342 /* This is what opens the connection and sets x_current_display.
5343 This also initializes many symbols, such as those used for input. */
fbd6baed 5344 dpyinfo = w32_term_init (display, xrm_option,
ee78dc32
GV
5345 (char *) XSTRING (Vx_resource_name)->data);
5346
5347 if (dpyinfo == 0)
5348 {
5349 if (!NILP (must_succeed))
3c190163
GV
5350 fatal ("Cannot connect to server %s.\n",
5351 XSTRING (display)->data);
ee78dc32
GV
5352 else
5353 error ("Cannot connect to server %s", XSTRING (display)->data);
5354 }
5355
1edf84e7
GV
5356 w32_in_use = 1;
5357
ee78dc32
GV
5358 XSETFASTINT (Vwindow_system_version, 3);
5359 return Qnil;
5360}
5361
5362DEFUN ("x-close-connection", Fx_close_connection,
5363 Sx_close_connection, 1, 1, 0,
5364 "Close the connection to DISPLAY's server.\n\
5365For DISPLAY, specify either a frame or a display name (a string).\n\
5366If DISPLAY is nil, that stands for the selected frame's display.")
5367 (display)
5368 Lisp_Object display;
5369{
fbd6baed
GV
5370 struct w32_display_info *dpyinfo = check_x_display_info (display);
5371 struct w32_display_info *tail;
ee78dc32
GV
5372 int i;
5373
5374 if (dpyinfo->reference_count > 0)
5375 error ("Display still has frames on it");
5376
5377 BLOCK_INPUT;
5378 /* Free the fonts in the font table. */
5379 for (i = 0; i < dpyinfo->n_fonts; i++)
5380 {
5381 if (dpyinfo->font_table[i].name)
5382 free (dpyinfo->font_table[i].name);
5383 /* Don't free the full_name string;
5384 it is always shared with something else. */
fbd6baed 5385 w32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
ee78dc32
GV
5386 }
5387 x_destroy_all_bitmaps (dpyinfo);
5388
5389 x_delete_display (dpyinfo);
5390 UNBLOCK_INPUT;
5391
5392 return Qnil;
5393}
5394
5395DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5396 "Return the list of display names that Emacs has connections to.")
5397 ()
5398{
5399 Lisp_Object tail, result;
5400
5401 result = Qnil;
fbd6baed 5402 for (tail = w32_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
ee78dc32
GV
5403 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
5404
5405 return result;
5406}
5407
5408DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5409 "If ON is non-nil, report errors as soon as the erring request is made.\n\
5410If ON is nil, allow buffering of requests.\n\
fbd6baed 5411This is a noop on W32 systems.\n\
ee78dc32
GV
5412The optional second argument DISPLAY specifies which display to act on.\n\
5413DISPLAY should be either a frame or a display name (a string).\n\
5414If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5415 (on, display)
5416 Lisp_Object display, on;
5417{
fbd6baed 5418 struct w32_display_info *dpyinfo = check_x_display_info (display);
ee78dc32
GV
5419
5420 return Qnil;
5421}
5422
5423\f
fbd6baed 5424/* These are the w32 specialized functions */
ee78dc32 5425
fbd6baed
GV
5426DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 1, 0,
5427 "This will display the W32 font dialog and return an X font string corresponding to the selection.")
ee78dc32
GV
5428 (frame)
5429 Lisp_Object frame;
5430{
5431 FRAME_PTR f = check_x_frame (frame);
5432 CHOOSEFONT cf;
5433 LOGFONT lf;
5434 char buf[100];
5435
5436 bzero (&cf, sizeof (cf));
5437
5438 cf.lStructSize = sizeof (cf);
fbd6baed 5439 cf.hwndOwner = FRAME_W32_WINDOW (f);
ee78dc32
GV
5440 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST | CF_SCREENFONTS;
5441 cf.lpLogFont = &lf;
5442
fbd6baed 5443 if (!ChooseFont (&cf) || !w32_to_x_font (&lf, buf, 100))
3c190163 5444 return Qnil;
ee78dc32
GV
5445
5446 return build_string (buf);
5447}
5448
1edf84e7
GV
5449DEFUN ("w32-send-sys-command", Fw32_send_sys_command, Sw32_send_sys_command, 1, 2, 0,
5450 "Send frame a Windows WM_SYSCOMMAND message of type COMMAND.\n\
5451Some useful values for command are 0xf030 to maximise frame (0xf020\n\
5452to minimize), 0xf120 to restore frame to original size, and 0xf100\n\
5453to activate the menubar for keyboard access. 0xf140 activates the\n\
5454screen saver if defined.\n\
5455\n\
5456If optional parameter FRAME is not specified, use selected frame.")
5457 (command, frame)
5458 Lisp_Object command, frame;
5459{
5460 WPARAM code;
5461 FRAME_PTR f = check_x_frame (frame);
5462
5463 CHECK_NUMBER (command, 0);
5464
5465 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
5466
5467 return Qnil;
5468}
5469
ee78dc32 5470\f
fbd6baed 5471syms_of_w32fns ()
ee78dc32 5472{
1edf84e7
GV
5473 /* This is zero if not using MS-Windows. */
5474 w32_in_use = 0;
5475
ee78dc32
GV
5476 /* The section below is built by the lisp expression at the top of the file,
5477 just above where these variables are declared. */
5478 /*&&& init symbols here &&&*/
5479 Qauto_raise = intern ("auto-raise");
5480 staticpro (&Qauto_raise);
5481 Qauto_lower = intern ("auto-lower");
5482 staticpro (&Qauto_lower);
5483 Qbackground_color = intern ("background-color");
5484 staticpro (&Qbackground_color);
5485 Qbar = intern ("bar");
5486 staticpro (&Qbar);
5487 Qborder_color = intern ("border-color");
5488 staticpro (&Qborder_color);
5489 Qborder_width = intern ("border-width");
5490 staticpro (&Qborder_width);
5491 Qbox = intern ("box");
5492 staticpro (&Qbox);
5493 Qcursor_color = intern ("cursor-color");
5494 staticpro (&Qcursor_color);
5495 Qcursor_type = intern ("cursor-type");
5496 staticpro (&Qcursor_type);
ee78dc32
GV
5497 Qforeground_color = intern ("foreground-color");
5498 staticpro (&Qforeground_color);
5499 Qgeometry = intern ("geometry");
5500 staticpro (&Qgeometry);
5501 Qicon_left = intern ("icon-left");
5502 staticpro (&Qicon_left);
5503 Qicon_top = intern ("icon-top");
5504 staticpro (&Qicon_top);
5505 Qicon_type = intern ("icon-type");
5506 staticpro (&Qicon_type);
5507 Qicon_name = intern ("icon-name");
5508 staticpro (&Qicon_name);
5509 Qinternal_border_width = intern ("internal-border-width");
5510 staticpro (&Qinternal_border_width);
5511 Qleft = intern ("left");
5512 staticpro (&Qleft);
1026b400
RS
5513 Qright = intern ("right");
5514 staticpro (&Qright);
ee78dc32
GV
5515 Qmouse_color = intern ("mouse-color");
5516 staticpro (&Qmouse_color);
5517 Qnone = intern ("none");
5518 staticpro (&Qnone);
5519 Qparent_id = intern ("parent-id");
5520 staticpro (&Qparent_id);
5521 Qscroll_bar_width = intern ("scroll-bar-width");
5522 staticpro (&Qscroll_bar_width);
5523 Qsuppress_icon = intern ("suppress-icon");
5524 staticpro (&Qsuppress_icon);
5525 Qtop = intern ("top");
5526 staticpro (&Qtop);
5527 Qundefined_color = intern ("undefined-color");
5528 staticpro (&Qundefined_color);
5529 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
5530 staticpro (&Qvertical_scroll_bars);
5531 Qvisibility = intern ("visibility");
5532 staticpro (&Qvisibility);
5533 Qwindow_id = intern ("window-id");
5534 staticpro (&Qwindow_id);
5535 Qx_frame_parameter = intern ("x-frame-parameter");
5536 staticpro (&Qx_frame_parameter);
5537 Qx_resource_name = intern ("x-resource-name");
5538 staticpro (&Qx_resource_name);
5539 Quser_position = intern ("user-position");
5540 staticpro (&Quser_position);
5541 Quser_size = intern ("user-size");
5542 staticpro (&Quser_size);
5543 Qdisplay = intern ("display");
5544 staticpro (&Qdisplay);
5545 /* This is the end of symbol initialization. */
5546
5547 Fput (Qundefined_color, Qerror_conditions,
5548 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
5549 Fput (Qundefined_color, Qerror_message,
5550 build_string ("Undefined color"));
5551
fbd6baed 5552 DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
ee78dc32 5553 "A array of color name mappings for windows.");
fbd6baed 5554 Vw32_color_map = Qnil;
ee78dc32 5555
fbd6baed 5556 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
da36a4d6
GV
5557 "Non-nil if alt key presses are passed on to Windows.\n\
5558When non-nil, for example, alt pressed and released and then space will\n\
5559open the System menu. When nil, Emacs silently swallows alt key events.");
fbd6baed 5560 Vw32_pass_alt_to_system = Qnil;
da36a4d6 5561
fbd6baed 5562 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
8c205c63
RS
5563 "Non-nil if the alt key is to be considered the same as the meta key.\n\
5564When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
fbd6baed 5565 Vw32_alt_is_meta = Qt;
8c205c63 5566
fbd6baed
GV
5567 DEFVAR_LISP ("w32-pass-optional-keys-to-system",
5568 &Vw32_pass_optional_keys_to_system,
da36a4d6
GV
5569 "Non-nil if the 'optional' keys (left window, right window,\n\
5570and application keys) are passed on to Windows.");
fbd6baed 5571 Vw32_pass_optional_keys_to_system = Qnil;
da36a4d6 5572
fbd6baed 5573 DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics,
5ac45f98 5574 "Non-nil enables selection of artificially italicized fonts.");
fbd6baed 5575 Vw32_enable_italics = Qnil;
5ac45f98 5576
fbd6baed 5577 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette,
5ac45f98 5578 "Non-nil enables Windows palette management to map colors exactly.");
fbd6baed 5579 Vw32_enable_palette = Qt;
5ac45f98 5580
fbd6baed
GV
5581 DEFVAR_INT ("w32-mouse-button-tolerance",
5582 &Vw32_mouse_button_tolerance,
5ac45f98
GV
5583 "Analogue of double click interval for faking middle mouse events.\n\
5584The value is the minimum time in milliseconds that must elapse between\n\
5585left/right button down events before they are considered distinct events.\n\
5586If both mouse buttons are depressed within this interval, a middle mouse\n\
5587button down event is generated instead.");
fbd6baed 5588 XSETINT (Vw32_mouse_button_tolerance, GetDoubleClickTime () / 2);
5ac45f98 5589
fbd6baed
GV
5590 DEFVAR_INT ("w32-mouse-move-interval",
5591 &Vw32_mouse_move_interval,
84fb1139
KH
5592 "Minimum interval between mouse move events.\n\
5593The value is the minimum time in milliseconds that must elapse between\n\
5594successive mouse move (or scroll bar drag) events before they are\n\
5595reported as lisp events.");
fbd6baed 5596 XSETINT (Vw32_mouse_move_interval, 50);
84fb1139 5597
ee78dc32
GV
5598 init_x_parm_symbols ();
5599
5600 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
fbd6baed 5601 "List of directories to search for bitmap files for w32.");
ee78dc32
GV
5602 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
5603
5604 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
5605 "The shape of the pointer when over text.\n\
5606Changing the value does not affect existing frames\n\
5607unless you set the mouse color.");
5608 Vx_pointer_shape = Qnil;
5609
5610 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
5611 "The name Emacs uses to look up resources; for internal use only.\n\
5612`x-get-resource' uses this as the first component of the instance name\n\
5613when requesting resource values.\n\
5614Emacs initially sets `x-resource-name' to the name under which Emacs\n\
5615was invoked, or to the value specified with the `-name' or `-rn'\n\
5616switches, if present.");
5617 Vx_resource_name = Qnil;
5618
5619 Vx_nontext_pointer_shape = Qnil;
5620
5621 Vx_mode_pointer_shape = Qnil;
5622
5623 DEFVAR_INT ("x-sensitive-text-pointer-shape",
5624 &Vx_sensitive_text_pointer_shape,
5625 "The shape of the pointer when over mouse-sensitive text.\n\
5626This variable takes effect when you create a new frame\n\
5627or when you set the mouse color.");
5628 Vx_sensitive_text_pointer_shape = Qnil;
5629
5630 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
5631 "A string indicating the foreground color of the cursor box.");
5632 Vx_cursor_fore_pixel = Qnil;
5633
5634 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
5635 "Non-nil if no window manager is in use.\n\
5636Emacs doesn't try to figure this out; this is always nil\n\
5637unless you set it to something else.");
5638 /* We don't have any way to find this out, so set it to nil
5639 and maybe the user would like to set it to t. */
5640 Vx_no_window_manager = Qnil;
5641
5642 defsubr (&Sx_get_resource);
5643 defsubr (&Sx_list_fonts);
5644 defsubr (&Sx_display_color_p);
5645 defsubr (&Sx_display_grayscale_p);
5646 defsubr (&Sx_color_defined_p);
5647 defsubr (&Sx_color_values);
5648 defsubr (&Sx_server_max_request_size);
5649 defsubr (&Sx_server_vendor);
5650 defsubr (&Sx_server_version);
5651 defsubr (&Sx_display_pixel_width);
5652 defsubr (&Sx_display_pixel_height);
5653 defsubr (&Sx_display_mm_width);
5654 defsubr (&Sx_display_mm_height);
5655 defsubr (&Sx_display_screens);
5656 defsubr (&Sx_display_planes);
5657 defsubr (&Sx_display_color_cells);
5658 defsubr (&Sx_display_visual_class);
5659 defsubr (&Sx_display_backing_store);
5660 defsubr (&Sx_display_save_under);
5661 defsubr (&Sx_parse_geometry);
5662 defsubr (&Sx_create_frame);
ee78dc32
GV
5663 defsubr (&Sx_open_connection);
5664 defsubr (&Sx_close_connection);
5665 defsubr (&Sx_display_list);
5666 defsubr (&Sx_synchronize);
5667
fbd6baed 5668 /* W32 specific functions */
ee78dc32 5669
1edf84e7 5670 defsubr (&Sw32_focus_frame);
fbd6baed
GV
5671 defsubr (&Sw32_select_font);
5672 defsubr (&Sw32_define_rgb_color);
5673 defsubr (&Sw32_default_color_map);
5674 defsubr (&Sw32_load_color_file);
1edf84e7 5675 defsubr (&Sw32_send_sys_command);
ee78dc32
GV
5676}
5677
5678#undef abort
5679
5680void
fbd6baed 5681w32_abort()
ee78dc32 5682{
5ac45f98
GV
5683 int button;
5684 button = MessageBox (NULL,
5685 "A fatal error has occurred!\n\n"
5686 "Select Abort to exit, Retry to debug, Ignore to continue",
5687 "Emacs Abort Dialog",
5688 MB_ICONEXCLAMATION | MB_TASKMODAL
5689 | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
5690 switch (button)
5691 {
5692 case IDRETRY:
5693 DebugBreak ();
5694 break;
5695 case IDIGNORE:
5696 break;
5697 case IDABORT:
5698 default:
5699 abort ();
5700 break;
5701 }
ee78dc32 5702}
d573caac 5703