Update FSF's address in the preamble.
[bpt/emacs.git] / src / w32fns.c
1 /* Functions for the Win32 window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Added by Kevin Gallo */
22
23 #include <signal.h>
24 #include <config.h>
25 #include <stdio.h>
26
27 #include "lisp.h"
28 #include "w32term.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "buffer.h"
32 #include "dispextern.h"
33 #include "keyboard.h"
34 #include "blockinput.h"
35 #include "paths.h"
36 #include "ntheap.h"
37 #include "termhooks.h"
38
39 #include <commdlg.h>
40
41 extern void abort ();
42 extern void free_frame_menubar ();
43 extern struct scroll_bar *x_window_to_scroll_bar ();
44
45 /* The colormap for converting color names to RGB values */
46 Lisp_Object Vwin32_color_map;
47
48 /* The name we're using in resource queries. */
49 Lisp_Object Vx_resource_name;
50
51 /* Non nil if no window manager is in use. */
52 Lisp_Object Vx_no_window_manager;
53
54 /* The background and shape of the mouse pointer, and shape when not
55 over text or in the modeline. */
56 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
57 /* The shape when over mouse-sensitive text. */
58 Lisp_Object Vx_sensitive_text_pointer_shape;
59
60 /* Color of chars displayed in cursor box. */
61 Lisp_Object Vx_cursor_fore_pixel;
62
63 /* Search path for bitmap files. */
64 Lisp_Object Vx_bitmap_file_path;
65
66 /* Evaluate this expression to rebuild the section of syms_of_w32fns
67 that initializes and staticpros the symbols declared below. Note
68 that Emacs 18 has a bug that keeps C-x C-e from being able to
69 evaluate this expression.
70
71 (progn
72 ;; Accumulate a list of the symbols we want to initialize from the
73 ;; declarations at the top of the file.
74 (goto-char (point-min))
75 (search-forward "/\*&&& symbols declared here &&&*\/\n")
76 (let (symbol-list)
77 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
78 (setq symbol-list
79 (cons (buffer-substring (match-beginning 1) (match-end 1))
80 symbol-list))
81 (forward-line 1))
82 (setq symbol-list (nreverse symbol-list))
83 ;; Delete the section of syms_of_... where we initialize the symbols.
84 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
85 (let ((start (point)))
86 (while (looking-at "^ Q")
87 (forward-line 2))
88 (kill-region start (point)))
89 ;; Write a new symbol initialization section.
90 (while symbol-list
91 (insert (format " %s = intern (\"" (car symbol-list)))
92 (let ((start (point)))
93 (insert (substring (car symbol-list) 1))
94 (subst-char-in-region start (point) ?_ ?-))
95 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
96 (setq symbol-list (cdr symbol-list)))))
97
98 */
99
100 /*&&& symbols declared here &&&*/
101 Lisp_Object Qauto_raise;
102 Lisp_Object Qauto_lower;
103 Lisp_Object Qbackground_color;
104 Lisp_Object Qbar;
105 Lisp_Object Qborder_color;
106 Lisp_Object Qborder_width;
107 Lisp_Object Qbox;
108 Lisp_Object Qcursor_color;
109 Lisp_Object Qcursor_type;
110 Lisp_Object Qfont;
111 Lisp_Object Qforeground_color;
112 Lisp_Object Qgeometry;
113 Lisp_Object Qicon_left;
114 Lisp_Object Qicon_top;
115 Lisp_Object Qicon_type;
116 Lisp_Object Qicon_name;
117 Lisp_Object Qinternal_border_width;
118 Lisp_Object Qleft;
119 Lisp_Object Qmouse_color;
120 Lisp_Object Qnone;
121 Lisp_Object Qparent_id;
122 Lisp_Object Qscroll_bar_width;
123 Lisp_Object Qsuppress_icon;
124 Lisp_Object Qtop;
125 Lisp_Object Qundefined_color;
126 Lisp_Object Qvertical_scroll_bars;
127 Lisp_Object Qvisibility;
128 Lisp_Object Qwindow_id;
129 Lisp_Object Qx_frame_parameter;
130 Lisp_Object Qx_resource_name;
131 Lisp_Object Quser_position;
132 Lisp_Object Quser_size;
133 Lisp_Object Qdisplay;
134
135 /* The below are defined in frame.c. */
136 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
137 extern Lisp_Object Qunsplittable, Qmenu_bar_lines;
138
139 extern Lisp_Object Vwindow_system_version;
140
141 extern Lisp_Object last_mouse_scroll_bar;
142 extern int last_mouse_scroll_bar_pos;
143 Time last_mouse_movement_time;
144
145 \f
146 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
147 and checking validity for Win32. */
148
149 FRAME_PTR
150 check_x_frame (frame)
151 Lisp_Object frame;
152 {
153 FRAME_PTR f;
154
155 if (NILP (frame))
156 f = selected_frame;
157 else
158 {
159 CHECK_LIVE_FRAME (frame, 0);
160 f = XFRAME (frame);
161 }
162 if (! FRAME_WIN32_P (f))
163 error ("non-win32 frame used");
164 return f;
165 }
166
167 /* Let the user specify an display with a frame.
168 nil stands for the selected frame--or, if that is not a win32 frame,
169 the first display on the list. */
170
171 static struct win32_display_info *
172 check_x_display_info (frame)
173 Lisp_Object frame;
174 {
175 if (NILP (frame))
176 {
177 if (FRAME_WIN32_P (selected_frame))
178 return FRAME_WIN32_DISPLAY_INFO (selected_frame);
179 else
180 return &one_win32_display_info;
181 }
182 else if (STRINGP (frame))
183 return x_display_info_for_name (frame);
184 else
185 {
186 FRAME_PTR f;
187
188 CHECK_LIVE_FRAME (frame, 0);
189 f = XFRAME (frame);
190 if (! FRAME_WIN32_P (f))
191 error ("non-win32 frame used");
192 return FRAME_WIN32_DISPLAY_INFO (f);
193 }
194 }
195 \f
196 /* Return the Emacs frame-object corresponding to an win32 window.
197 It could be the frame's main window or an icon window. */
198
199 /* This function can be called during GC, so use GC_xxx type test macros. */
200
201 struct frame *
202 x_window_to_frame (dpyinfo, wdesc)
203 struct win32_display_info *dpyinfo;
204 HWND wdesc;
205 {
206 Lisp_Object tail, frame;
207 struct frame *f;
208
209 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
210 {
211 frame = XCONS (tail)->car;
212 if (!GC_FRAMEP (frame))
213 continue;
214 f = XFRAME (frame);
215 if (f->output_data.nothing == 1
216 || FRAME_WIN32_DISPLAY_INFO (f) != dpyinfo)
217 continue;
218 if (FRAME_WIN32_WINDOW (f) == wdesc)
219 return f;
220 }
221 return 0;
222 }
223
224 \f
225
226 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
227 id, which is just an int that this section returns. Bitmaps are
228 reference counted so they can be shared among frames.
229
230 Bitmap indices are guaranteed to be > 0, so a negative number can
231 be used to indicate no bitmap.
232
233 If you use x_create_bitmap_from_data, then you must keep track of
234 the bitmaps yourself. That is, creating a bitmap from the same
235 data more than once will not be caught. */
236
237
238 /* Functions to access the contents of a bitmap, given an id. */
239
240 int
241 x_bitmap_height (f, id)
242 FRAME_PTR f;
243 int id;
244 {
245 return FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
246 }
247
248 int
249 x_bitmap_width (f, id)
250 FRAME_PTR f;
251 int id;
252 {
253 return FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
254 }
255
256 int
257 x_bitmap_pixmap (f, id)
258 FRAME_PTR f;
259 int id;
260 {
261 return (int) FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
262 }
263
264
265 /* Allocate a new bitmap record. Returns index of new record. */
266
267 static int
268 x_allocate_bitmap_record (f)
269 FRAME_PTR f;
270 {
271 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
272 int i;
273
274 if (dpyinfo->bitmaps == NULL)
275 {
276 dpyinfo->bitmaps_size = 10;
277 dpyinfo->bitmaps
278 = (struct win32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct win32_bitmap_record));
279 dpyinfo->bitmaps_last = 1;
280 return 1;
281 }
282
283 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
284 return ++dpyinfo->bitmaps_last;
285
286 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
287 if (dpyinfo->bitmaps[i].refcount == 0)
288 return i + 1;
289
290 dpyinfo->bitmaps_size *= 2;
291 dpyinfo->bitmaps
292 = (struct win32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
293 dpyinfo->bitmaps_size * sizeof (struct win32_bitmap_record));
294 return ++dpyinfo->bitmaps_last;
295 }
296
297 /* Add one reference to the reference count of the bitmap with id ID. */
298
299 void
300 x_reference_bitmap (f, id)
301 FRAME_PTR f;
302 int id;
303 {
304 ++FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
305 }
306
307 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
308
309 int
310 x_create_bitmap_from_data (f, bits, width, height)
311 struct frame *f;
312 char *bits;
313 unsigned int width, height;
314 {
315 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
316 Pixmap bitmap;
317 int id;
318
319 bitmap = CreateBitmap (width, height,
320 FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_planes,
321 FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
322 bits);
323
324 if (! bitmap)
325 return -1;
326
327 id = x_allocate_bitmap_record (f);
328 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
329 dpyinfo->bitmaps[id - 1].file = NULL;
330 dpyinfo->bitmaps[id - 1].hinst = NULL;
331 dpyinfo->bitmaps[id - 1].refcount = 1;
332 dpyinfo->bitmaps[id - 1].depth = 1;
333 dpyinfo->bitmaps[id - 1].height = height;
334 dpyinfo->bitmaps[id - 1].width = width;
335
336 return id;
337 }
338
339 /* Create bitmap from file FILE for frame F. */
340
341 int
342 x_create_bitmap_from_file (f, file)
343 struct frame *f;
344 Lisp_Object file;
345 {
346 return -1;
347 #if 0
348 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
349 unsigned int width, height;
350 Pixmap bitmap;
351 int xhot, yhot, result, id;
352 Lisp_Object found;
353 int fd;
354 char *filename;
355 HINSTANCE hinst;
356
357 /* Look for an existing bitmap with the same name. */
358 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
359 {
360 if (dpyinfo->bitmaps[id].refcount
361 && dpyinfo->bitmaps[id].file
362 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
363 {
364 ++dpyinfo->bitmaps[id].refcount;
365 return id + 1;
366 }
367 }
368
369 /* Search bitmap-file-path for the file, if appropriate. */
370 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
371 if (fd < 0)
372 return -1;
373 close (fd);
374
375 filename = (char *) XSTRING (found)->data;
376
377 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
378
379 if (hinst == NULL)
380 return -1;
381
382
383 result = XReadBitmapFile (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f),
384 filename, &width, &height, &bitmap, &xhot, &yhot);
385 if (result != BitmapSuccess)
386 return -1;
387
388 id = x_allocate_bitmap_record (f);
389 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
390 dpyinfo->bitmaps[id - 1].refcount = 1;
391 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
392 dpyinfo->bitmaps[id - 1].depth = 1;
393 dpyinfo->bitmaps[id - 1].height = height;
394 dpyinfo->bitmaps[id - 1].width = width;
395 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
396
397 return id;
398 #endif
399 }
400
401 /* Remove reference to bitmap with id number ID. */
402
403 int
404 x_destroy_bitmap (f, id)
405 FRAME_PTR f;
406 int id;
407 {
408 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
409
410 if (id > 0)
411 {
412 --dpyinfo->bitmaps[id - 1].refcount;
413 if (dpyinfo->bitmaps[id - 1].refcount == 0)
414 {
415 BLOCK_INPUT;
416 DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
417 if (dpyinfo->bitmaps[id - 1].file)
418 {
419 free (dpyinfo->bitmaps[id - 1].file);
420 dpyinfo->bitmaps[id - 1].file = NULL;
421 }
422 UNBLOCK_INPUT;
423 }
424 }
425 }
426
427 /* Free all the bitmaps for the display specified by DPYINFO. */
428
429 static void
430 x_destroy_all_bitmaps (dpyinfo)
431 struct win32_display_info *dpyinfo;
432 {
433 int i;
434 for (i = 0; i < dpyinfo->bitmaps_last; i++)
435 if (dpyinfo->bitmaps[i].refcount > 0)
436 {
437 DeleteObject (dpyinfo->bitmaps[i].pixmap);
438 if (dpyinfo->bitmaps[i].file)
439 free (dpyinfo->bitmaps[i].file);
440 }
441 dpyinfo->bitmaps_last = 0;
442 }
443 \f
444 /* Connect the frame-parameter names for Win32 frames
445 to the ways of passing the parameter values to the window system.
446
447 The name of a parameter, as a Lisp symbol,
448 has an `x-frame-parameter' property which is an integer in Lisp
449 but can be interpreted as an `enum x_frame_parm' in C. */
450
451 enum x_frame_parm
452 {
453 X_PARM_FOREGROUND_COLOR,
454 X_PARM_BACKGROUND_COLOR,
455 X_PARM_MOUSE_COLOR,
456 X_PARM_CURSOR_COLOR,
457 X_PARM_BORDER_COLOR,
458 X_PARM_ICON_TYPE,
459 X_PARM_FONT,
460 X_PARM_BORDER_WIDTH,
461 X_PARM_INTERNAL_BORDER_WIDTH,
462 X_PARM_NAME,
463 X_PARM_AUTORAISE,
464 X_PARM_AUTOLOWER,
465 X_PARM_VERT_SCROLL_BAR,
466 X_PARM_VISIBILITY,
467 X_PARM_MENU_BAR_LINES
468 };
469
470
471 struct x_frame_parm_table
472 {
473 char *name;
474 void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
475 };
476
477 void x_set_foreground_color ();
478 void x_set_background_color ();
479 void x_set_mouse_color ();
480 void x_set_cursor_color ();
481 void x_set_border_color ();
482 void x_set_cursor_type ();
483 void x_set_icon_type ();
484 void x_set_icon_name ();
485 void x_set_font ();
486 void x_set_border_width ();
487 void x_set_internal_border_width ();
488 void x_explicitly_set_name ();
489 void x_set_autoraise ();
490 void x_set_autolower ();
491 void x_set_vertical_scroll_bars ();
492 void x_set_visibility ();
493 void x_set_menu_bar_lines ();
494 void x_set_scroll_bar_width ();
495 void x_set_unsplittable ();
496
497 static struct x_frame_parm_table x_frame_parms[] =
498 {
499 "foreground-color", x_set_foreground_color,
500 "background-color", x_set_background_color,
501 "mouse-color", x_set_mouse_color,
502 "cursor-color", x_set_cursor_color,
503 "border-color", x_set_border_color,
504 "cursor-type", x_set_cursor_type,
505 "icon-type", x_set_icon_type,
506 "icon-name", x_set_icon_name,
507 "font", x_set_font,
508 "border-width", x_set_border_width,
509 "internal-border-width", x_set_internal_border_width,
510 "name", x_explicitly_set_name,
511 "auto-raise", x_set_autoraise,
512 "auto-lower", x_set_autolower,
513 "vertical-scroll-bars", x_set_vertical_scroll_bars,
514 "visibility", x_set_visibility,
515 "menu-bar-lines", x_set_menu_bar_lines,
516 "scroll-bar-width", x_set_scroll_bar_width,
517 "unsplittable", x_set_unsplittable,
518 };
519
520 /* Attach the `x-frame-parameter' properties to
521 the Lisp symbol names of parameters relevant to Win32. */
522
523 init_x_parm_symbols ()
524 {
525 int i;
526
527 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
528 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
529 make_number (i));
530 }
531 \f
532 /* Change the parameters of FRAME as specified by ALIST.
533 If a parameter is not specially recognized, do nothing;
534 otherwise call the `x_set_...' function for that parameter. */
535
536 void
537 x_set_frame_parameters (f, alist)
538 FRAME_PTR f;
539 Lisp_Object alist;
540 {
541 Lisp_Object tail;
542
543 /* If both of these parameters are present, it's more efficient to
544 set them both at once. So we wait until we've looked at the
545 entire list before we set them. */
546 Lisp_Object width, height;
547
548 /* Same here. */
549 Lisp_Object left, top;
550
551 /* Same with these. */
552 Lisp_Object icon_left, icon_top;
553
554 /* Record in these vectors all the parms specified. */
555 Lisp_Object *parms;
556 Lisp_Object *values;
557 int i;
558 int left_no_change = 0, top_no_change = 0;
559 int icon_left_no_change = 0, icon_top_no_change = 0;
560
561 i = 0;
562 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
563 i++;
564
565 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
566 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
567
568 /* Extract parm names and values into those vectors. */
569
570 i = 0;
571 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
572 {
573 Lisp_Object elt, prop, val;
574
575 elt = Fcar (tail);
576 parms[i] = Fcar (elt);
577 values[i] = Fcdr (elt);
578 i++;
579 }
580
581 width = height = top = left = Qunbound;
582 icon_left = icon_top = Qunbound;
583
584 /* Now process them in reverse of specified order. */
585 for (i--; i >= 0; i--)
586 {
587 Lisp_Object prop, val;
588
589 prop = parms[i];
590 val = values[i];
591
592 if (EQ (prop, Qwidth))
593 width = val;
594 else if (EQ (prop, Qheight))
595 height = val;
596 else if (EQ (prop, Qtop))
597 top = val;
598 else if (EQ (prop, Qleft))
599 left = val;
600 else if (EQ (prop, Qicon_top))
601 icon_top = val;
602 else if (EQ (prop, Qicon_left))
603 icon_left = val;
604 else
605 {
606 register Lisp_Object param_index, old_value;
607
608 param_index = Fget (prop, Qx_frame_parameter);
609 old_value = get_frame_param (f, prop);
610 store_frame_param (f, prop, val);
611 if (NATNUMP (param_index)
612 && (XFASTINT (param_index)
613 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
614 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
615 }
616 }
617
618 /* Don't die if just one of these was set. */
619 if (EQ (left, Qunbound))
620 {
621 left_no_change = 1;
622 if (f->output_data.win32->left_pos < 0)
623 left = Fcons (Qplus, Fcons (make_number (f->output_data.win32->left_pos), Qnil));
624 else
625 XSETINT (left, f->output_data.win32->left_pos);
626 }
627 if (EQ (top, Qunbound))
628 {
629 top_no_change = 1;
630 if (f->output_data.win32->top_pos < 0)
631 top = Fcons (Qplus, Fcons (make_number (f->output_data.win32->top_pos), Qnil));
632 else
633 XSETINT (top, f->output_data.win32->top_pos);
634 }
635
636 /* If one of the icon positions was not set, preserve or default it. */
637 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
638 {
639 icon_left_no_change = 1;
640 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
641 if (NILP (icon_left))
642 XSETINT (icon_left, 0);
643 }
644 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
645 {
646 icon_top_no_change = 1;
647 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
648 if (NILP (icon_top))
649 XSETINT (icon_top, 0);
650 }
651
652 /* Don't die if just one of these was set. */
653 if (EQ (width, Qunbound))
654 XSETINT (width, FRAME_WIDTH (f));
655 if (EQ (height, Qunbound))
656 XSETINT (height, FRAME_HEIGHT (f));
657
658 /* Don't set these parameters unless they've been explicitly
659 specified. The window might be mapped or resized while we're in
660 this function, and we don't want to override that unless the lisp
661 code has asked for it.
662
663 Don't set these parameters unless they actually differ from the
664 window's current parameters; the window may not actually exist
665 yet. */
666 {
667 Lisp_Object frame;
668
669 check_frame_size (f, &height, &width);
670
671 XSETFRAME (frame, f);
672
673 if ((NUMBERP (width) && XINT (width) != FRAME_WIDTH (f))
674 || (NUMBERP (height) && XINT (height) != FRAME_HEIGHT (f)))
675 Fset_frame_size (frame, width, height);
676
677 if ((!NILP (left) || !NILP (top))
678 && ! (left_no_change && top_no_change)
679 && ! (NUMBERP (left) && XINT (left) == f->output_data.win32->left_pos
680 && NUMBERP (top) && XINT (top) == f->output_data.win32->top_pos))
681 {
682 int leftpos = 0;
683 int toppos = 0;
684
685 /* Record the signs. */
686 f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
687 if (EQ (left, Qminus))
688 f->output_data.win32->size_hint_flags |= XNegative;
689 else if (INTEGERP (left))
690 {
691 leftpos = XINT (left);
692 if (leftpos < 0)
693 f->output_data.win32->size_hint_flags |= XNegative;
694 }
695 else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
696 && CONSP (XCONS (left)->cdr)
697 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
698 {
699 leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
700 f->output_data.win32->size_hint_flags |= XNegative;
701 }
702 else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
703 && CONSP (XCONS (left)->cdr)
704 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
705 {
706 leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
707 }
708
709 if (EQ (top, Qminus))
710 f->output_data.win32->size_hint_flags |= YNegative;
711 else if (INTEGERP (top))
712 {
713 toppos = XINT (top);
714 if (toppos < 0)
715 f->output_data.win32->size_hint_flags |= YNegative;
716 }
717 else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
718 && CONSP (XCONS (top)->cdr)
719 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
720 {
721 toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
722 f->output_data.win32->size_hint_flags |= YNegative;
723 }
724 else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
725 && CONSP (XCONS (top)->cdr)
726 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
727 {
728 toppos = XINT (XCONS (XCONS (top)->cdr)->car);
729 }
730
731
732 /* Store the numeric value of the position. */
733 f->output_data.win32->top_pos = toppos;
734 f->output_data.win32->left_pos = leftpos;
735
736 f->output_data.win32->win_gravity = NorthWestGravity;
737
738 /* Actually set that position, and convert to absolute. */
739 x_set_offset (f, leftpos, toppos, -1);
740 }
741
742 if ((!NILP (icon_left) || !NILP (icon_top))
743 && ! (icon_left_no_change && icon_top_no_change))
744 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
745 }
746 }
747
748 /* Store the screen positions of frame F into XPTR and YPTR.
749 These are the positions of the containing window manager window,
750 not Emacs's own window. */
751
752 void
753 x_real_positions (f, xptr, yptr)
754 FRAME_PTR f;
755 int *xptr, *yptr;
756 {
757 POINT pt;
758
759 {
760 RECT rect;
761
762 GetClientRect(FRAME_WIN32_WINDOW(f), &rect);
763 AdjustWindowRect(&rect, f->output_data.win32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
764
765 pt.x = rect.left;
766 pt.y = rect.top;
767 }
768
769 ClientToScreen (FRAME_WIN32_WINDOW(f), &pt);
770
771 *xptr = pt.x;
772 *yptr = pt.y;
773 }
774
775 /* Insert a description of internally-recorded parameters of frame X
776 into the parameter alist *ALISTPTR that is to be given to the user.
777 Only parameters that are specific to Win32
778 and whose values are not correctly recorded in the frame's
779 param_alist need to be considered here. */
780
781 x_report_frame_params (f, alistptr)
782 struct frame *f;
783 Lisp_Object *alistptr;
784 {
785 char buf[16];
786 Lisp_Object tem;
787
788 /* Represent negative positions (off the top or left screen edge)
789 in a way that Fmodify_frame_parameters will understand correctly. */
790 XSETINT (tem, f->output_data.win32->left_pos);
791 if (f->output_data.win32->left_pos >= 0)
792 store_in_alist (alistptr, Qleft, tem);
793 else
794 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
795
796 XSETINT (tem, f->output_data.win32->top_pos);
797 if (f->output_data.win32->top_pos >= 0)
798 store_in_alist (alistptr, Qtop, tem);
799 else
800 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
801
802 store_in_alist (alistptr, Qborder_width,
803 make_number (f->output_data.win32->border_width));
804 store_in_alist (alistptr, Qinternal_border_width,
805 make_number (f->output_data.win32->internal_border_width));
806 sprintf (buf, "%ld", (long) FRAME_WIN32_WINDOW (f));
807 store_in_alist (alistptr, Qwindow_id,
808 build_string (buf));
809 store_in_alist (alistptr, Qicon_name, f->icon_name);
810 FRAME_SAMPLE_VISIBILITY (f);
811 store_in_alist (alistptr, Qvisibility,
812 (FRAME_VISIBLE_P (f) ? Qt
813 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
814 store_in_alist (alistptr, Qdisplay,
815 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->car);
816 }
817 \f
818
819 #if 0
820 DEFUN ("win32-rgb", Fwin32_rgb, Swin32_rgb, 3, 3, 0,
821 "Convert RGB numbers to a windows color reference.")
822 (red, green, blue)
823 Lisp_Object red, green, blue;
824 {
825 Lisp_Object rgb;
826
827 CHECK_NUMBER (red, 0);
828 CHECK_NUMBER (green, 0);
829 CHECK_NUMBER (blue, 0);
830
831 XSET (rgb, Lisp_Int, RGB(XUINT(red), XUINT(green), XUINT(blue)));
832
833 return (rgb);
834 }
835
836
837 #else
838 /* The default colors for the win32 color map */
839 typedef struct colormap_t
840 {
841 char *name;
842 COLORREF colorref;
843 } colormap_t;
844
845 colormap_t win32_color_map[] =
846 {
847 {"snow" , RGB (255,250,250)},
848 {"ghost white" , RGB (248,248,255)},
849 {"GhostWhite" , RGB (248,248,255)},
850 {"white smoke" , RGB (245,245,245)},
851 {"WhiteSmoke" , RGB (245,245,245)},
852 {"gainsboro" , RGB (220,220,220)},
853 {"floral white" , RGB (255,250,240)},
854 {"FloralWhite" , RGB (255,250,240)},
855 {"old lace" , RGB (253,245,230)},
856 {"OldLace" , RGB (253,245,230)},
857 {"linen" , RGB (250,240,230)},
858 {"antique white" , RGB (250,235,215)},
859 {"AntiqueWhite" , RGB (250,235,215)},
860 {"papaya whip" , RGB (255,239,213)},
861 {"PapayaWhip" , RGB (255,239,213)},
862 {"blanched almond" , RGB (255,235,205)},
863 {"BlanchedAlmond" , RGB (255,235,205)},
864 {"bisque" , RGB (255,228,196)},
865 {"peach puff" , RGB (255,218,185)},
866 {"PeachPuff" , RGB (255,218,185)},
867 {"navajo white" , RGB (255,222,173)},
868 {"NavajoWhite" , RGB (255,222,173)},
869 {"moccasin" , RGB (255,228,181)},
870 {"cornsilk" , RGB (255,248,220)},
871 {"ivory" , RGB (255,255,240)},
872 {"lemon chiffon" , RGB (255,250,205)},
873 {"LemonChiffon" , RGB (255,250,205)},
874 {"seashell" , RGB (255,245,238)},
875 {"honeydew" , RGB (240,255,240)},
876 {"mint cream" , RGB (245,255,250)},
877 {"MintCream" , RGB (245,255,250)},
878 {"azure" , RGB (240,255,255)},
879 {"alice blue" , RGB (240,248,255)},
880 {"AliceBlue" , RGB (240,248,255)},
881 {"lavender" , RGB (230,230,250)},
882 {"lavender blush" , RGB (255,240,245)},
883 {"LavenderBlush" , RGB (255,240,245)},
884 {"misty rose" , RGB (255,228,225)},
885 {"MistyRose" , RGB (255,228,225)},
886 {"white" , RGB (255,255,255)},
887 {"black" , RGB ( 0, 0, 0)},
888 {"dark slate gray" , RGB ( 47, 79, 79)},
889 {"DarkSlateGray" , RGB ( 47, 79, 79)},
890 {"dark slate grey" , RGB ( 47, 79, 79)},
891 {"DarkSlateGrey" , RGB ( 47, 79, 79)},
892 {"dim gray" , RGB (105,105,105)},
893 {"DimGray" , RGB (105,105,105)},
894 {"dim grey" , RGB (105,105,105)},
895 {"DimGrey" , RGB (105,105,105)},
896 {"slate gray" , RGB (112,128,144)},
897 {"SlateGray" , RGB (112,128,144)},
898 {"slate grey" , RGB (112,128,144)},
899 {"SlateGrey" , RGB (112,128,144)},
900 {"light slate gray" , RGB (119,136,153)},
901 {"LightSlateGray" , RGB (119,136,153)},
902 {"light slate grey" , RGB (119,136,153)},
903 {"LightSlateGrey" , RGB (119,136,153)},
904 {"gray" , RGB (190,190,190)},
905 {"grey" , RGB (190,190,190)},
906 {"light grey" , RGB (211,211,211)},
907 {"LightGrey" , RGB (211,211,211)},
908 {"light gray" , RGB (211,211,211)},
909 {"LightGray" , RGB (211,211,211)},
910 {"midnight blue" , RGB ( 25, 25,112)},
911 {"MidnightBlue" , RGB ( 25, 25,112)},
912 {"navy" , RGB ( 0, 0,128)},
913 {"navy blue" , RGB ( 0, 0,128)},
914 {"NavyBlue" , RGB ( 0, 0,128)},
915 {"cornflower blue" , RGB (100,149,237)},
916 {"CornflowerBlue" , RGB (100,149,237)},
917 {"dark slate blue" , RGB ( 72, 61,139)},
918 {"DarkSlateBlue" , RGB ( 72, 61,139)},
919 {"slate blue" , RGB (106, 90,205)},
920 {"SlateBlue" , RGB (106, 90,205)},
921 {"medium slate blue" , RGB (123,104,238)},
922 {"MediumSlateBlue" , RGB (123,104,238)},
923 {"light slate blue" , RGB (132,112,255)},
924 {"LightSlateBlue" , RGB (132,112,255)},
925 {"medium blue" , RGB ( 0, 0,205)},
926 {"MediumBlue" , RGB ( 0, 0,205)},
927 {"royal blue" , RGB ( 65,105,225)},
928 {"RoyalBlue" , RGB ( 65,105,225)},
929 {"blue" , RGB ( 0, 0,255)},
930 {"dodger blue" , RGB ( 30,144,255)},
931 {"DodgerBlue" , RGB ( 30,144,255)},
932 {"deep sky blue" , RGB ( 0,191,255)},
933 {"DeepSkyBlue" , RGB ( 0,191,255)},
934 {"sky blue" , RGB (135,206,235)},
935 {"SkyBlue" , RGB (135,206,235)},
936 {"light sky blue" , RGB (135,206,250)},
937 {"LightSkyBlue" , RGB (135,206,250)},
938 {"steel blue" , RGB ( 70,130,180)},
939 {"SteelBlue" , RGB ( 70,130,180)},
940 {"light steel blue" , RGB (176,196,222)},
941 {"LightSteelBlue" , RGB (176,196,222)},
942 {"light blue" , RGB (173,216,230)},
943 {"LightBlue" , RGB (173,216,230)},
944 {"powder blue" , RGB (176,224,230)},
945 {"PowderBlue" , RGB (176,224,230)},
946 {"pale turquoise" , RGB (175,238,238)},
947 {"PaleTurquoise" , RGB (175,238,238)},
948 {"dark turquoise" , RGB ( 0,206,209)},
949 {"DarkTurquoise" , RGB ( 0,206,209)},
950 {"medium turquoise" , RGB ( 72,209,204)},
951 {"MediumTurquoise" , RGB ( 72,209,204)},
952 {"turquoise" , RGB ( 64,224,208)},
953 {"cyan" , RGB ( 0,255,255)},
954 {"light cyan" , RGB (224,255,255)},
955 {"LightCyan" , RGB (224,255,255)},
956 {"cadet blue" , RGB ( 95,158,160)},
957 {"CadetBlue" , RGB ( 95,158,160)},
958 {"medium aquamarine" , RGB (102,205,170)},
959 {"MediumAquamarine" , RGB (102,205,170)},
960 {"aquamarine" , RGB (127,255,212)},
961 {"dark green" , RGB ( 0,100, 0)},
962 {"DarkGreen" , RGB ( 0,100, 0)},
963 {"dark olive green" , RGB ( 85,107, 47)},
964 {"DarkOliveGreen" , RGB ( 85,107, 47)},
965 {"dark sea green" , RGB (143,188,143)},
966 {"DarkSeaGreen" , RGB (143,188,143)},
967 {"sea green" , RGB ( 46,139, 87)},
968 {"SeaGreen" , RGB ( 46,139, 87)},
969 {"medium sea green" , RGB ( 60,179,113)},
970 {"MediumSeaGreen" , RGB ( 60,179,113)},
971 {"light sea green" , RGB ( 32,178,170)},
972 {"LightSeaGreen" , RGB ( 32,178,170)},
973 {"pale green" , RGB (152,251,152)},
974 {"PaleGreen" , RGB (152,251,152)},
975 {"spring green" , RGB ( 0,255,127)},
976 {"SpringGreen" , RGB ( 0,255,127)},
977 {"lawn green" , RGB (124,252, 0)},
978 {"LawnGreen" , RGB (124,252, 0)},
979 {"green" , RGB ( 0,255, 0)},
980 {"chartreuse" , RGB (127,255, 0)},
981 {"medium spring green" , RGB ( 0,250,154)},
982 {"MediumSpringGreen" , RGB ( 0,250,154)},
983 {"green yellow" , RGB (173,255, 47)},
984 {"GreenYellow" , RGB (173,255, 47)},
985 {"lime green" , RGB ( 50,205, 50)},
986 {"LimeGreen" , RGB ( 50,205, 50)},
987 {"yellow green" , RGB (154,205, 50)},
988 {"YellowGreen" , RGB (154,205, 50)},
989 {"forest green" , RGB ( 34,139, 34)},
990 {"ForestGreen" , RGB ( 34,139, 34)},
991 {"olive drab" , RGB (107,142, 35)},
992 {"OliveDrab" , RGB (107,142, 35)},
993 {"dark khaki" , RGB (189,183,107)},
994 {"DarkKhaki" , RGB (189,183,107)},
995 {"khaki" , RGB (240,230,140)},
996 {"pale goldenrod" , RGB (238,232,170)},
997 {"PaleGoldenrod" , RGB (238,232,170)},
998 {"light goldenrod yellow" , RGB (250,250,210)},
999 {"LightGoldenrodYellow" , RGB (250,250,210)},
1000 {"light yellow" , RGB (255,255,224)},
1001 {"LightYellow" , RGB (255,255,224)},
1002 {"yellow" , RGB (255,255, 0)},
1003 {"gold" , RGB (255,215, 0)},
1004 {"light goldenrod" , RGB (238,221,130)},
1005 {"LightGoldenrod" , RGB (238,221,130)},
1006 {"goldenrod" , RGB (218,165, 32)},
1007 {"dark goldenrod" , RGB (184,134, 11)},
1008 {"DarkGoldenrod" , RGB (184,134, 11)},
1009 {"rosy brown" , RGB (188,143,143)},
1010 {"RosyBrown" , RGB (188,143,143)},
1011 {"indian red" , RGB (205, 92, 92)},
1012 {"IndianRed" , RGB (205, 92, 92)},
1013 {"saddle brown" , RGB (139, 69, 19)},
1014 {"SaddleBrown" , RGB (139, 69, 19)},
1015 {"sienna" , RGB (160, 82, 45)},
1016 {"peru" , RGB (205,133, 63)},
1017 {"burlywood" , RGB (222,184,135)},
1018 {"beige" , RGB (245,245,220)},
1019 {"wheat" , RGB (245,222,179)},
1020 {"sandy brown" , RGB (244,164, 96)},
1021 {"SandyBrown" , RGB (244,164, 96)},
1022 {"tan" , RGB (210,180,140)},
1023 {"chocolate" , RGB (210,105, 30)},
1024 {"firebrick" , RGB (178,34, 34)},
1025 {"brown" , RGB (165,42, 42)},
1026 {"dark salmon" , RGB (233,150,122)},
1027 {"DarkSalmon" , RGB (233,150,122)},
1028 {"salmon" , RGB (250,128,114)},
1029 {"light salmon" , RGB (255,160,122)},
1030 {"LightSalmon" , RGB (255,160,122)},
1031 {"orange" , RGB (255,165, 0)},
1032 {"dark orange" , RGB (255,140, 0)},
1033 {"DarkOrange" , RGB (255,140, 0)},
1034 {"coral" , RGB (255,127, 80)},
1035 {"light coral" , RGB (240,128,128)},
1036 {"LightCoral" , RGB (240,128,128)},
1037 {"tomato" , RGB (255, 99, 71)},
1038 {"orange red" , RGB (255, 69, 0)},
1039 {"OrangeRed" , RGB (255, 69, 0)},
1040 {"red" , RGB (255, 0, 0)},
1041 {"hot pink" , RGB (255,105,180)},
1042 {"HotPink" , RGB (255,105,180)},
1043 {"deep pink" , RGB (255, 20,147)},
1044 {"DeepPink" , RGB (255, 20,147)},
1045 {"pink" , RGB (255,192,203)},
1046 {"light pink" , RGB (255,182,193)},
1047 {"LightPink" , RGB (255,182,193)},
1048 {"pale violet red" , RGB (219,112,147)},
1049 {"PaleVioletRed" , RGB (219,112,147)},
1050 {"maroon" , RGB (176, 48, 96)},
1051 {"medium violet red" , RGB (199, 21,133)},
1052 {"MediumVioletRed" , RGB (199, 21,133)},
1053 {"violet red" , RGB (208, 32,144)},
1054 {"VioletRed" , RGB (208, 32,144)},
1055 {"magenta" , RGB (255, 0,255)},
1056 {"violet" , RGB (238,130,238)},
1057 {"plum" , RGB (221,160,221)},
1058 {"orchid" , RGB (218,112,214)},
1059 {"medium orchid" , RGB (186, 85,211)},
1060 {"MediumOrchid" , RGB (186, 85,211)},
1061 {"dark orchid" , RGB (153, 50,204)},
1062 {"DarkOrchid" , RGB (153, 50,204)},
1063 {"dark violet" , RGB (148, 0,211)},
1064 {"DarkViolet" , RGB (148, 0,211)},
1065 {"blue violet" , RGB (138, 43,226)},
1066 {"BlueViolet" , RGB (138, 43,226)},
1067 {"purple" , RGB (160, 32,240)},
1068 {"medium purple" , RGB (147,112,219)},
1069 {"MediumPurple" , RGB (147,112,219)},
1070 {"thistle" , RGB (216,191,216)},
1071 {"gray0" , RGB ( 0, 0, 0)},
1072 {"grey0" , RGB ( 0, 0, 0)},
1073 {"dark grey" , RGB (169,169,169)},
1074 {"DarkGrey" , RGB (169,169,169)},
1075 {"dark gray" , RGB (169,169,169)},
1076 {"DarkGray" , RGB (169,169,169)},
1077 {"dark blue" , RGB ( 0, 0,139)},
1078 {"DarkBlue" , RGB ( 0, 0,139)},
1079 {"dark cyan" , RGB ( 0,139,139)},
1080 {"DarkCyan" , RGB ( 0,139,139)},
1081 {"dark magenta" , RGB (139, 0,139)},
1082 {"DarkMagenta" , RGB (139, 0,139)},
1083 {"dark red" , RGB (139, 0, 0)},
1084 {"DarkRed" , RGB (139, 0, 0)},
1085 {"light green" , RGB (144,238,144)},
1086 {"LightGreen" , RGB (144,238,144)},
1087 };
1088
1089 DEFUN ("win32-default-color-map", Fwin32_default_color_map, Swin32_default_color_map,
1090 0, 0, 0, "Return the default color map.")
1091 ()
1092 {
1093 int i;
1094 colormap_t *pc = win32_color_map;
1095 Lisp_Object cmap;
1096
1097 BLOCK_INPUT;
1098
1099 cmap = Qnil;
1100
1101 for (i = 0; i < sizeof (win32_color_map) / sizeof (win32_color_map[0]);
1102 pc++, i++)
1103 cmap = Fcons (Fcons (build_string (pc->name),
1104 make_number (pc->colorref)),
1105 cmap);
1106
1107 UNBLOCK_INPUT;
1108
1109 return (cmap);
1110 }
1111 #endif
1112
1113 Lisp_Object
1114 win32_to_x_color (rgb)
1115 Lisp_Object rgb;
1116 {
1117 Lisp_Object color;
1118
1119 CHECK_NUMBER (rgb, 0);
1120
1121 BLOCK_INPUT;
1122
1123 color = Frassq (rgb, Vwin32_color_map);
1124
1125 UNBLOCK_INPUT;
1126
1127 if (!NILP (color))
1128 return (Fcar (color));
1129 else
1130 return Qnil;
1131 }
1132
1133 COLORREF
1134 x_to_win32_color (colorname)
1135 char * colorname;
1136 {
1137 register Lisp_Object tail, ret = Qnil;
1138
1139 BLOCK_INPUT;
1140
1141 for (tail = Vwin32_color_map; !NILP (tail); tail = Fcdr (tail))
1142 {
1143 register Lisp_Object elt, tem;
1144
1145 elt = Fcar (tail);
1146 if (!CONSP (elt)) continue;
1147
1148 tem = Fcar (elt);
1149
1150 if (lstrcmpi (XSTRING (tem)->data, colorname) == 0)
1151 {
1152 ret = XUINT(Fcdr (elt));
1153 break;
1154 }
1155
1156 QUIT;
1157 }
1158
1159 UNBLOCK_INPUT;
1160
1161 return ret;
1162 }
1163
1164 /* Decide if color named COLOR is valid for the display associated with
1165 the selected frame; if so, return the rgb values in COLOR_DEF.
1166 If ALLOC is nonzero, allocate a new colormap cell. */
1167
1168 int
1169 defined_color (f, color, color_def, alloc)
1170 FRAME_PTR f;
1171 char *color;
1172 COLORREF *color_def;
1173 int alloc;
1174 {
1175 register Lisp_Object tem;
1176
1177 tem = x_to_win32_color (color);
1178
1179 if (!NILP (tem))
1180 {
1181 *color_def = XUINT (tem);
1182 return 1;
1183 }
1184 else
1185 {
1186 return 0;
1187 }
1188 }
1189
1190 /* Given a string ARG naming a color, compute a pixel value from it
1191 suitable for screen F.
1192 If F is not a color screen, return DEF (default) regardless of what
1193 ARG says. */
1194
1195 int
1196 x_decode_color (f, arg, def)
1197 FRAME_PTR f;
1198 Lisp_Object arg;
1199 int def;
1200 {
1201 COLORREF cdef;
1202
1203 CHECK_STRING (arg, 0);
1204
1205 if (strcmp (XSTRING (arg)->data, "black") == 0)
1206 return BLACK_PIX_DEFAULT (f);
1207 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1208 return WHITE_PIX_DEFAULT (f);
1209
1210 if ((FRAME_WIN32_DISPLAY_INFO (f)->n_planes * FRAME_WIN32_DISPLAY_INFO (f)->n_cbits) == 1)
1211 return def;
1212
1213 /* defined_color is responsible for coping with failures
1214 by looking for a near-miss. */
1215 if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
1216 return cdef;
1217
1218 /* defined_color failed; return an ultimate default. */
1219 return def;
1220 }
1221 \f
1222 /* Functions called only from `x_set_frame_param'
1223 to set individual parameters.
1224
1225 If FRAME_WIN32_WINDOW (f) is 0,
1226 the frame is being created and its window does not exist yet.
1227 In that case, just record the parameter's new value
1228 in the standard place; do not attempt to change the window. */
1229
1230 void
1231 x_set_foreground_color (f, arg, oldval)
1232 struct frame *f;
1233 Lisp_Object arg, oldval;
1234 {
1235 f->output_data.win32->foreground_pixel
1236 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1237 if (FRAME_WIN32_WINDOW (f) != 0)
1238 {
1239 recompute_basic_faces (f);
1240 if (FRAME_VISIBLE_P (f))
1241 redraw_frame (f);
1242 }
1243 }
1244
1245 void
1246 x_set_background_color (f, arg, oldval)
1247 struct frame *f;
1248 Lisp_Object arg, oldval;
1249 {
1250 Pixmap temp;
1251 int mask;
1252
1253 f->output_data.win32->background_pixel
1254 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1255
1256 if (FRAME_WIN32_WINDOW (f) != 0)
1257 {
1258 SetWindowLong (FRAME_WIN32_WINDOW (f), WND_BACKGROUND_INDEX, f->output_data.win32->background_pixel);
1259
1260 recompute_basic_faces (f);
1261
1262 if (FRAME_VISIBLE_P (f))
1263 redraw_frame (f);
1264 }
1265 }
1266
1267 void
1268 x_set_mouse_color (f, arg, oldval)
1269 struct frame *f;
1270 Lisp_Object arg, oldval;
1271 {
1272 #if 0
1273 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1274 #endif
1275 int mask_color;
1276
1277 if (!EQ (Qnil, arg))
1278 f->output_data.win32->mouse_pixel
1279 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1280 mask_color = f->output_data.win32->background_pixel;
1281 /* No invisible pointers. */
1282 if (mask_color == f->output_data.win32->mouse_pixel
1283 && mask_color == f->output_data.win32->background_pixel)
1284 f->output_data.win32->mouse_pixel = f->output_data.win32->foreground_pixel;
1285
1286 #if 0
1287 BLOCK_INPUT;
1288
1289 /* It's not okay to crash if the user selects a screwy cursor. */
1290 x_catch_errors (FRAME_WIN32_DISPLAY (f));
1291
1292 if (!EQ (Qnil, Vx_pointer_shape))
1293 {
1294 CHECK_NUMBER (Vx_pointer_shape, 0);
1295 cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XINT (Vx_pointer_shape));
1296 }
1297 else
1298 cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_xterm);
1299 x_check_errors (FRAME_WIN32_DISPLAY (f), "bad text pointer cursor: %s");
1300
1301 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1302 {
1303 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1304 nontext_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f),
1305 XINT (Vx_nontext_pointer_shape));
1306 }
1307 else
1308 nontext_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_left_ptr);
1309 x_check_errors (FRAME_WIN32_DISPLAY (f), "bad nontext pointer cursor: %s");
1310
1311 if (!EQ (Qnil, Vx_mode_pointer_shape))
1312 {
1313 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1314 mode_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f),
1315 XINT (Vx_mode_pointer_shape));
1316 }
1317 else
1318 mode_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_xterm);
1319 x_check_errors (FRAME_WIN32_DISPLAY (f), "bad modeline pointer cursor: %s");
1320
1321 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1322 {
1323 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1324 cross_cursor
1325 = XCreateFontCursor (FRAME_WIN32_DISPLAY (f),
1326 XINT (Vx_sensitive_text_pointer_shape));
1327 }
1328 else
1329 cross_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_crosshair);
1330
1331 /* Check and report errors with the above calls. */
1332 x_check_errors (FRAME_WIN32_DISPLAY (f), "can't set cursor shape: %s");
1333 x_uncatch_errors (FRAME_WIN32_DISPLAY (f));
1334
1335 {
1336 XColor fore_color, back_color;
1337
1338 fore_color.pixel = f->output_data.win32->mouse_pixel;
1339 back_color.pixel = mask_color;
1340 XQueryColor (FRAME_WIN32_DISPLAY (f),
1341 DefaultColormap (FRAME_WIN32_DISPLAY (f),
1342 DefaultScreen (FRAME_WIN32_DISPLAY (f))),
1343 &fore_color);
1344 XQueryColor (FRAME_WIN32_DISPLAY (f),
1345 DefaultColormap (FRAME_WIN32_DISPLAY (f),
1346 DefaultScreen (FRAME_WIN32_DISPLAY (f))),
1347 &back_color);
1348 XRecolorCursor (FRAME_WIN32_DISPLAY (f), cursor,
1349 &fore_color, &back_color);
1350 XRecolorCursor (FRAME_WIN32_DISPLAY (f), nontext_cursor,
1351 &fore_color, &back_color);
1352 XRecolorCursor (FRAME_WIN32_DISPLAY (f), mode_cursor,
1353 &fore_color, &back_color);
1354 XRecolorCursor (FRAME_WIN32_DISPLAY (f), cross_cursor,
1355 &fore_color, &back_color);
1356 }
1357
1358 if (FRAME_WIN32_WINDOW (f) != 0)
1359 {
1360 XDefineCursor (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f), cursor);
1361 }
1362
1363 if (cursor != f->output_data.win32->text_cursor && f->output_data.win32->text_cursor != 0)
1364 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->text_cursor);
1365 f->output_data.win32->text_cursor = cursor;
1366
1367 if (nontext_cursor != f->output_data.win32->nontext_cursor
1368 && f->output_data.win32->nontext_cursor != 0)
1369 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->nontext_cursor);
1370 f->output_data.win32->nontext_cursor = nontext_cursor;
1371
1372 if (mode_cursor != f->output_data.win32->modeline_cursor
1373 && f->output_data.win32->modeline_cursor != 0)
1374 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->modeline_cursor);
1375 f->output_data.win32->modeline_cursor = mode_cursor;
1376 if (cross_cursor != f->output_data.win32->cross_cursor
1377 && f->output_data.win32->cross_cursor != 0)
1378 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->cross_cursor);
1379 f->output_data.win32->cross_cursor = cross_cursor;
1380
1381 XFlush (FRAME_WIN32_DISPLAY (f));
1382 UNBLOCK_INPUT;
1383 #endif
1384 }
1385
1386 void
1387 x_set_cursor_color (f, arg, oldval)
1388 struct frame *f;
1389 Lisp_Object arg, oldval;
1390 {
1391 unsigned long fore_pixel;
1392
1393 if (!EQ (Vx_cursor_fore_pixel, Qnil))
1394 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1395 WHITE_PIX_DEFAULT (f));
1396 else
1397 fore_pixel = f->output_data.win32->background_pixel;
1398 f->output_data.win32->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1399
1400 /* Make sure that the cursor color differs from the background color. */
1401 if (f->output_data.win32->cursor_pixel == f->output_data.win32->background_pixel)
1402 {
1403 f->output_data.win32->cursor_pixel = f->output_data.win32->mouse_pixel;
1404 if (f->output_data.win32->cursor_pixel == fore_pixel)
1405 fore_pixel = f->output_data.win32->background_pixel;
1406 }
1407 f->output_data.win32->cursor_foreground_pixel = fore_pixel;
1408
1409 if (FRAME_WIN32_WINDOW (f) != 0)
1410 {
1411 if (FRAME_VISIBLE_P (f))
1412 {
1413 x_display_cursor (f, 0);
1414 x_display_cursor (f, 1);
1415 }
1416 }
1417 }
1418
1419 /* Set the border-color of frame F to value described by ARG.
1420 ARG can be a string naming a color.
1421 The border-color is used for the border that is drawn by the server.
1422 Note that this does not fully take effect if done before
1423 F has a window; it must be redone when the window is created. */
1424
1425 void
1426 x_set_border_color (f, arg, oldval)
1427 struct frame *f;
1428 Lisp_Object arg, oldval;
1429 {
1430 unsigned char *str;
1431 int pix;
1432
1433 CHECK_STRING (arg, 0);
1434 str = XSTRING (arg)->data;
1435
1436 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1437
1438 x_set_border_pixel (f, pix);
1439 }
1440
1441 /* Set the border-color of frame F to pixel value PIX.
1442 Note that this does not fully take effect if done before
1443 F has an window. */
1444
1445 x_set_border_pixel (f, pix)
1446 struct frame *f;
1447 int pix;
1448 {
1449 f->output_data.win32->border_pixel = pix;
1450
1451 if (FRAME_WIN32_WINDOW (f) != 0 && f->output_data.win32->border_width > 0)
1452 {
1453 if (FRAME_VISIBLE_P (f))
1454 redraw_frame (f);
1455 }
1456 }
1457
1458 void
1459 x_set_cursor_type (f, arg, oldval)
1460 FRAME_PTR f;
1461 Lisp_Object arg, oldval;
1462 {
1463 if (EQ (arg, Qbar))
1464 {
1465 FRAME_DESIRED_CURSOR (f) = bar_cursor;
1466 f->output_data.win32->cursor_width = 2;
1467 }
1468 else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
1469 && INTEGERP (XCONS (arg)->cdr))
1470 {
1471 FRAME_DESIRED_CURSOR (f) = bar_cursor;
1472 f->output_data.win32->cursor_width = XINT (XCONS (arg)->cdr);
1473 }
1474 else
1475 /* Treat anything unknown as "box cursor".
1476 It was bad to signal an error; people have trouble fixing
1477 .Xdefaults with Emacs, when it has something bad in it. */
1478 FRAME_DESIRED_CURSOR (f) = filled_box_cursor;
1479
1480 /* Make sure the cursor gets redrawn. This is overkill, but how
1481 often do people change cursor types? */
1482 update_mode_lines++;
1483 }
1484
1485 void
1486 x_set_icon_type (f, arg, oldval)
1487 struct frame *f;
1488 Lisp_Object arg, oldval;
1489 {
1490 #if 0
1491 Lisp_Object tem;
1492 int result;
1493
1494 if (STRINGP (arg))
1495 {
1496 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1497 return;
1498 }
1499 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1500 return;
1501
1502 BLOCK_INPUT;
1503 if (NILP (arg))
1504 result = x_text_icon (f,
1505 (char *) XSTRING ((!NILP (f->icon_name)
1506 ? f->icon_name
1507 : f->name))->data);
1508 else
1509 result = x_bitmap_icon (f, arg);
1510
1511 if (result)
1512 {
1513 UNBLOCK_INPUT;
1514 error ("No icon window available");
1515 }
1516
1517 /* If the window was unmapped (and its icon was mapped),
1518 the new icon is not mapped, so map the window in its stead. */
1519 if (FRAME_VISIBLE_P (f))
1520 {
1521 #ifdef USE_X_TOOLKIT
1522 XtPopup (f->output_data.win32->widget, XtGrabNone);
1523 #endif
1524 XMapWindow (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f));
1525 }
1526
1527 XFlush (FRAME_WIN32_DISPLAY (f));
1528 UNBLOCK_INPUT;
1529 #endif
1530 }
1531
1532 /* Return non-nil if frame F wants a bitmap icon. */
1533
1534 Lisp_Object
1535 x_icon_type (f)
1536 FRAME_PTR f;
1537 {
1538 Lisp_Object tem;
1539
1540 tem = assq_no_quit (Qicon_type, f->param_alist);
1541 if (CONSP (tem))
1542 return XCONS (tem)->cdr;
1543 else
1544 return Qnil;
1545 }
1546
1547 void
1548 x_set_icon_name (f, arg, oldval)
1549 struct frame *f;
1550 Lisp_Object arg, oldval;
1551 {
1552 Lisp_Object tem;
1553 int result;
1554
1555 if (STRINGP (arg))
1556 {
1557 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1558 return;
1559 }
1560 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1561 return;
1562
1563 f->icon_name = arg;
1564
1565 #if 0
1566 if (f->output_data.win32->icon_bitmap != 0)
1567 return;
1568
1569 BLOCK_INPUT;
1570
1571 result = x_text_icon (f,
1572 (char *) XSTRING ((!NILP (f->icon_name)
1573 ? f->icon_name
1574 : f->name))->data);
1575
1576 if (result)
1577 {
1578 UNBLOCK_INPUT;
1579 error ("No icon window available");
1580 }
1581
1582 /* If the window was unmapped (and its icon was mapped),
1583 the new icon is not mapped, so map the window in its stead. */
1584 if (FRAME_VISIBLE_P (f))
1585 {
1586 #ifdef USE_X_TOOLKIT
1587 XtPopup (f->output_data.win32->widget, XtGrabNone);
1588 #endif
1589 XMapWindow (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f));
1590 }
1591
1592 XFlush (FRAME_WIN32_DISPLAY (f));
1593 UNBLOCK_INPUT;
1594 #endif
1595 }
1596
1597 extern Lisp_Object x_new_font ();
1598
1599 void
1600 x_set_font (f, arg, oldval)
1601 struct frame *f;
1602 Lisp_Object arg, oldval;
1603 {
1604 Lisp_Object result;
1605
1606 CHECK_STRING (arg, 1);
1607
1608 BLOCK_INPUT;
1609 result = x_new_font (f, XSTRING (arg)->data);
1610 UNBLOCK_INPUT;
1611
1612 if (EQ (result, Qnil))
1613 error ("Font \"%s\" is not defined", XSTRING (arg)->data);
1614 else if (EQ (result, Qt))
1615 error ("the characters of the given font have varying widths");
1616 else if (STRINGP (result))
1617 {
1618 recompute_basic_faces (f);
1619 store_frame_param (f, Qfont, result);
1620 }
1621 else
1622 abort ();
1623 }
1624
1625 void
1626 x_set_border_width (f, arg, oldval)
1627 struct frame *f;
1628 Lisp_Object arg, oldval;
1629 {
1630 CHECK_NUMBER (arg, 0);
1631
1632 if (XINT (arg) == f->output_data.win32->border_width)
1633 return;
1634
1635 if (FRAME_WIN32_WINDOW (f) != 0)
1636 error ("Cannot change the border width of a window");
1637
1638 f->output_data.win32->border_width = XINT (arg);
1639 }
1640
1641 void
1642 x_set_internal_border_width (f, arg, oldval)
1643 struct frame *f;
1644 Lisp_Object arg, oldval;
1645 {
1646 int mask;
1647 int old = f->output_data.win32->internal_border_width;
1648
1649 CHECK_NUMBER (arg, 0);
1650 f->output_data.win32->internal_border_width = XINT (arg);
1651 if (f->output_data.win32->internal_border_width < 0)
1652 f->output_data.win32->internal_border_width = 0;
1653
1654 if (f->output_data.win32->internal_border_width == old)
1655 return;
1656
1657 if (FRAME_WIN32_WINDOW (f) != 0)
1658 {
1659 BLOCK_INPUT;
1660 x_set_window_size (f, 0, f->width, f->height);
1661 UNBLOCK_INPUT;
1662 SET_FRAME_GARBAGED (f);
1663 }
1664 }
1665
1666 void
1667 x_set_visibility (f, value, oldval)
1668 struct frame *f;
1669 Lisp_Object value, oldval;
1670 {
1671 Lisp_Object frame;
1672 XSETFRAME (frame, f);
1673
1674 if (NILP (value))
1675 Fmake_frame_invisible (frame, Qt);
1676 else if (EQ (value, Qicon))
1677 Ficonify_frame (frame);
1678 else
1679 Fmake_frame_visible (frame);
1680 }
1681
1682 void
1683 x_set_menu_bar_lines (f, value, oldval)
1684 struct frame *f;
1685 Lisp_Object value, oldval;
1686 {
1687 int nlines;
1688 int olines = FRAME_MENU_BAR_LINES (f);
1689
1690 /* Right now, menu bars don't work properly in minibuf-only frames;
1691 most of the commands try to apply themselves to the minibuffer
1692 frame itslef, and get an error because you can't switch buffers
1693 in or split the minibuffer window. */
1694 if (FRAME_MINIBUF_ONLY_P (f))
1695 return;
1696
1697 if (INTEGERP (value))
1698 nlines = XINT (value);
1699 else
1700 nlines = 0;
1701
1702 FRAME_MENU_BAR_LINES (f) = 0;
1703 if (nlines)
1704 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1705 else
1706 {
1707 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1708 free_frame_menubar (f);
1709 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1710 }
1711 }
1712
1713 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1714 win32_id_name.
1715
1716 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1717 name; if NAME is a string, set F's name to NAME and set
1718 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1719
1720 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1721 suggesting a new name, which lisp code should override; if
1722 F->explicit_name is set, ignore the new name; otherwise, set it. */
1723
1724 void
1725 x_set_name (f, name, explicit)
1726 struct frame *f;
1727 Lisp_Object name;
1728 int explicit;
1729 {
1730 /* Make sure that requests from lisp code override requests from
1731 Emacs redisplay code. */
1732 if (explicit)
1733 {
1734 /* If we're switching from explicit to implicit, we had better
1735 update the mode lines and thereby update the title. */
1736 if (f->explicit_name && NILP (name))
1737 update_mode_lines = 1;
1738
1739 f->explicit_name = ! NILP (name);
1740 }
1741 else if (f->explicit_name)
1742 return;
1743
1744 /* If NAME is nil, set the name to the win32_id_name. */
1745 if (NILP (name))
1746 {
1747 /* Check for no change needed in this very common case
1748 before we do any consing. */
1749 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f)->win32_id_name,
1750 XSTRING (f->name)->data))
1751 return;
1752 name = build_string (FRAME_WIN32_DISPLAY_INFO (f)->win32_id_name);
1753 }
1754 else
1755 CHECK_STRING (name, 0);
1756
1757 /* Don't change the name if it's already NAME. */
1758 if (! NILP (Fstring_equal (name, f->name)))
1759 return;
1760
1761 if (FRAME_WIN32_WINDOW (f))
1762 {
1763 BLOCK_INPUT;
1764 SetWindowText(FRAME_WIN32_WINDOW (f), XSTRING (name)->data);
1765 UNBLOCK_INPUT;
1766 }
1767
1768 f->name = name;
1769 }
1770
1771 /* This function should be called when the user's lisp code has
1772 specified a name for the frame; the name will override any set by the
1773 redisplay code. */
1774 void
1775 x_explicitly_set_name (f, arg, oldval)
1776 FRAME_PTR f;
1777 Lisp_Object arg, oldval;
1778 {
1779 x_set_name (f, arg, 1);
1780 }
1781
1782 /* This function should be called by Emacs redisplay code to set the
1783 name; names set this way will never override names set by the user's
1784 lisp code. */
1785 void
1786 x_implicitly_set_name (f, arg, oldval)
1787 FRAME_PTR f;
1788 Lisp_Object arg, oldval;
1789 {
1790 x_set_name (f, arg, 0);
1791 }
1792
1793 void
1794 x_set_autoraise (f, arg, oldval)
1795 struct frame *f;
1796 Lisp_Object arg, oldval;
1797 {
1798 f->auto_raise = !EQ (Qnil, arg);
1799 }
1800
1801 void
1802 x_set_autolower (f, arg, oldval)
1803 struct frame *f;
1804 Lisp_Object arg, oldval;
1805 {
1806 f->auto_lower = !EQ (Qnil, arg);
1807 }
1808
1809 void
1810 x_set_unsplittable (f, arg, oldval)
1811 struct frame *f;
1812 Lisp_Object arg, oldval;
1813 {
1814 f->no_split = !NILP (arg);
1815 }
1816
1817 void
1818 x_set_vertical_scroll_bars (f, arg, oldval)
1819 struct frame *f;
1820 Lisp_Object arg, oldval;
1821 {
1822 if (NILP (arg) != ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1823 {
1824 FRAME_HAS_VERTICAL_SCROLL_BARS (f) = ! NILP (arg);
1825
1826 /* We set this parameter before creating the window for the
1827 frame, so we can get the geometry right from the start.
1828 However, if the window hasn't been created yet, we shouldn't
1829 call x_set_window_size. */
1830 if (FRAME_WIN32_WINDOW (f))
1831 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1832 }
1833 }
1834
1835 void
1836 x_set_scroll_bar_width (f, arg, oldval)
1837 struct frame *f;
1838 Lisp_Object arg, oldval;
1839 {
1840 if (NILP (arg))
1841 {
1842 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
1843 FRAME_SCROLL_BAR_COLS (f) = 2;
1844 }
1845 else if (INTEGERP (arg) && XINT (arg) > 0
1846 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
1847 {
1848 int wid = FONT_WIDTH (f->output_data.win32->font);
1849 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
1850 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
1851 if (FRAME_WIN32_WINDOW (f))
1852 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1853 }
1854 }
1855 \f
1856 /* Subroutines of creating an frame. */
1857
1858 /* Make sure that Vx_resource_name is set to a reasonable value.
1859 Fix it up, or set it to `emacs' if it is too hopeless. */
1860
1861 static void
1862 validate_x_resource_name ()
1863 {
1864 int len;
1865 /* Number of valid characters in the resource name. */
1866 int good_count = 0;
1867 /* Number of invalid characters in the resource name. */
1868 int bad_count = 0;
1869 Lisp_Object new;
1870 int i;
1871
1872 if (STRINGP (Vx_resource_name))
1873 {
1874 unsigned char *p = XSTRING (Vx_resource_name)->data;
1875 int i;
1876
1877 len = XSTRING (Vx_resource_name)->size;
1878
1879 /* Only letters, digits, - and _ are valid in resource names.
1880 Count the valid characters and count the invalid ones. */
1881 for (i = 0; i < len; i++)
1882 {
1883 int c = p[i];
1884 if (! ((c >= 'a' && c <= 'z')
1885 || (c >= 'A' && c <= 'Z')
1886 || (c >= '0' && c <= '9')
1887 || c == '-' || c == '_'))
1888 bad_count++;
1889 else
1890 good_count++;
1891 }
1892 }
1893 else
1894 /* Not a string => completely invalid. */
1895 bad_count = 5, good_count = 0;
1896
1897 /* If name is valid already, return. */
1898 if (bad_count == 0)
1899 return;
1900
1901 /* If name is entirely invalid, or nearly so, use `emacs'. */
1902 if (good_count == 0
1903 || (good_count == 1 && bad_count > 0))
1904 {
1905 Vx_resource_name = build_string ("emacs");
1906 return;
1907 }
1908
1909 /* Name is partly valid. Copy it and replace the invalid characters
1910 with underscores. */
1911
1912 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
1913
1914 for (i = 0; i < len; i++)
1915 {
1916 int c = XSTRING (new)->data[i];
1917 if (! ((c >= 'a' && c <= 'z')
1918 || (c >= 'A' && c <= 'Z')
1919 || (c >= '0' && c <= '9')
1920 || c == '-' || c == '_'))
1921 XSTRING (new)->data[i] = '_';
1922 }
1923 }
1924
1925
1926 extern char *x_get_string_resource ();
1927
1928 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
1929 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
1930 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
1931 class, where INSTANCE is the name under which Emacs was invoked, or\n\
1932 the name specified by the `-name' or `-rn' command-line arguments.\n\
1933 \n\
1934 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
1935 class, respectively. You must specify both of them or neither.\n\
1936 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
1937 and the class is `Emacs.CLASS.SUBCLASS'.")
1938 (attribute, class, component, subclass)
1939 Lisp_Object attribute, class, component, subclass;
1940 {
1941 register char *value;
1942 char *name_key;
1943 char *class_key;
1944
1945 CHECK_STRING (attribute, 0);
1946 CHECK_STRING (class, 0);
1947
1948 if (!NILP (component))
1949 CHECK_STRING (component, 1);
1950 if (!NILP (subclass))
1951 CHECK_STRING (subclass, 2);
1952 if (NILP (component) != NILP (subclass))
1953 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
1954
1955 validate_x_resource_name ();
1956
1957 /* Allocate space for the components, the dots which separate them,
1958 and the final '\0'. Make them big enough for the worst case. */
1959 name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
1960 + (STRINGP (component)
1961 ? XSTRING (component)->size : 0)
1962 + XSTRING (attribute)->size
1963 + 3);
1964
1965 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
1966 + XSTRING (class)->size
1967 + (STRINGP (subclass)
1968 ? XSTRING (subclass)->size : 0)
1969 + 3);
1970
1971 /* Start with emacs.FRAMENAME for the name (the specific one)
1972 and with `Emacs' for the class key (the general one). */
1973 strcpy (name_key, XSTRING (Vx_resource_name)->data);
1974 strcpy (class_key, EMACS_CLASS);
1975
1976 strcat (class_key, ".");
1977 strcat (class_key, XSTRING (class)->data);
1978
1979 if (!NILP (component))
1980 {
1981 strcat (class_key, ".");
1982 strcat (class_key, XSTRING (subclass)->data);
1983
1984 strcat (name_key, ".");
1985 strcat (name_key, XSTRING (component)->data);
1986 }
1987
1988 strcat (name_key, ".");
1989 strcat (name_key, XSTRING (attribute)->data);
1990
1991 value = x_get_string_resource (Qnil,
1992 name_key, class_key);
1993
1994 if (value != (char *) 0)
1995 return build_string (value);
1996 else
1997 return Qnil;
1998 }
1999
2000 /* Used when C code wants a resource value. */
2001
2002 char *
2003 x_get_resource_string (attribute, class)
2004 char *attribute, *class;
2005 {
2006 register char *value;
2007 char *name_key;
2008 char *class_key;
2009
2010 /* Allocate space for the components, the dots which separate them,
2011 and the final '\0'. */
2012 name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
2013 + strlen (attribute) + 2);
2014 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2015 + strlen (class) + 2);
2016
2017 sprintf (name_key, "%s.%s",
2018 XSTRING (Vinvocation_name)->data,
2019 attribute);
2020 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2021
2022 return x_get_string_resource (selected_frame,
2023 name_key, class_key);
2024 }
2025
2026 /* Types we might convert a resource string into. */
2027 enum resource_types
2028 {
2029 number, boolean, string, symbol
2030 };
2031
2032 /* Return the value of parameter PARAM.
2033
2034 First search ALIST, then Vdefault_frame_alist, then the X defaults
2035 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2036
2037 Convert the resource to the type specified by desired_type.
2038
2039 If no default is specified, return Qunbound. If you call
2040 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2041 and don't let it get stored in any Lisp-visible variables! */
2042
2043 static Lisp_Object
2044 x_get_arg (alist, param, attribute, class, type)
2045 Lisp_Object alist, param;
2046 char *attribute;
2047 char *class;
2048 enum resource_types type;
2049 {
2050 register Lisp_Object tem;
2051
2052 tem = Fassq (param, alist);
2053 if (EQ (tem, Qnil))
2054 tem = Fassq (param, Vdefault_frame_alist);
2055 if (EQ (tem, Qnil))
2056 {
2057
2058 if (attribute)
2059 {
2060 tem = Fx_get_resource (build_string (attribute),
2061 build_string (class),
2062 Qnil, Qnil);
2063
2064 if (NILP (tem))
2065 return Qunbound;
2066
2067 switch (type)
2068 {
2069 case number:
2070 return make_number (atoi (XSTRING (tem)->data));
2071
2072 case boolean:
2073 tem = Fdowncase (tem);
2074 if (!strcmp (XSTRING (tem)->data, "on")
2075 || !strcmp (XSTRING (tem)->data, "true"))
2076 return Qt;
2077 else
2078 return Qnil;
2079
2080 case string:
2081 return tem;
2082
2083 case symbol:
2084 /* As a special case, we map the values `true' and `on'
2085 to Qt, and `false' and `off' to Qnil. */
2086 {
2087 Lisp_Object lower;
2088 lower = Fdowncase (tem);
2089 if (!strcmp (XSTRING (lower)->data, "on")
2090 || !strcmp (XSTRING (lower)->data, "true"))
2091 return Qt;
2092 else if (!strcmp (XSTRING (lower)->data, "off")
2093 || !strcmp (XSTRING (lower)->data, "false"))
2094 return Qnil;
2095 else
2096 return Fintern (tem, Qnil);
2097 }
2098
2099 default:
2100 abort ();
2101 }
2102 }
2103 else
2104 return Qunbound;
2105 }
2106 return Fcdr (tem);
2107 }
2108
2109 /* Record in frame F the specified or default value according to ALIST
2110 of the parameter named PARAM (a Lisp symbol).
2111 If no value is specified for PARAM, look for an X default for XPROP
2112 on the frame named NAME.
2113 If that is not found either, use the value DEFLT. */
2114
2115 static Lisp_Object
2116 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2117 struct frame *f;
2118 Lisp_Object alist;
2119 Lisp_Object prop;
2120 Lisp_Object deflt;
2121 char *xprop;
2122 char *xclass;
2123 enum resource_types type;
2124 {
2125 Lisp_Object tem;
2126
2127 tem = x_get_arg (alist, prop, xprop, xclass, type);
2128 if (EQ (tem, Qunbound))
2129 tem = deflt;
2130 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2131 return tem;
2132 }
2133 \f
2134 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2135 "Parse an X-style geometry string STRING.\n\
2136 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2137 The properties returned may include `top', `left', `height', and `width'.\n\
2138 The value of `left' or `top' may be an integer,\n\
2139 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2140 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2141 (string)
2142 Lisp_Object string;
2143 {
2144 int geometry, x, y;
2145 unsigned int width, height;
2146 Lisp_Object result;
2147
2148 CHECK_STRING (string, 0);
2149
2150 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2151 &x, &y, &width, &height);
2152
2153 result = Qnil;
2154 if (geometry & XValue)
2155 {
2156 Lisp_Object element;
2157
2158 if (x >= 0 && (geometry & XNegative))
2159 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2160 else if (x < 0 && ! (geometry & XNegative))
2161 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2162 else
2163 element = Fcons (Qleft, make_number (x));
2164 result = Fcons (element, result);
2165 }
2166
2167 if (geometry & YValue)
2168 {
2169 Lisp_Object element;
2170
2171 if (y >= 0 && (geometry & YNegative))
2172 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2173 else if (y < 0 && ! (geometry & YNegative))
2174 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2175 else
2176 element = Fcons (Qtop, make_number (y));
2177 result = Fcons (element, result);
2178 }
2179
2180 if (geometry & WidthValue)
2181 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2182 if (geometry & HeightValue)
2183 result = Fcons (Fcons (Qheight, make_number (height)), result);
2184
2185 return result;
2186 }
2187
2188 /* Calculate the desired size and position of this window,
2189 and return the flags saying which aspects were specified.
2190
2191 This function does not make the coordinates positive. */
2192
2193 #define DEFAULT_ROWS 40
2194 #define DEFAULT_COLS 80
2195
2196 static int
2197 x_figure_window_size (f, parms)
2198 struct frame *f;
2199 Lisp_Object parms;
2200 {
2201 register Lisp_Object tem0, tem1, tem2;
2202 int height, width, left, top;
2203 register int geometry;
2204 long window_prompting = 0;
2205
2206 /* Default values if we fall through.
2207 Actually, if that happens we should get
2208 window manager prompting. */
2209 f->width = DEFAULT_COLS;
2210 f->height = DEFAULT_ROWS;
2211 /* Window managers expect that if program-specified
2212 positions are not (0,0), they're intentional, not defaults. */
2213 f->output_data.win32->top_pos = 0;
2214 f->output_data.win32->left_pos = 0;
2215
2216 tem0 = x_get_arg (parms, Qheight, 0, 0, number);
2217 tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
2218 tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
2219 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2220 {
2221 if (!EQ (tem0, Qunbound))
2222 {
2223 CHECK_NUMBER (tem0, 0);
2224 f->height = XINT (tem0);
2225 }
2226 if (!EQ (tem1, Qunbound))
2227 {
2228 CHECK_NUMBER (tem1, 0);
2229 f->width = XINT (tem1);
2230 }
2231 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2232 window_prompting |= USSize;
2233 else
2234 window_prompting |= PSize;
2235 }
2236
2237 f->output_data.win32->vertical_scroll_bar_extra
2238 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2239 ? 0
2240 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2241 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2242 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
2243 f->output_data.win32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2244 f->output_data.win32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2245
2246 tem0 = x_get_arg (parms, Qtop, 0, 0, number);
2247 tem1 = x_get_arg (parms, Qleft, 0, 0, number);
2248 tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
2249 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2250 {
2251 if (EQ (tem0, Qminus))
2252 {
2253 f->output_data.win32->top_pos = 0;
2254 window_prompting |= YNegative;
2255 }
2256 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
2257 && CONSP (XCONS (tem0)->cdr)
2258 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2259 {
2260 f->output_data.win32->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
2261 window_prompting |= YNegative;
2262 }
2263 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
2264 && CONSP (XCONS (tem0)->cdr)
2265 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2266 {
2267 f->output_data.win32->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
2268 }
2269 else if (EQ (tem0, Qunbound))
2270 f->output_data.win32->top_pos = 0;
2271 else
2272 {
2273 CHECK_NUMBER (tem0, 0);
2274 f->output_data.win32->top_pos = XINT (tem0);
2275 if (f->output_data.win32->top_pos < 0)
2276 window_prompting |= YNegative;
2277 }
2278
2279 if (EQ (tem1, Qminus))
2280 {
2281 f->output_data.win32->left_pos = 0;
2282 window_prompting |= XNegative;
2283 }
2284 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
2285 && CONSP (XCONS (tem1)->cdr)
2286 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2287 {
2288 f->output_data.win32->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
2289 window_prompting |= XNegative;
2290 }
2291 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
2292 && CONSP (XCONS (tem1)->cdr)
2293 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2294 {
2295 f->output_data.win32->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
2296 }
2297 else if (EQ (tem1, Qunbound))
2298 f->output_data.win32->left_pos = 0;
2299 else
2300 {
2301 CHECK_NUMBER (tem1, 0);
2302 f->output_data.win32->left_pos = XINT (tem1);
2303 if (f->output_data.win32->left_pos < 0)
2304 window_prompting |= XNegative;
2305 }
2306
2307 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2308 window_prompting |= USPosition;
2309 else
2310 window_prompting |= PPosition;
2311 }
2312
2313 return window_prompting;
2314 }
2315
2316 \f
2317
2318 extern LRESULT CALLBACK win32_wnd_proc ();
2319
2320 BOOL
2321 win32_init_class (hinst)
2322 HINSTANCE hinst;
2323 {
2324 WNDCLASS wc;
2325
2326 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
2327 wc.lpfnWndProc = (WNDPROC) win32_wnd_proc;
2328 wc.cbClsExtra = 0;
2329 wc.cbWndExtra = WND_EXTRA_BYTES;
2330 wc.hInstance = hinst;
2331 wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
2332 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
2333 wc.hbrBackground = NULL; // GetStockObject (WHITE_BRUSH);
2334 wc.lpszMenuName = NULL;
2335 wc.lpszClassName = EMACS_CLASS;
2336
2337 return (RegisterClass (&wc));
2338 }
2339
2340 HWND
2341 win32_createscrollbar (f, bar)
2342 struct frame *f;
2343 struct scroll_bar * bar;
2344 {
2345 return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
2346 /* Position and size of scroll bar. */
2347 XINT(bar->left), XINT(bar->top),
2348 XINT(bar->width), XINT(bar->height),
2349 FRAME_WIN32_WINDOW (f),
2350 NULL,
2351 hinst,
2352 NULL));
2353 }
2354
2355 void
2356 win32_createwindow (f)
2357 struct frame *f;
2358 {
2359 HWND hwnd;
2360
2361 /* Do first time app init */
2362
2363 if (!hprevinst)
2364 {
2365 win32_init_class (hinst);
2366 }
2367
2368 FRAME_WIN32_WINDOW (f) = hwnd = CreateWindow (EMACS_CLASS,
2369 f->namebuf,
2370 f->output_data.win32->dwStyle | WS_CLIPCHILDREN,
2371 f->output_data.win32->left_pos,
2372 f->output_data.win32->top_pos,
2373 PIXEL_WIDTH (f),
2374 PIXEL_HEIGHT (f),
2375 NULL,
2376 NULL,
2377 hinst,
2378 NULL);
2379
2380 if (hwnd)
2381 {
2382 SetWindowLong (hwnd, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.win32->font));
2383 SetWindowLong (hwnd, WND_Y_UNITS_INDEX, f->output_data.win32->line_height);
2384 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, f->output_data.win32->background_pixel);
2385 }
2386 }
2387
2388 DWORD
2389 win_msg_worker (dw)
2390 DWORD dw;
2391 {
2392 MSG msg;
2393
2394 /* Ensure our message queue is created */
2395
2396 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2397
2398 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0);
2399
2400 while (GetMessage (&msg, NULL, 0, 0))
2401 {
2402 if (msg.hwnd == NULL)
2403 {
2404 switch (msg.message)
2405 {
2406 case WM_EMACS_CREATEWINDOW:
2407 win32_createwindow ((struct frame *) msg.wParam);
2408 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0);
2409 break;
2410 case WM_EMACS_CREATESCROLLBAR:
2411 {
2412 HWND hwnd = win32_createscrollbar ((struct frame *) msg.wParam,
2413 (struct scroll_bar *) msg.lParam);
2414 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, (WPARAM)hwnd, 0);
2415 }
2416 break;
2417 case WM_EMACS_KILL:
2418 return (0);
2419 }
2420 }
2421 else
2422 {
2423 DispatchMessage (&msg);
2424 }
2425 }
2426
2427 return (0);
2428 }
2429
2430 HDC
2431 map_mode (hdc)
2432 HDC hdc;
2433 {
2434 if (hdc)
2435 {
2436 #if 0
2437 /* Make mapping mode be in 1/20 of point */
2438
2439 SetMapMode (hdc, MM_ANISOTROPIC);
2440 SetWindowExtEx (hdc, 1440, 1440, NULL);
2441 SetViewportExtEx (hdc,
2442 GetDeviceCaps (hdc, LOGPIXELSX),
2443 GetDeviceCaps (hdc, LOGPIXELSY),
2444 NULL);
2445 #endif
2446 }
2447 return (hdc);
2448 }
2449
2450 /* Convert between the modifier bits Win32 uses and the modifier bits
2451 Emacs uses. */
2452 unsigned int
2453 win32_get_modifiers ()
2454 {
2455 return (((GetKeyState (VK_SHIFT)&0x8000) ? shift_modifier : 0) |
2456 ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier : 0) |
2457 ((GetKeyState (VK_MENU)&0x8000) ? meta_modifier : 0));
2458 }
2459
2460 void
2461 my_post_msg (wmsg, hwnd, msg, wParam, lParam)
2462 Win32Msg * wmsg;
2463 HWND hwnd;
2464 UINT msg;
2465 WPARAM wParam;
2466 LPARAM lParam;
2467 {
2468 wmsg->msg.hwnd = hwnd;
2469 wmsg->msg.message = msg;
2470 wmsg->msg.wParam = wParam;
2471 wmsg->msg.lParam = lParam;
2472 wmsg->msg.time = GetMessageTime ();
2473
2474 post_msg (wmsg);
2475 }
2476
2477 /* Main window procedure */
2478
2479 extern char *lispy_function_keys[];
2480
2481 LRESULT CALLBACK
2482 win32_wnd_proc (hwnd, msg, wParam, lParam)
2483 HWND hwnd;
2484 UINT msg;
2485 WPARAM wParam;
2486 LPARAM lParam;
2487 {
2488 struct frame *f;
2489 LRESULT ret = 1;
2490 struct win32_display_info *dpyinfo = &one_win32_display_info;
2491 Win32Msg wmsg;
2492
2493 switch (msg)
2494 {
2495 case WM_ERASEBKGND:
2496 {
2497 HBRUSH hb;
2498 HANDLE oldobj;
2499 RECT rect;
2500
2501 GetClientRect (hwnd, &rect);
2502
2503 hb = CreateSolidBrush (GetWindowLong (hwnd, WND_BACKGROUND_INDEX));
2504
2505 oldobj = SelectObject ((HDC)wParam, hb);
2506
2507 FillRect((HDC)wParam, &rect, hb);
2508
2509 SelectObject((HDC)wParam, oldobj);
2510
2511 DeleteObject (hb);
2512
2513 return (0);
2514 }
2515 case WM_PAINT:
2516 {
2517 PAINTSTRUCT paintStruct;
2518
2519 BeginPaint (hwnd, &paintStruct);
2520 wmsg.rect = paintStruct.rcPaint;
2521 EndPaint (hwnd, &paintStruct);
2522
2523 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2524
2525 return (0);
2526 }
2527
2528 case WM_CREATE:
2529 {
2530 HDC hdc = my_get_dc (hwnd);
2531
2532 /* Make mapping mode be in 1/20 of point */
2533
2534 map_mode (hdc);
2535
2536 ReleaseDC (hwnd, hdc);
2537 }
2538
2539 return (0);
2540 case WM_KEYDOWN:
2541 case WM_SYSKEYDOWN:
2542 #if 0
2543 if (! ((wParam >= VK_BACK && wParam <= VK_TAB)
2544 || (wParam >= VK_CLEAR && wParam <= VK_RETURN)
2545 || (wParam == VK_ESCAPE)
2546 || (wParam >= VK_PRIOR && wParam <= VK_HELP)
2547 || (wParam >= VK_LWIN && wParam <= VK_APPS)
2548 || (wParam >= VK_NUMPAD0 && wParam <= VK_F24)
2549 || (wParam >= VK_NUMLOCK && wParam <= VK_SCROLL)
2550 || (wParam >= VK_ATTN && wParam <= VK_OEM_CLEAR)
2551 || !TranslateMessage (&msg1)))
2552 {
2553 goto dflt;
2554 }
2555 #endif
2556
2557 /* Check for special characters since translate message
2558 seems to always indicate true. */
2559
2560 if (wParam == VK_MENU
2561 || wParam == VK_SHIFT
2562 || wParam == VK_CONTROL
2563 || wParam == VK_CAPITAL)
2564 break;
2565
2566 /* Anything we do not have a name for needs to be translated or
2567 returned as ascii keystroke. */
2568
2569 if (lispy_function_keys[wParam] == 0)
2570 {
2571 MSG msg1;
2572
2573 msg1.hwnd = hwnd;
2574 msg1.message = msg;
2575 msg1.wParam = wParam;
2576 msg1.lParam = lParam;
2577
2578 if (TranslateMessage (&msg1))
2579 break;
2580 else
2581 msg = WM_CHAR;
2582 }
2583
2584 /* Fall through */
2585
2586 case WM_SYSCHAR:
2587 case WM_CHAR:
2588 wmsg.dwModifiers = win32_get_modifiers ();
2589
2590 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2591 break;
2592 case WM_LBUTTONDOWN:
2593 case WM_LBUTTONUP:
2594 case WM_MBUTTONDOWN:
2595 case WM_MBUTTONUP:
2596 case WM_RBUTTONDOWN:
2597 case WM_RBUTTONUP:
2598 {
2599 BOOL up;
2600
2601 if (parse_button (msg, NULL, &up))
2602 {
2603 if (up) ReleaseCapture ();
2604 else SetCapture (hwnd);
2605 }
2606 }
2607
2608 wmsg.dwModifiers = win32_get_modifiers ();
2609
2610 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2611 goto dflt;
2612 case WM_MOUSEMOVE:
2613 case WM_MOVE:
2614 case WM_SIZE:
2615 case WM_SETFOCUS:
2616 case WM_KILLFOCUS:
2617 case WM_CLOSE:
2618 case WM_VSCROLL:
2619 case WM_SYSCOMMAND:
2620 case WM_COMMAND:
2621 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2622 goto dflt;
2623 case WM_WINDOWPOSCHANGING:
2624 {
2625 WINDOWPLACEMENT wp;
2626 LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
2627
2628 GetWindowPlacement (hwnd, &wp);
2629
2630 if (wp.showCmd != SW_SHOWMINIMIZED && ! (lppos->flags & SWP_NOSIZE))
2631 {
2632 RECT rect;
2633 int wdiff;
2634 int hdiff;
2635 DWORD dwXUnits;
2636 DWORD dwYUnits;
2637 RECT wr;
2638
2639 GetWindowRect (hwnd, &wr);
2640
2641 enter_crit ();
2642
2643 dwXUnits = GetWindowLong (hwnd, WND_X_UNITS_INDEX);
2644 dwYUnits = GetWindowLong (hwnd, WND_Y_UNITS_INDEX);
2645
2646 leave_crit ();
2647
2648 memset (&rect, 0, sizeof (rect));
2649 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
2650 GetMenu (hwnd) != NULL);
2651
2652 /* All windows have an extra pixel so subtract 1 */
2653
2654 wdiff = (lppos->cx - (rect.right - rect.left) - 0) % dwXUnits;
2655 hdiff = (lppos->cy - (rect.bottom - rect.top) - 0) % dwYUnits;
2656
2657 if (wdiff || hdiff)
2658 {
2659 /* For right/bottom sizing we can just fix the sizes.
2660 However for top/left sizing we will need to fix the X
2661 and Y positions as well. */
2662
2663 lppos->cx -= wdiff;
2664 lppos->cy -= hdiff;
2665
2666 if (wp.showCmd != SW_SHOWMAXIMIZED
2667 && ! (lppos->flags & SWP_NOMOVE))
2668 {
2669 if (lppos->x != wr.left || lppos->y != wr.top)
2670 {
2671 lppos->x += wdiff;
2672 lppos->y += hdiff;
2673 }
2674 else
2675 {
2676 lppos->flags |= SWP_NOMOVE;
2677 }
2678 }
2679
2680 ret = 0;
2681 }
2682 }
2683 }
2684
2685 if (ret == 0) return (0);
2686
2687 goto dflt;
2688 case WM_EMACS_DESTROYWINDOW:
2689 DestroyWindow ((HWND) wParam);
2690 break;
2691 default:
2692 dflt:
2693 return DefWindowProc (hwnd, msg, wParam, lParam);
2694 }
2695
2696 return (1);
2697 }
2698
2699 void
2700 my_create_window (f)
2701 struct frame * f;
2702 {
2703 MSG msg;
2704
2705 PostThreadMessage (dwWinThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0);
2706 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
2707 }
2708
2709 /* Create and set up the win32 window for frame F. */
2710
2711 static void
2712 win32_window (f, window_prompting, minibuffer_only)
2713 struct frame *f;
2714 long window_prompting;
2715 int minibuffer_only;
2716 {
2717 BLOCK_INPUT;
2718
2719 /* Use the resource name as the top-level window name
2720 for looking up resources. Make a non-Lisp copy
2721 for the window manager, so GC relocation won't bother it.
2722
2723 Elsewhere we specify the window name for the window manager. */
2724
2725 {
2726 char *str = (char *) XSTRING (Vx_resource_name)->data;
2727 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2728 strcpy (f->namebuf, str);
2729 }
2730
2731 my_create_window (f);
2732
2733 validate_x_resource_name ();
2734
2735 /* x_set_name normally ignores requests to set the name if the
2736 requested name is the same as the current name. This is the one
2737 place where that assumption isn't correct; f->name is set, but
2738 the server hasn't been told. */
2739 {
2740 Lisp_Object name;
2741 int explicit = f->explicit_name;
2742
2743 f->explicit_name = 0;
2744 name = f->name;
2745 f->name = Qnil;
2746 x_set_name (f, name, explicit);
2747 }
2748
2749 UNBLOCK_INPUT;
2750
2751 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
2752 initialize_frame_menubar (f);
2753
2754 if (FRAME_WIN32_WINDOW (f) == 0)
2755 error ("Unable to create window");
2756 }
2757
2758 /* Handle the icon stuff for this window. Perhaps later we might
2759 want an x_set_icon_position which can be called interactively as
2760 well. */
2761
2762 static void
2763 x_icon (f, parms)
2764 struct frame *f;
2765 Lisp_Object parms;
2766 {
2767 Lisp_Object icon_x, icon_y;
2768
2769 /* Set the position of the icon. Note that win95 groups all
2770 icons in the tray. */
2771 icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
2772 icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
2773 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2774 {
2775 CHECK_NUMBER (icon_x, 0);
2776 CHECK_NUMBER (icon_y, 0);
2777 }
2778 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2779 error ("Both left and top icon corners of icon must be specified");
2780
2781 BLOCK_INPUT;
2782
2783 if (! EQ (icon_x, Qunbound))
2784 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2785
2786 UNBLOCK_INPUT;
2787 }
2788
2789 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2790 1, 1, 0,
2791 "Make a new window, which is called a \"frame\" in Emacs terms.\n\
2792 Returns an Emacs frame object.\n\
2793 ALIST is an alist of frame parameters.\n\
2794 If the parameters specify that the frame should not have a minibuffer,\n\
2795 and do not specify a specific minibuffer window to use,\n\
2796 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
2797 be shared by the new frame.\n\
2798 \n\
2799 This function is an internal primitive--use `make-frame' instead.")
2800 (parms)
2801 Lisp_Object parms;
2802 {
2803 struct frame *f;
2804 Lisp_Object frame, tem;
2805 Lisp_Object name;
2806 int minibuffer_only = 0;
2807 long window_prompting = 0;
2808 int width, height;
2809 int count = specpdl_ptr - specpdl;
2810 struct gcpro gcpro1;
2811 Lisp_Object display;
2812 struct win32_display_info *dpyinfo;
2813 Lisp_Object parent;
2814 struct kboard *kb;
2815
2816 /* Use this general default value to start with
2817 until we know if this frame has a specified name. */
2818 Vx_resource_name = Vinvocation_name;
2819
2820 display = x_get_arg (parms, Qdisplay, 0, 0, string);
2821 if (EQ (display, Qunbound))
2822 display = Qnil;
2823 dpyinfo = check_x_display_info (display);
2824 #ifdef MULTI_KBOARD
2825 kb = dpyinfo->kboard;
2826 #else
2827 kb = &the_only_kboard;
2828 #endif
2829
2830 name = x_get_arg (parms, Qname, "title", "Title", string);
2831 if (!STRINGP (name)
2832 && ! EQ (name, Qunbound)
2833 && ! NILP (name))
2834 error ("Invalid frame name--not a string or nil");
2835
2836 if (STRINGP (name))
2837 Vx_resource_name = name;
2838
2839 /* See if parent window is specified. */
2840 parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
2841 if (EQ (parent, Qunbound))
2842 parent = Qnil;
2843 if (! NILP (parent))
2844 CHECK_NUMBER (parent, 0);
2845
2846 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
2847 if (EQ (tem, Qnone) || NILP (tem))
2848 f = make_frame_without_minibuffer (Qnil, kb, display);
2849 else if (EQ (tem, Qonly))
2850 {
2851 f = make_minibuffer_frame ();
2852 minibuffer_only = 1;
2853 }
2854 else if (WINDOWP (tem))
2855 f = make_frame_without_minibuffer (tem, kb, display);
2856 else
2857 f = make_frame (1);
2858
2859 /* Note that Windows does support scroll bars. */
2860 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
2861
2862 XSETFRAME (frame, f);
2863 GCPRO1 (frame);
2864
2865 f->output_method = output_win32;
2866 f->output_data.win32 = (struct win32_output *) xmalloc (sizeof (struct win32_output));
2867 bzero (f->output_data.win32, sizeof (struct win32_output));
2868
2869 /* FRAME_WIN32_DISPLAY_INFO (f) = dpyinfo; */
2870 #ifdef MULTI_KBOARD
2871 FRAME_KBOARD (f) = kb;
2872 #endif
2873
2874 /* Specify the parent under which to make this window. */
2875
2876 if (!NILP (parent))
2877 {
2878 f->output_data.win32->parent_desc = (Window) parent;
2879 f->output_data.win32->explicit_parent = 1;
2880 }
2881 else
2882 {
2883 f->output_data.win32->parent_desc = FRAME_WIN32_DISPLAY_INFO (f)->root_window;
2884 f->output_data.win32->explicit_parent = 0;
2885 }
2886
2887 /* Note that the frame has no physical cursor right now. */
2888 f->phys_cursor_x = -1;
2889
2890 /* Set the name; the functions to which we pass f expect the name to
2891 be set. */
2892 if (EQ (name, Qunbound) || NILP (name))
2893 {
2894 f->name = build_string (dpyinfo->win32_id_name);
2895 f->explicit_name = 0;
2896 }
2897 else
2898 {
2899 f->name = name;
2900 f->explicit_name = 1;
2901 /* use the frame's title when getting resources for this frame. */
2902 specbind (Qx_resource_name, name);
2903 }
2904
2905 /* Extract the window parameters from the supplied values
2906 that are needed to determine window geometry. */
2907 {
2908 Lisp_Object font;
2909
2910 font = x_get_arg (parms, Qfont, "font", "Font", string);
2911 BLOCK_INPUT;
2912 /* First, try whatever font the caller has specified. */
2913 if (STRINGP (font))
2914 font = x_new_font (f, XSTRING (font)->data);
2915 #if 0
2916 /* Try out a font which we hope has bold and italic variations. */
2917 if (!STRINGP (font))
2918 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
2919 if (! STRINGP (font))
2920 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
2921 if (! STRINGP (font))
2922 /* This was formerly the first thing tried, but it finds too many fonts
2923 and takes too long. */
2924 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
2925 /* If those didn't work, look for something which will at least work. */
2926 if (! STRINGP (font))
2927 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
2928 if (! STRINGP (font))
2929 font = x_new_font (f, "-*-system-medium-r-normal-*-*-200-*-*-c-120-*-*");
2930 #endif
2931 if (! STRINGP (font))
2932 font = x_new_font (f, "-*-terminal-medium-r-normal-*-*-180-*-*-c-120-*-*");
2933 UNBLOCK_INPUT;
2934 if (! STRINGP (font))
2935 font = build_string ("-*-system");
2936
2937 x_default_parameter (f, parms, Qfont, font,
2938 "font", "Font", string);
2939 }
2940
2941 x_default_parameter (f, parms, Qborder_width, make_number (2),
2942 "borderwidth", "BorderWidth", number);
2943 /* This defaults to 2 in order to match xterm. We recognize either
2944 internalBorderWidth or internalBorder (which is what xterm calls
2945 it). */
2946 if (NILP (Fassq (Qinternal_border_width, parms)))
2947 {
2948 Lisp_Object value;
2949
2950 value = x_get_arg (parms, Qinternal_border_width,
2951 "internalBorder", "BorderWidth", number);
2952 if (! EQ (value, Qunbound))
2953 parms = Fcons (Fcons (Qinternal_border_width, value),
2954 parms);
2955 }
2956 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
2957 "internalBorderWidth", "BorderWidth", number);
2958 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
2959 "verticalScrollBars", "ScrollBars", boolean);
2960
2961 /* Also do the stuff which must be set before the window exists. */
2962 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
2963 "foreground", "Foreground", string);
2964 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
2965 "background", "Background", string);
2966 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
2967 "pointerColor", "Foreground", string);
2968 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
2969 "cursorColor", "Foreground", string);
2970 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
2971 "borderColor", "BorderColor", string);
2972
2973 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
2974 "menuBar", "MenuBar", number);
2975 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
2976 "scrollBarWidth", "ScrollBarWidth", number);
2977
2978 f->output_data.win32->dwStyle = WS_OVERLAPPEDWINDOW;
2979 f->output_data.win32->parent_desc = FRAME_WIN32_DISPLAY_INFO (f)->root_window;
2980 window_prompting = x_figure_window_size (f, parms);
2981
2982 if (window_prompting & XNegative)
2983 {
2984 if (window_prompting & YNegative)
2985 f->output_data.win32->win_gravity = SouthEastGravity;
2986 else
2987 f->output_data.win32->win_gravity = NorthEastGravity;
2988 }
2989 else
2990 {
2991 if (window_prompting & YNegative)
2992 f->output_data.win32->win_gravity = SouthWestGravity;
2993 else
2994 f->output_data.win32->win_gravity = NorthWestGravity;
2995 }
2996
2997 f->output_data.win32->size_hint_flags = window_prompting;
2998
2999 win32_window (f, window_prompting, minibuffer_only);
3000 x_icon (f, parms);
3001 init_frame_faces (f);
3002
3003 /* We need to do this after creating the window, so that the
3004 icon-creation functions can say whose icon they're describing. */
3005 x_default_parameter (f, parms, Qicon_type, Qnil,
3006 "bitmapIcon", "BitmapIcon", symbol);
3007
3008 x_default_parameter (f, parms, Qauto_raise, Qnil,
3009 "autoRaise", "AutoRaiseLower", boolean);
3010 x_default_parameter (f, parms, Qauto_lower, Qnil,
3011 "autoLower", "AutoRaiseLower", boolean);
3012 x_default_parameter (f, parms, Qcursor_type, Qbox,
3013 "cursorType", "CursorType", symbol);
3014
3015 /* Dimensions, especially f->height, must be done via change_frame_size.
3016 Change will not be effected unless different from the current
3017 f->height. */
3018 width = f->width;
3019 height = f->height;
3020 f->height = f->width = 0;
3021 change_frame_size (f, height, width, 1, 0);
3022
3023 /* Tell the server what size and position, etc, we want,
3024 and how badly we want them. */
3025 BLOCK_INPUT;
3026 x_wm_set_size_hint (f, window_prompting, 0);
3027 UNBLOCK_INPUT;
3028
3029 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
3030 f->no_split = minibuffer_only || EQ (tem, Qt);
3031
3032 UNGCPRO;
3033
3034 /* It is now ok to make the frame official
3035 even if we get an error below.
3036 And the frame needs to be on Vframe_list
3037 or making it visible won't work. */
3038 Vframe_list = Fcons (frame, Vframe_list);
3039
3040 /* Now that the frame is official, it counts as a reference to
3041 its display. */
3042 FRAME_WIN32_DISPLAY_INFO (f)->reference_count++;
3043
3044 /* Make the window appear on the frame and enable display,
3045 unless the caller says not to. However, with explicit parent,
3046 Emacs cannot control visibility, so don't try. */
3047 if (! f->output_data.win32->explicit_parent)
3048 {
3049 Lisp_Object visibility;
3050
3051 visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
3052 if (EQ (visibility, Qunbound))
3053 visibility = Qt;
3054
3055 if (EQ (visibility, Qicon))
3056 x_iconify_frame (f);
3057 else if (! NILP (visibility))
3058 x_make_frame_visible (f);
3059 else
3060 /* Must have been Qnil. */
3061 ;
3062 }
3063
3064 return unbind_to (count, frame);
3065 }
3066
3067 /* FRAME is used only to get a handle on the X display. We don't pass the
3068 display info directly because we're called from frame.c, which doesn't
3069 know about that structure. */
3070 Lisp_Object
3071 x_get_focus_frame (frame)
3072 struct frame *frame;
3073 {
3074 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (frame);
3075 Lisp_Object xfocus;
3076 if (! dpyinfo->win32_focus_frame)
3077 return Qnil;
3078
3079 XSETFRAME (xfocus, dpyinfo->win32_focus_frame);
3080 return xfocus;
3081 }
3082
3083 DEFUN ("focus-frame", Ffocus_frame, Sfocus_frame, 1, 1, 0,
3084 "Set the focus on FRAME.")
3085 (frame)
3086 Lisp_Object frame;
3087 {
3088 CHECK_LIVE_FRAME (frame, 0);
3089
3090 if (FRAME_WIN32_P (XFRAME (frame)))
3091 {
3092 BLOCK_INPUT;
3093 x_focus_on_frame (XFRAME (frame));
3094 UNBLOCK_INPUT;
3095 return frame;
3096 }
3097
3098 return Qnil;
3099 }
3100
3101 DEFUN ("unfocus-frame", Funfocus_frame, Sunfocus_frame, 0, 0, 0,
3102 "If a frame has been focused, release it.")
3103 ()
3104 {
3105 if (FRAME_WIN32_P (selected_frame))
3106 {
3107 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (selected_frame);
3108
3109 if (dpyinfo->win32_focus_frame)
3110 {
3111 BLOCK_INPUT;
3112 x_unfocus_frame (dpyinfo->win32_focus_frame);
3113 UNBLOCK_INPUT;
3114 }
3115 }
3116
3117 return Qnil;
3118 }
3119 \f
3120 XFontStruct
3121 *win32_load_font (dpyinfo,name)
3122 struct win32_display_info *dpyinfo;
3123 char * name;
3124 {
3125 XFontStruct * font = NULL;
3126 BOOL ok;
3127
3128 {
3129 LOGFONT lf;
3130
3131 if (!name || !x_to_win32_font(name, &lf))
3132 return (NULL);
3133
3134 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
3135
3136 if (!font) return (NULL);
3137
3138 BLOCK_INPUT;
3139
3140 font->hfont = CreateFontIndirect(&lf);
3141 }
3142
3143 if (font->hfont == NULL)
3144 {
3145 ok = FALSE;
3146 }
3147 else
3148 {
3149 HDC hdc;
3150 HANDLE oldobj;
3151
3152 hdc = my_get_dc (dpyinfo->root_window);
3153
3154 oldobj = SelectObject (hdc, font->hfont);
3155
3156 ok = GetTextMetrics (hdc, &font->tm);
3157
3158 SelectObject (hdc, oldobj);
3159
3160 ReleaseDC (dpyinfo->root_window, hdc);
3161 }
3162
3163 UNBLOCK_INPUT;
3164
3165 if (ok) return (font);
3166
3167 win32_unload_font(dpyinfo, font);
3168 return (NULL);
3169 }
3170
3171 void
3172 win32_unload_font (dpyinfo, font)
3173 struct win32_display_info *dpyinfo;
3174 XFontStruct * font;
3175 {
3176 if (font)
3177 {
3178 if (font->hfont) DeleteObject(font->hfont);
3179 xfree (font);
3180 }
3181 }
3182
3183 /* The font conversion stuff between x and win32 */
3184
3185 /* X font string is as follows (from faces.el)
3186 * (let ((- "[-?]")
3187 * (foundry "[^-]+")
3188 * (family "[^-]+")
3189 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
3190 * (weight\? "\\([^-]*\\)") ; 1
3191 * (slant "\\([ior]\\)") ; 2
3192 * (slant\? "\\([^-]?\\)") ; 2
3193 * (swidth "\\([^-]*\\)") ; 3
3194 * (adstyle "[^-]*") ; 4
3195 * (pixelsize "[0-9]+")
3196 * (pointsize "[0-9][0-9]+")
3197 * (resx "[0-9][0-9]+")
3198 * (resy "[0-9][0-9]+")
3199 * (spacing "[cmp?*]")
3200 * (avgwidth "[0-9]+")
3201 * (registry "[^-]+")
3202 * (encoding "[^-]+")
3203 * )
3204 * (setq x-font-regexp
3205 * (concat "\\`\\*?[-?*]"
3206 * foundry - family - weight\? - slant\? - swidth - adstyle -
3207 * pixelsize - pointsize - resx - resy - spacing - registry -
3208 * encoding "[-?*]\\*?\\'"
3209 * ))
3210 * (setq x-font-regexp-head
3211 * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
3212 * "\\([-*?]\\|\\'\\)"))
3213 * (setq x-font-regexp-slant (concat - slant -))
3214 * (setq x-font-regexp-weight (concat - weight -))
3215 * nil)
3216 */
3217
3218 #define FONT_START "[-?]"
3219 #define FONT_FOUNDRY "[^-]+"
3220 #define FONT_FAMILY "\\([^-]+\\)" /* 1 */
3221 #define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
3222 #define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
3223 #define FONT_SLANT "\\([ior]\\)" /* 3 */
3224 #define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
3225 #define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
3226 #define FONT_ADSTYLE "[^-]*"
3227 #define FONT_PIXELSIZE "[^-]*"
3228 #define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
3229 #define FONT_RESX "[0-9][0-9]+"
3230 #define FONT_RESY "[0-9][0-9]+"
3231 #define FONT_SPACING "[cmp?*]"
3232 #define FONT_AVGWIDTH "[0-9]+"
3233 #define FONT_REGISTRY "[^-]+"
3234 #define FONT_ENCODING "[^-]+"
3235
3236 #define FONT_REGEXP ("\\`\\*?[-?*]" \
3237 FONT_FOUNDRY "-" \
3238 FONT_FAMILY "-" \
3239 FONT_WEIGHT_Q "-" \
3240 FONT_SLANT_Q "-" \
3241 FONT_SWIDTH "-" \
3242 FONT_ADSTYLE "-" \
3243 FONT_PIXELSIZE "-" \
3244 FONT_POINTSIZE "-" \
3245 "[-?*]\\|\\'")
3246
3247 #define FONT_REGEXP_HEAD ("\\`[-?*]" \
3248 FONT_FOUNDRY "-" \
3249 FONT_FAMILY "-" \
3250 FONT_WEIGHT_Q "-" \
3251 FONT_SLANT_Q \
3252 "\\([-*?]\\|\\'\\)")
3253
3254 #define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
3255 #define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
3256
3257 LONG
3258 x_to_win32_weight (lpw)
3259 char * lpw;
3260 {
3261 if (!lpw) return (FW_DONTCARE);
3262
3263 if (stricmp (lpw, "bold") == 0)
3264 return (FW_BOLD);
3265 else if (stricmp (lpw, "demibold") == 0)
3266 return (FW_SEMIBOLD);
3267 else if (stricmp (lpw, "medium") == 0)
3268 return (FW_MEDIUM);
3269 else if (stricmp (lpw, "normal") == 0)
3270 return (FW_NORMAL);
3271 else
3272 return (FW_DONTCARE);
3273 }
3274
3275 char *
3276 win32_to_x_weight (fnweight)
3277 int fnweight;
3278 {
3279 if (fnweight >= FW_BOLD)
3280 return ("bold");
3281 else if (fnweight >= FW_SEMIBOLD)
3282 return ("demibold");
3283 else if (fnweight >= FW_MEDIUM)
3284 return ("medium");
3285 else
3286 return ("normal");
3287 }
3288
3289 BOOL
3290 win32_to_x_font (lplogfont, lpxstr, len)
3291 LOGFONT * lplogfont;
3292 char * lpxstr;
3293 int len;
3294 {
3295 if (!lpxstr) return (FALSE);
3296
3297 if (lplogfont)
3298 {
3299 int height = (lplogfont->lfHeight * 1440)
3300 / one_win32_display_info.height_in;
3301 int width = (lplogfont->lfWidth * 1440)
3302 / one_win32_display_info.width_in;
3303
3304 height = abs (height);
3305 _snprintf (lpxstr, len - 1,
3306 "-*-%s-%s-%c-%s-%s-*-%d-*-*-%c-%d-*-*-",
3307 lplogfont->lfFaceName,
3308 win32_to_x_weight (lplogfont->lfWeight),
3309 lplogfont->lfItalic ? 'i' : 'r',
3310 "*", "*",
3311 height,
3312 ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH) ? 'p' : 'c',
3313 width);
3314 }
3315 else
3316 {
3317 strncpy (lpxstr, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-", len - 1);
3318 }
3319
3320 lpxstr[len - 1] = 0; /* just to be sure */
3321 return (TRUE);
3322 }
3323
3324 BOOL
3325 x_to_win32_font (lpxstr, lplogfont)
3326 char * lpxstr;
3327 LOGFONT * lplogfont;
3328 {
3329 if (!lplogfont) return (FALSE);
3330
3331 memset (lplogfont, 0, sizeof (*lplogfont));
3332
3333 lplogfont->lfCharSet = OEM_CHARSET;
3334 lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
3335 lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
3336 lplogfont->lfQuality = DEFAULT_QUALITY;
3337
3338 if (lpxstr && *lpxstr == '-') lpxstr++;
3339
3340 {
3341 int fields;
3342 char name[50], weight[20], slant, pitch, height[10], width[10];
3343
3344 fields = (lpxstr
3345 ? sscanf (lpxstr,
3346 "%*[^-]-%[^-]-%[^-]-%c-%*[^-]-%*[^-]-%*[^-]-%[^-]-%*[^-]-%*[^-]-%c-%[^-]",
3347 name, weight, &slant, height, &pitch, width)
3348 : 0);
3349
3350 if (fields == EOF) return (FALSE);
3351
3352 if (fields > 0 && name[0] != '*')
3353 {
3354 strncpy (lplogfont->lfFaceName, name, LF_FACESIZE);
3355 }
3356 else
3357 {
3358 lplogfont->lfFaceName[0] = 0;
3359 }
3360
3361 fields--;
3362
3363 lplogfont->lfWeight = x_to_win32_weight((fields > 0 ? weight : ""));
3364
3365 fields--;
3366
3367 lplogfont->lfItalic = (fields > 0 && slant == 'i');
3368
3369 fields--;
3370
3371 if (fields > 0 && height[0] != '*')
3372 lplogfont->lfHeight = (atoi (height) * one_win32_display_info.height_in) / 1440;
3373
3374 fields--;
3375
3376 lplogfont->lfPitchAndFamily = (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
3377
3378 fields--;
3379
3380 if (fields > 0 && width[0] != '*')
3381 lplogfont->lfWidth = (atoi (width) * one_win32_display_info.width_in) / 1440;
3382 }
3383
3384 return (TRUE);
3385 }
3386
3387 BOOL
3388 win32_font_match (lpszfont1, lpszfont2)
3389 char * lpszfont1;
3390 char * lpszfont2;
3391 {
3392 char * s1 = lpszfont1, *e1;
3393 char * s2 = lpszfont2, *e2;
3394
3395 if (s1 == NULL || s2 == NULL) return (FALSE);
3396
3397 if (*s1 == '-') s1++;
3398 if (*s2 == '-') s2++;
3399
3400 while (1)
3401 {
3402 int len1, len2;
3403
3404 e1 = strchr (s1, '-');
3405 e2 = strchr (s2, '-');
3406
3407 if (e1 == NULL || e2 == NULL) return (TRUE);
3408
3409 len1 = e1 - s1;
3410 len2 = e2 - s2;
3411
3412 if (*s1 != '*' && *s2 != '*'
3413 && (len1 != len2 || strnicmp (s1, s2, len1) != 0))
3414 return (FALSE);
3415
3416 s1 = e1 + 1;
3417 s2 = e2 + 1;
3418 }
3419 }
3420
3421 typedef struct enumfont_t
3422 {
3423 HDC hdc;
3424 int numFonts;
3425 XFontStruct *size_ref;
3426 Lisp_Object *pattern;
3427 Lisp_Object *head;
3428 Lisp_Object *tail;
3429 } enumfont_t;
3430
3431 int CALLBACK
3432 enum_font_cb2 (lplf, lptm, FontType, lpef)
3433 ENUMLOGFONT * lplf;
3434 NEWTEXTMETRIC * lptm;
3435 int FontType;
3436 enumfont_t * lpef;
3437 {
3438 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline
3439 || (lplf->elfLogFont.lfCharSet != ANSI_CHARSET && lplf->elfLogFont.lfCharSet != OEM_CHARSET))
3440 return (1);
3441
3442 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */
3443 {
3444 char buf[100];
3445
3446 if (!win32_to_x_font (lplf, buf, 100)) return (0);
3447
3448 if (NILP (*(lpef->pattern)) || win32_font_match (buf, XSTRING (*(lpef->pattern))->data))
3449 {
3450 *lpef->tail = Fcons (build_string (buf), Qnil);
3451 lpef->tail = &XCONS (*lpef->tail)->cdr;
3452 lpef->numFonts++;
3453 }
3454 }
3455
3456 return (1);
3457 }
3458
3459 int CALLBACK
3460 enum_font_cb1 (lplf, lptm, FontType, lpef)
3461 ENUMLOGFONT * lplf;
3462 NEWTEXTMETRIC * lptm;
3463 int FontType;
3464 enumfont_t * lpef;
3465 {
3466 return EnumFontFamilies (lpef->hdc,
3467 lplf->elfLogFont.lfFaceName,
3468 (FONTENUMPROC) enum_font_cb2,
3469 (LPARAM) lpef);
3470 }
3471
3472
3473 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 3, 0,
3474 "Return a list of the names of available fonts matching PATTERN.\n\
3475 If optional arguments FACE and FRAME are specified, return only fonts\n\
3476 the same size as FACE on FRAME.\n\
3477 \n\
3478 PATTERN is a string, perhaps with wildcard characters;\n\
3479 the * character matches any substring, and\n\
3480 the ? character matches any single character.\n\
3481 PATTERN is case-insensitive.\n\
3482 FACE is a face name--a symbol.\n\
3483 \n\
3484 The return value is a list of strings, suitable as arguments to\n\
3485 set-face-font.\n\
3486 \n\
3487 Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
3488 even if they match PATTERN and FACE.")
3489 (pattern, face, frame)
3490 Lisp_Object pattern, face, frame;
3491 {
3492 int num_fonts;
3493 char **names;
3494 XFontStruct *info;
3495 XFontStruct *size_ref;
3496 Lisp_Object namelist;
3497 Lisp_Object list;
3498 FRAME_PTR f;
3499 enumfont_t ef;
3500
3501 CHECK_STRING (pattern, 0);
3502 if (!NILP (face))
3503 CHECK_SYMBOL (face, 1);
3504
3505 f = check_x_frame (frame);
3506
3507 /* Determine the width standard for comparison with the fonts we find. */
3508
3509 if (NILP (face))
3510 size_ref = 0;
3511 else
3512 {
3513 int face_id;
3514
3515 /* Don't die if we get called with a terminal frame. */
3516 if (! FRAME_WIN32_P (f))
3517 error ("non-win32 frame used in `x-list-fonts'");
3518
3519 face_id = face_name_id_number (f, face);
3520
3521 if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
3522 || FRAME_PARAM_FACES (f) [face_id] == 0)
3523 size_ref = f->output_data.win32->font;
3524 else
3525 {
3526 size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
3527 if (size_ref == (XFontStruct *) (~0))
3528 size_ref = f->output_data.win32->font;
3529 }
3530 }
3531
3532 /* See if we cached the result for this particular query. */
3533 list = Fassoc (pattern,
3534 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->cdr);
3535
3536 /* We have info in the cache for this PATTERN. */
3537 if (!NILP (list))
3538 {
3539 Lisp_Object tem, newlist;
3540
3541 /* We have info about this pattern. */
3542 list = XCONS (list)->cdr;
3543
3544 if (size_ref == 0)
3545 return list;
3546
3547 BLOCK_INPUT;
3548
3549 /* Filter the cached info and return just the fonts that match FACE. */
3550 newlist = Qnil;
3551 for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
3552 {
3553 XFontStruct *thisinfo;
3554
3555 thisinfo = win32_load_font (FRAME_WIN32_DISPLAY_INFO (f), XSTRING (XCONS (tem)->car)->data);
3556
3557 if (thisinfo && same_size_fonts (thisinfo, size_ref))
3558 newlist = Fcons (XCONS (tem)->car, newlist);
3559
3560 win32_unload_font (FRAME_WIN32_DISPLAY_INFO (f), thisinfo);
3561 }
3562
3563 UNBLOCK_INPUT;
3564
3565 return newlist;
3566 }
3567
3568 BLOCK_INPUT;
3569
3570 namelist = Qnil;
3571 ef.pattern = &pattern;
3572 ef.tail = ef.head = &namelist;
3573 ef.numFonts = 0;
3574
3575 {
3576 ef.hdc = my_get_dc (FRAME_WIN32_WINDOW (f));
3577
3578 EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1, (LPARAM)&ef);
3579
3580 ReleaseDC (FRAME_WIN32_WINDOW (f), ef.hdc);
3581 }
3582
3583 UNBLOCK_INPUT;
3584
3585 if (ef.numFonts)
3586 {
3587 int i;
3588 Lisp_Object cur;
3589
3590 /* Make a list of all the fonts we got back.
3591 Store that in the font cache for the display. */
3592 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->cdr
3593 = Fcons (Fcons (pattern, namelist),
3594 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->cdr);
3595
3596 /* Make a list of the fonts that have the right width. */
3597 list = Qnil;
3598 cur=namelist;
3599 for (i = 0; i < ef.numFonts; i++)
3600 {
3601 int keeper;
3602
3603 if (!size_ref)
3604 keeper = 1;
3605 else
3606 {
3607 XFontStruct *thisinfo;
3608
3609 BLOCK_INPUT;
3610 thisinfo = win32_load_font (FRAME_WIN32_DISPLAY_INFO (f), XSTRING (Fcar (cur))->data);
3611
3612 keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
3613
3614 win32_unload_font (FRAME_WIN32_DISPLAY_INFO (f), thisinfo);
3615
3616 UNBLOCK_INPUT;
3617 }
3618 if (keeper)
3619 list = Fcons (build_string (XSTRING (Fcar (cur))->data), list);
3620
3621 cur = Fcdr (cur);
3622 }
3623 list = Fnreverse (list);
3624 }
3625
3626 return list;
3627 }
3628 \f
3629 DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
3630 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3631 If FRAME is omitted or nil, use the selected frame.")
3632 (color, frame)
3633 Lisp_Object color, frame;
3634 {
3635 COLORREF foo;
3636 FRAME_PTR f = check_x_frame (frame);
3637
3638 CHECK_STRING (color, 1);
3639
3640 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3641 return Qt;
3642 else
3643 return Qnil;
3644 }
3645
3646 DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
3647 "Return a description of the color named COLOR on frame FRAME.\n\
3648 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3649 These values appear to range from 0 to 65280 or 65535, depending\n\
3650 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3651 If FRAME is omitted or nil, use the selected frame.")
3652 (color, frame)
3653 Lisp_Object color, frame;
3654 {
3655 COLORREF foo;
3656 FRAME_PTR f = check_x_frame (frame);
3657
3658 CHECK_STRING (color, 1);
3659
3660 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3661 {
3662 Lisp_Object rgb[3];
3663
3664 rgb[0] = make_number (GetRValue (foo));
3665 rgb[1] = make_number (GetGValue (foo));
3666 rgb[2] = make_number (GetBValue (foo));
3667 return Flist (3, rgb);
3668 }
3669 else
3670 return Qnil;
3671 }
3672
3673 DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
3674 "Return t if the X display supports color.\n\
3675 The optional argument DISPLAY specifies which display to ask about.\n\
3676 DISPLAY should be either a frame or a display name (a string).\n\
3677 If omitted or nil, that stands for the selected frame's display.")
3678 (display)
3679 Lisp_Object display;
3680 {
3681 struct win32_display_info *dpyinfo = check_x_display_info (display);
3682
3683 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
3684 return Qnil;
3685
3686 return Qt;
3687 }
3688
3689 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3690 0, 1, 0,
3691 "Return t if the X display supports shades of gray.\n\
3692 Note that color displays do support shades of gray.\n\
3693 The optional argument DISPLAY specifies which display to ask about.\n\
3694 DISPLAY should be either a frame or a display name (a string).\n\
3695 If omitted or nil, that stands for the selected frame's display.")
3696 (display)
3697 Lisp_Object display;
3698 {
3699 struct win32_display_info *dpyinfo = check_x_display_info (display);
3700
3701 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
3702 return Qnil;
3703
3704 return Qt;
3705 }
3706
3707 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3708 0, 1, 0,
3709 "Returns the width in pixels of the X display DISPLAY.\n\
3710 The optional argument DISPLAY specifies which display to ask about.\n\
3711 DISPLAY should be either a frame or a display name (a string).\n\
3712 If omitted or nil, that stands for the selected frame's display.")
3713 (display)
3714 Lisp_Object display;
3715 {
3716 struct win32_display_info *dpyinfo = check_x_display_info (display);
3717
3718 return make_number (dpyinfo->width);
3719 }
3720
3721 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3722 Sx_display_pixel_height, 0, 1, 0,
3723 "Returns the height in pixels of the X display DISPLAY.\n\
3724 The optional argument DISPLAY specifies which display to ask about.\n\
3725 DISPLAY should be either a frame or a display name (a string).\n\
3726 If omitted or nil, that stands for the selected frame's display.")
3727 (display)
3728 Lisp_Object display;
3729 {
3730 struct win32_display_info *dpyinfo = check_x_display_info (display);
3731
3732 return make_number (dpyinfo->height);
3733 }
3734
3735 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3736 0, 1, 0,
3737 "Returns the number of bitplanes of the display DISPLAY.\n\
3738 The optional argument DISPLAY specifies which display to ask about.\n\
3739 DISPLAY should be either a frame or a display name (a string).\n\
3740 If omitted or nil, that stands for the selected frame's display.")
3741 (display)
3742 Lisp_Object display;
3743 {
3744 struct win32_display_info *dpyinfo = check_x_display_info (display);
3745
3746 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
3747 }
3748
3749 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3750 0, 1, 0,
3751 "Returns the number of color cells of the display DISPLAY.\n\
3752 The optional argument DISPLAY specifies which display to ask about.\n\
3753 DISPLAY should be either a frame or a display name (a string).\n\
3754 If omitted or nil, that stands for the selected frame's display.")
3755 (display)
3756 Lisp_Object display;
3757 {
3758 struct win32_display_info *dpyinfo = check_x_display_info (display);
3759 HDC hdc;
3760 int cap;
3761
3762 hdc = my_get_dc (dpyinfo->root_window);
3763
3764 cap = GetDeviceCaps (hdc,NUMCOLORS);
3765
3766 ReleaseDC (dpyinfo->root_window, hdc);
3767
3768 return make_number (cap);
3769 }
3770
3771 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3772 Sx_server_max_request_size,
3773 0, 1, 0,
3774 "Returns the maximum request size of the server of display DISPLAY.\n\
3775 The optional argument DISPLAY specifies which display to ask about.\n\
3776 DISPLAY should be either a frame or a display name (a string).\n\
3777 If omitted or nil, that stands for the selected frame's display.")
3778 (display)
3779 Lisp_Object display;
3780 {
3781 struct win32_display_info *dpyinfo = check_x_display_info (display);
3782
3783 return make_number (1);
3784 }
3785
3786 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3787 "Returns the vendor ID string of the Win32 system (Microsoft).\n\
3788 The optional argument DISPLAY specifies which display to ask about.\n\
3789 DISPLAY should be either a frame or a display name (a string).\n\
3790 If omitted or nil, that stands for the selected frame's display.")
3791 (display)
3792 Lisp_Object display;
3793 {
3794 struct win32_display_info *dpyinfo = check_x_display_info (display);
3795 char *vendor = "Microsoft Corp.";
3796
3797 if (! vendor) vendor = "";
3798 return build_string (vendor);
3799 }
3800
3801 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3802 "Returns the version numbers of the server of display DISPLAY.\n\
3803 The value is a list of three integers: the major and minor\n\
3804 version numbers, and the vendor-specific release\n\
3805 number. See also the function `x-server-vendor'.\n\n\
3806 The optional argument DISPLAY specifies which display to ask about.\n\
3807 DISPLAY should be either a frame or a display name (a string).\n\
3808 If omitted or nil, that stands for the selected frame's display.")
3809 (display)
3810 Lisp_Object display;
3811 {
3812 struct win32_display_info *dpyinfo = check_x_display_info (display);
3813
3814 return Fcons (make_number (nt_major_version),
3815 Fcons (make_number (nt_minor_version), Qnil));
3816 }
3817
3818 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3819 "Returns the number of screens on the server of display DISPLAY.\n\
3820 The optional argument DISPLAY specifies which display to ask about.\n\
3821 DISPLAY should be either a frame or a display name (a string).\n\
3822 If omitted or nil, that stands for the selected frame's display.")
3823 (display)
3824 Lisp_Object display;
3825 {
3826 struct win32_display_info *dpyinfo = check_x_display_info (display);
3827
3828 return make_number (1);
3829 }
3830
3831 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3832 "Returns the height in millimeters of the X display DISPLAY.\n\
3833 The optional argument DISPLAY specifies which display to ask about.\n\
3834 DISPLAY should be either a frame or a display name (a string).\n\
3835 If omitted or nil, that stands for the selected frame's display.")
3836 (display)
3837 Lisp_Object display;
3838 {
3839 struct win32_display_info *dpyinfo = check_x_display_info (display);
3840 HDC hdc;
3841 int cap;
3842
3843 hdc = my_get_dc (dpyinfo->root_window);
3844
3845 cap = GetDeviceCaps (hdc, VERTSIZE);
3846
3847 ReleaseDC (dpyinfo->root_window, hdc);
3848
3849 return make_number (cap);
3850 }
3851
3852 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3853 "Returns the width in millimeters of the X display DISPLAY.\n\
3854 The optional argument DISPLAY specifies which display to ask about.\n\
3855 DISPLAY should be either a frame or a display name (a string).\n\
3856 If omitted or nil, that stands for the selected frame's display.")
3857 (display)
3858 Lisp_Object display;
3859 {
3860 struct win32_display_info *dpyinfo = check_x_display_info (display);
3861
3862 HDC hdc;
3863 int cap;
3864
3865 hdc = my_get_dc (dpyinfo->root_window);
3866
3867 cap = GetDeviceCaps (hdc, HORZSIZE);
3868
3869 ReleaseDC (dpyinfo->root_window, hdc);
3870
3871 return make_number (cap);
3872 }
3873
3874 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3875 Sx_display_backing_store, 0, 1, 0,
3876 "Returns an indication of whether display DISPLAY does backing store.\n\
3877 The value may be `always', `when-mapped', or `not-useful'.\n\
3878 The optional argument DISPLAY specifies which display to ask about.\n\
3879 DISPLAY should be either a frame or a display name (a string).\n\
3880 If omitted or nil, that stands for the selected frame's display.")
3881 (display)
3882 Lisp_Object display;
3883 {
3884 return intern ("not-useful");
3885 }
3886
3887 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3888 Sx_display_visual_class, 0, 1, 0,
3889 "Returns the visual class of the display DISPLAY.\n\
3890 The value is one of the symbols `static-gray', `gray-scale',\n\
3891 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
3892 The optional argument DISPLAY specifies which display to ask about.\n\
3893 DISPLAY should be either a frame or a display name (a string).\n\
3894 If omitted or nil, that stands for the selected frame's display.")
3895 (display)
3896 Lisp_Object display;
3897 {
3898 struct win32_display_info *dpyinfo = check_x_display_info (display);
3899
3900 #if 0
3901 switch (dpyinfo->visual->class)
3902 {
3903 case StaticGray: return (intern ("static-gray"));
3904 case GrayScale: return (intern ("gray-scale"));
3905 case StaticColor: return (intern ("static-color"));
3906 case PseudoColor: return (intern ("pseudo-color"));
3907 case TrueColor: return (intern ("true-color"));
3908 case DirectColor: return (intern ("direct-color"));
3909 default:
3910 error ("Display has an unknown visual class");
3911 }
3912 #endif
3913
3914 error ("Display has an unknown visual class");
3915 }
3916
3917 DEFUN ("x-display-save-under", Fx_display_save_under,
3918 Sx_display_save_under, 0, 1, 0,
3919 "Returns t if the display DISPLAY supports the save-under feature.\n\
3920 The optional argument DISPLAY specifies which display to ask about.\n\
3921 DISPLAY should be either a frame or a display name (a string).\n\
3922 If omitted or nil, that stands for the selected frame's display.")
3923 (display)
3924 Lisp_Object display;
3925 {
3926 struct win32_display_info *dpyinfo = check_x_display_info (display);
3927
3928 return Qnil;
3929 }
3930 \f
3931 int
3932 x_pixel_width (f)
3933 register struct frame *f;
3934 {
3935 return PIXEL_WIDTH (f);
3936 }
3937
3938 int
3939 x_pixel_height (f)
3940 register struct frame *f;
3941 {
3942 return PIXEL_HEIGHT (f);
3943 }
3944
3945 int
3946 x_char_width (f)
3947 register struct frame *f;
3948 {
3949 return FONT_WIDTH (f->output_data.win32->font);
3950 }
3951
3952 int
3953 x_char_height (f)
3954 register struct frame *f;
3955 {
3956 return f->output_data.win32->line_height;
3957 }
3958
3959 int
3960 x_screen_planes (frame)
3961 Lisp_Object frame;
3962 {
3963 return (FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_planes *
3964 FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_cbits);
3965 }
3966 \f
3967 /* Return the display structure for the display named NAME.
3968 Open a new connection if necessary. */
3969
3970 struct win32_display_info *
3971 x_display_info_for_name (name)
3972 Lisp_Object name;
3973 {
3974 Lisp_Object names;
3975 struct win32_display_info *dpyinfo;
3976
3977 CHECK_STRING (name, 0);
3978
3979 for (dpyinfo = &one_win32_display_info, names = win32_display_name_list;
3980 dpyinfo;
3981 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
3982 {
3983 Lisp_Object tem;
3984 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
3985 if (!NILP (tem))
3986 return dpyinfo;
3987 }
3988
3989 /* Use this general default value to start with. */
3990 Vx_resource_name = Vinvocation_name;
3991
3992 validate_x_resource_name ();
3993
3994 dpyinfo = win32_term_init (name, (unsigned char *)0,
3995 (char *) XSTRING (Vx_resource_name)->data);
3996
3997 if (dpyinfo == 0)
3998 error ("Cannot connect to server %s", XSTRING (name)->data);
3999
4000 XSETFASTINT (Vwindow_system_version, 3);
4001
4002 return dpyinfo;
4003 }
4004
4005 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4006 1, 3, 0, "Open a connection to a server.\n\
4007 DISPLAY is the name of the display to connect to.\n\
4008 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4009 If the optional third arg MUST-SUCCEED is non-nil,\n\
4010 terminate Emacs if we can't open the connection.")
4011 (display, xrm_string, must_succeed)
4012 Lisp_Object display, xrm_string, must_succeed;
4013 {
4014 unsigned int n_planes;
4015 unsigned char *xrm_option;
4016 struct win32_display_info *dpyinfo;
4017
4018 CHECK_STRING (display, 0);
4019 if (! NILP (xrm_string))
4020 CHECK_STRING (xrm_string, 1);
4021
4022 Vwin32_color_map = Fwin32_default_color_map ();
4023
4024 if (! NILP (xrm_string))
4025 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4026 else
4027 xrm_option = (unsigned char *) 0;
4028
4029 /* Use this general default value to start with. */
4030 Vx_resource_name = Vinvocation_name;
4031
4032 validate_x_resource_name ();
4033
4034 /* This is what opens the connection and sets x_current_display.
4035 This also initializes many symbols, such as those used for input. */
4036 dpyinfo = win32_term_init (display, xrm_option,
4037 (char *) XSTRING (Vx_resource_name)->data);
4038
4039 if (dpyinfo == 0)
4040 {
4041 if (!NILP (must_succeed))
4042 fatal ("Cannot connect to server %s.\n",
4043 XSTRING (display)->data);
4044 else
4045 error ("Cannot connect to server %s", XSTRING (display)->data);
4046 }
4047
4048 XSETFASTINT (Vwindow_system_version, 3);
4049 return Qnil;
4050 }
4051
4052 DEFUN ("x-close-connection", Fx_close_connection,
4053 Sx_close_connection, 1, 1, 0,
4054 "Close the connection to DISPLAY's server.\n\
4055 For DISPLAY, specify either a frame or a display name (a string).\n\
4056 If DISPLAY is nil, that stands for the selected frame's display.")
4057 (display)
4058 Lisp_Object display;
4059 {
4060 struct win32_display_info *dpyinfo = check_x_display_info (display);
4061 struct win32_display_info *tail;
4062 int i;
4063
4064 if (dpyinfo->reference_count > 0)
4065 error ("Display still has frames on it");
4066
4067 BLOCK_INPUT;
4068 /* Free the fonts in the font table. */
4069 for (i = 0; i < dpyinfo->n_fonts; i++)
4070 {
4071 if (dpyinfo->font_table[i].name)
4072 free (dpyinfo->font_table[i].name);
4073 /* Don't free the full_name string;
4074 it is always shared with something else. */
4075 win32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
4076 }
4077 x_destroy_all_bitmaps (dpyinfo);
4078
4079 x_delete_display (dpyinfo);
4080 UNBLOCK_INPUT;
4081
4082 return Qnil;
4083 }
4084
4085 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4086 "Return the list of display names that Emacs has connections to.")
4087 ()
4088 {
4089 Lisp_Object tail, result;
4090
4091 result = Qnil;
4092 for (tail = win32_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
4093 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
4094
4095 return result;
4096 }
4097
4098 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4099 "If ON is non-nil, report errors as soon as the erring request is made.\n\
4100 If ON is nil, allow buffering of requests.\n\
4101 This is a noop on Win32 systems.\n\
4102 The optional second argument DISPLAY specifies which display to act on.\n\
4103 DISPLAY should be either a frame or a display name (a string).\n\
4104 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
4105 (on, display)
4106 Lisp_Object display, on;
4107 {
4108 struct win32_display_info *dpyinfo = check_x_display_info (display);
4109
4110 return Qnil;
4111 }
4112
4113 \f
4114 /* These are the win32 specialized functions */
4115
4116 DEFUN ("win32-select-font", Fwin32_select_font, Swin32_select_font, 0, 1, 0,
4117 "This will display the Win32 font dialog and return an X font string corresponding to the selection.")
4118 (frame)
4119 Lisp_Object frame;
4120 {
4121 FRAME_PTR f = check_x_frame (frame);
4122 CHOOSEFONT cf;
4123 LOGFONT lf;
4124 char buf[100];
4125
4126 bzero (&cf, sizeof (cf));
4127
4128 cf.lStructSize = sizeof (cf);
4129 cf.hwndOwner = FRAME_WIN32_WINDOW (f);
4130 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST | CF_SCREENFONTS;
4131 cf.lpLogFont = &lf;
4132
4133 if (!ChooseFont (&cf) || !win32_to_x_font (&lf, buf, 100))
4134 return Qnil;
4135
4136 return build_string (buf);
4137 }
4138
4139 \f
4140 syms_of_win32fns ()
4141 {
4142 /* The section below is built by the lisp expression at the top of the file,
4143 just above where these variables are declared. */
4144 /*&&& init symbols here &&&*/
4145 Qauto_raise = intern ("auto-raise");
4146 staticpro (&Qauto_raise);
4147 Qauto_lower = intern ("auto-lower");
4148 staticpro (&Qauto_lower);
4149 Qbackground_color = intern ("background-color");
4150 staticpro (&Qbackground_color);
4151 Qbar = intern ("bar");
4152 staticpro (&Qbar);
4153 Qborder_color = intern ("border-color");
4154 staticpro (&Qborder_color);
4155 Qborder_width = intern ("border-width");
4156 staticpro (&Qborder_width);
4157 Qbox = intern ("box");
4158 staticpro (&Qbox);
4159 Qcursor_color = intern ("cursor-color");
4160 staticpro (&Qcursor_color);
4161 Qcursor_type = intern ("cursor-type");
4162 staticpro (&Qcursor_type);
4163 Qfont = intern ("font");
4164 staticpro (&Qfont);
4165 Qforeground_color = intern ("foreground-color");
4166 staticpro (&Qforeground_color);
4167 Qgeometry = intern ("geometry");
4168 staticpro (&Qgeometry);
4169 Qicon_left = intern ("icon-left");
4170 staticpro (&Qicon_left);
4171 Qicon_top = intern ("icon-top");
4172 staticpro (&Qicon_top);
4173 Qicon_type = intern ("icon-type");
4174 staticpro (&Qicon_type);
4175 Qicon_name = intern ("icon-name");
4176 staticpro (&Qicon_name);
4177 Qinternal_border_width = intern ("internal-border-width");
4178 staticpro (&Qinternal_border_width);
4179 Qleft = intern ("left");
4180 staticpro (&Qleft);
4181 Qmouse_color = intern ("mouse-color");
4182 staticpro (&Qmouse_color);
4183 Qnone = intern ("none");
4184 staticpro (&Qnone);
4185 Qparent_id = intern ("parent-id");
4186 staticpro (&Qparent_id);
4187 Qscroll_bar_width = intern ("scroll-bar-width");
4188 staticpro (&Qscroll_bar_width);
4189 Qsuppress_icon = intern ("suppress-icon");
4190 staticpro (&Qsuppress_icon);
4191 Qtop = intern ("top");
4192 staticpro (&Qtop);
4193 Qundefined_color = intern ("undefined-color");
4194 staticpro (&Qundefined_color);
4195 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
4196 staticpro (&Qvertical_scroll_bars);
4197 Qvisibility = intern ("visibility");
4198 staticpro (&Qvisibility);
4199 Qwindow_id = intern ("window-id");
4200 staticpro (&Qwindow_id);
4201 Qx_frame_parameter = intern ("x-frame-parameter");
4202 staticpro (&Qx_frame_parameter);
4203 Qx_resource_name = intern ("x-resource-name");
4204 staticpro (&Qx_resource_name);
4205 Quser_position = intern ("user-position");
4206 staticpro (&Quser_position);
4207 Quser_size = intern ("user-size");
4208 staticpro (&Quser_size);
4209 Qdisplay = intern ("display");
4210 staticpro (&Qdisplay);
4211 /* This is the end of symbol initialization. */
4212
4213 Fput (Qundefined_color, Qerror_conditions,
4214 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
4215 Fput (Qundefined_color, Qerror_message,
4216 build_string ("Undefined color"));
4217
4218 DEFVAR_LISP ("win32-color-map", &Vwin32_color_map,
4219 "A array of color name mappings for windows.");
4220 Vwin32_color_map = Qnil;
4221
4222 init_x_parm_symbols ();
4223
4224 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
4225 "List of directories to search for bitmap files for win32.");
4226 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
4227
4228 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
4229 "The shape of the pointer when over text.\n\
4230 Changing the value does not affect existing frames\n\
4231 unless you set the mouse color.");
4232 Vx_pointer_shape = Qnil;
4233
4234 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
4235 "The name Emacs uses to look up resources; for internal use only.\n\
4236 `x-get-resource' uses this as the first component of the instance name\n\
4237 when requesting resource values.\n\
4238 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
4239 was invoked, or to the value specified with the `-name' or `-rn'\n\
4240 switches, if present.");
4241 Vx_resource_name = Qnil;
4242
4243 Vx_nontext_pointer_shape = Qnil;
4244
4245 Vx_mode_pointer_shape = Qnil;
4246
4247 DEFVAR_INT ("x-sensitive-text-pointer-shape",
4248 &Vx_sensitive_text_pointer_shape,
4249 "The shape of the pointer when over mouse-sensitive text.\n\
4250 This variable takes effect when you create a new frame\n\
4251 or when you set the mouse color.");
4252 Vx_sensitive_text_pointer_shape = Qnil;
4253
4254 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
4255 "A string indicating the foreground color of the cursor box.");
4256 Vx_cursor_fore_pixel = Qnil;
4257
4258 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
4259 "Non-nil if no window manager is in use.\n\
4260 Emacs doesn't try to figure this out; this is always nil\n\
4261 unless you set it to something else.");
4262 /* We don't have any way to find this out, so set it to nil
4263 and maybe the user would like to set it to t. */
4264 Vx_no_window_manager = Qnil;
4265
4266 defsubr (&Sx_get_resource);
4267 defsubr (&Sx_list_fonts);
4268 defsubr (&Sx_display_color_p);
4269 defsubr (&Sx_display_grayscale_p);
4270 defsubr (&Sx_color_defined_p);
4271 defsubr (&Sx_color_values);
4272 defsubr (&Sx_server_max_request_size);
4273 defsubr (&Sx_server_vendor);
4274 defsubr (&Sx_server_version);
4275 defsubr (&Sx_display_pixel_width);
4276 defsubr (&Sx_display_pixel_height);
4277 defsubr (&Sx_display_mm_width);
4278 defsubr (&Sx_display_mm_height);
4279 defsubr (&Sx_display_screens);
4280 defsubr (&Sx_display_planes);
4281 defsubr (&Sx_display_color_cells);
4282 defsubr (&Sx_display_visual_class);
4283 defsubr (&Sx_display_backing_store);
4284 defsubr (&Sx_display_save_under);
4285 defsubr (&Sx_parse_geometry);
4286 defsubr (&Sx_create_frame);
4287 defsubr (&Sfocus_frame);
4288 defsubr (&Sunfocus_frame);
4289 defsubr (&Sx_open_connection);
4290 defsubr (&Sx_close_connection);
4291 defsubr (&Sx_display_list);
4292 defsubr (&Sx_synchronize);
4293
4294 /* Win32 specific functions */
4295
4296 defsubr (&Swin32_select_font);
4297 }
4298
4299 #undef abort
4300
4301 void
4302 win32_abort()
4303 {
4304 MessageBox (NULL,
4305 "A fatal error has occurred - aborting!",
4306 "Emacs Abort Dialog",
4307 MB_OK|MB_ICONEXCLAMATION);
4308 abort();
4309 }