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