aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGeoff Voelker1995-11-07 07:52:28 +0000
committerGeoff Voelker1995-11-07 07:52:28 +0000
commitee78dc3223f2552bcb0604d344e88221ff24daac (patch)
tree87192dd95e18d9f3fb3075e3c6b0b4a3228f4281 /src
parente80af09c2f58c1d931cbcb016dbd042c348dbf74 (diff)
downloademacs-ee78dc3223f2552bcb0604d344e88221ff24daac.tar.gz
emacs-ee78dc3223f2552bcb0604d344e88221ff24daac.zip
Initial revision
Diffstat (limited to 'src')
-rw-r--r--src/w32faces.c1048
-rw-r--r--src/w32fns.c4308
-rw-r--r--src/w32gui.h83
-rw-r--r--src/w32menu.c1917
-rw-r--r--src/w32reg.c94
-rw-r--r--src/w32select.c226
-rw-r--r--src/w32term.c3711
-rw-r--r--src/w32xfns.c293
8 files changed, 11680 insertions, 0 deletions
diff --git a/src/w32faces.c b/src/w32faces.c
new file mode 100644
index 00000000000..dd0cbbaa8a7
--- /dev/null
+++ b/src/w32faces.c
@@ -0,0 +1,1048 @@
1/* "Face" primitives.
2 Copyright (C) 1993, 1994, 1995 Free Software Foundation.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* Ported xfaces.c for win32 - Kevin Gallo */
21
22#include <sys/types.h>
23#include <sys/stat.h>
24
25#include <config.h>
26#include "lisp.h"
27
28#include "w32term.h"
29#include "buffer.h"
30#include "dispextern.h"
31#include "frame.h"
32#include "blockinput.h"
33#include "window.h"
34#include "intervals.h"
35
36
37/* An explanation of the face data structures. */
38
39/* ========================= Face Data Structures =========================
40
41 Let FACE-NAME be a symbol naming a face.
42
43 Let FACE-VECTOR be (assq FACE-NAME (frame-face-alist FRAME))
44 FACE-VECTOR is either nil, or a vector of the form
45 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
46 where
47 face is the symbol `face',
48 NAME is the symbol with which this vector is associated (a backpointer),
49 ID is the face ID, an integer used internally by the C code to identify
50 the face,
51 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
52 to use with the face,
53 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
54 use right now, and
55 UNDERLINE-P is non-nil if the face should be underlined.
56 If any of these elements are nil, that parameter is considered
57 unspecified; parameters from faces specified by lower-priority
58 overlays or text properties, or the parameters of the frame itself,
59 can show through. (lisp/faces.el maintains these lists.)
60
61 (assq FACE-NAME global-face-data) returns a vector describing the
62 global parameters for that face.
63
64 Let PARAM-FACE be FRAME->display.x->param_faces[Faref (FACE-VECTOR, 2)].
65 PARAM_FACE is a struct face whose members are the Xlib analogues of
66 the parameters in FACE-VECTOR. If an element of FACE-VECTOR is
67 nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
68 These faces are called "parameter faces", because they're the ones
69 lisp manipulates to control what gets displayed. Elements 0 and 1
70 of FRAME->display.x->param_faces are special - they describe the
71 default and mode line faces. None of the faces in param_faces have
72 GC's. (See src/dispextern.h for the definiton of struct face.
73 lisp/faces.el maintains the isomorphism between face_alist and
74 param_faces.)
75
76 The functions compute_char_face and compute_glyph_face find and
77 combine the parameter faces associated with overlays and text
78 properties. The resulting faces are called "computed faces"; none
79 of their members are FACE_DEFAULT; they are completely specified.
80 They then call intern_compute_face to search
81 FRAME->display.x->computed_faces for a matching face, add one if
82 none is found, and return the index into
83 FRAME->display.x->computed_faces. FRAME's glyph matrices use these
84 indices to record the faces of the matrix characters, and the X
85 display hooks consult compute_faces to decide how to display these
86 characters. Elements 0 and 1 of computed_faces always describe the
87 default and mode-line faces.
88
89 Each computed face belongs to a particular frame.
90
91 Computed faces have graphics contexts some of the time.
92 intern_face builds a GC for a specified computed face
93 if it doesn't have one already.
94 clear_face_cache clears out the GCs of all computed faces.
95 This is done from time to time so that we don't hold on to
96 lots of GCs that are no longer needed.
97
98 Constraints:
99
100 Symbols naming faces must have associations on all frames; for any
101 FRAME, for all FACE-NAME, if (assq FACE-NAME (frame-face-alist
102 FRAME)) is non-nil, it must be non-nil for all frames.
103
104 Analogously, indices into param_faces must be valid on all frames;
105 if param_faces[i] is a non-zero face pointer on one frame, then it
106 must be filled in on all frames. Code assumes that face ID's can
107 be used on any frame.
108
109 Some subtleties:
110
111 Why do we keep param_faces and computed_faces separate?
112 computed_faces contains an element for every combination of facial
113 parameters we have ever displayed. indices into param_faces have
114 to be valid on all frames. If they were the same array, then that
115 array would grow very large on all frames, because any facial
116 combination displayed on any frame would need to be a valid entry
117 on all frames. */
118
119/* Definitions and declarations. */
120
121/* The number of face-id's in use (same for all frames). */
122static int next_face_id;
123
124/* The number of the face to use to indicate the region. */
125static int region_face;
126
127/* This is what appears in a slot in a face to signify that the face
128 does not specify that display aspect. */
129#define FACE_DEFAULT (~0)
130
131Lisp_Object Qface, Qmouse_face;
132Lisp_Object Qpixmap_spec_p;
133
134int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
135
136struct face *intern_face ( /* FRAME_PTR, struct face * */ );
137static int new_computed_face ( /* FRAME_PTR, struct face * */ );
138static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
139static void ensure_face_ready ( /* FRAME_PTR, int id */ );
140void recompute_basic_faces ( /* FRAME_PTR f */ );
141
142/* Allocating, copying, and comparing struct faces. */
143
144/* Allocate a new face */
145static struct face *
146allocate_face ()
147{
148 struct face *result = (struct face *) xmalloc (sizeof (struct face));
149 bzero (result, sizeof (struct face));
150 result->font = (XFontStruct *) FACE_DEFAULT;
151 result->foreground = FACE_DEFAULT;
152 result->background = FACE_DEFAULT;
153 result->stipple = FACE_DEFAULT;
154 return result;
155}
156
157/* Make a new face that's a copy of an existing one. */
158static struct face *
159copy_face (face)
160 struct face *face;
161{
162 struct face *result = allocate_face ();
163
164 result->font = face->font;
165 result->foreground = face->foreground;
166 result->background = face->background;
167 result->stipple = face->stipple;
168 result->underline = face->underline;
169 result->pixmap_h = face->pixmap_h;
170 result->pixmap_w = face->pixmap_w;
171
172 return result;
173}
174
175static int
176face_eql (face1, face2)
177 struct face *face1, *face2;
178{
179 return ( face1->font == face2->font
180 && face1->foreground == face2->foreground
181 && face1->background == face2->background
182 && face1->stipple == face2->stipple
183 && face1->underline == face2->underline);
184}
185
186/* Managing graphics contexts of faces. */
187
188/* Given a computed face, construct its graphics context if necessary. */
189
190struct face *
191intern_face (f, face)
192 struct frame *f;
193 struct face *face;
194{
195 face->gc = NULL;
196
197 return face;
198}
199
200/* Clear out all graphics contexts for all computed faces
201 except for the default and mode line faces.
202 This should be done from time to time just to avoid
203 keeping too many graphics contexts that are no longer needed. */
204
205void
206clear_face_cache ()
207{
208/* Nothing extra */
209}
210
211/* Allocating, freeing, and duplicating fonts, colors, and pixmaps.
212
213 These functions operate on param faces only.
214 Computed faces get their fonts, colors and pixmaps
215 by merging param faces. */
216
217static XFontStruct *
218load_font (f, name)
219 struct frame *f;
220 Lisp_Object name;
221{
222 XFontStruct *font;
223
224 if (NILP (name))
225 return (XFontStruct *) FACE_DEFAULT;
226
227 CHECK_STRING (name, 0);
228 BLOCK_INPUT;
229 font = win32_load_font (FRAME_WIN32_DISPLAY_INFO (f), (char *) XSTRING (name)->data);
230 UNBLOCK_INPUT;
231
232 if (! font)
233 Fsignal (Qerror, Fcons (build_string ("undefined font"),
234 Fcons (name, Qnil)));
235 return font;
236}
237
238static void
239unload_font (f, font)
240 struct frame *f;
241 XFontStruct *font;
242{
243 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
244 return;
245
246 BLOCK_INPUT;
247 win32_unload_font (FRAME_WIN32_DISPLAY_INFO (f), font);
248 UNBLOCK_INPUT;
249}
250
251static unsigned long
252load_color (f, name)
253 struct frame *f;
254 Lisp_Object name;
255{
256 COLORREF color;
257 int result;
258
259 if (NILP (name))
260 return FACE_DEFAULT;
261
262 CHECK_STRING (name, 0);
263 /* if the colormap is full, defined_color will return a best match
264 to the values in an an existing cell. */
265 result = defined_color(f, (char *) XSTRING (name)->data, &color, 1);
266 if (! result)
267 Fsignal (Qerror, Fcons (build_string ("undefined color"),
268 Fcons (name, Qnil)));
269 return (unsigned long) color;
270}
271
272static void
273unload_color (f, pixel)
274 struct frame *f;
275 unsigned long pixel;
276{
277}
278
279DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
280 "Return t if ARG is a valid pixmap specification.")
281 (arg)
282 Lisp_Object arg;
283{
284 Lisp_Object height, width;
285
286 return ((STRINGP (arg)
287 || (CONSP (arg)
288 && CONSP (XCONS (arg)->cdr)
289 && CONSP (XCONS (XCONS (arg)->cdr)->cdr)
290 && NILP (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->cdr)
291 && (width = XCONS (arg)->car, INTEGERP (width))
292 && (height = XCONS (XCONS (arg)->cdr)->car, INTEGERP (height))
293 && STRINGP (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->car)
294 && XINT (width) > 0
295 && XINT (height) > 0
296 /* The string must have enough bits for width * height. */
297 && ((XSTRING (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->car)->size
298 * (BITS_PER_INT / sizeof (int)))
299 >= XFASTINT (width) * XFASTINT (height))))
300 ? Qt : Qnil);
301}
302
303/* Load a bitmap according to NAME (which is either a file name
304 or a pixmap spec). Return the bitmap_id (see xfns.c)
305 or get an error if NAME is invalid.
306
307 Store the bitmap width in *W_PTR and height in *H_PTR. */
308
309static long
310load_pixmap (f, name, w_ptr, h_ptr)
311 FRAME_PTR f;
312 Lisp_Object name;
313 unsigned int *w_ptr, *h_ptr;
314{
315 int bitmap_id;
316 Lisp_Object tem;
317
318 if (NILP (name))
319 return FACE_DEFAULT;
320
321 tem = Fpixmap_spec_p (name);
322 if (NILP (tem))
323 wrong_type_argument (Qpixmap_spec_p, name);
324
325 BLOCK_INPUT;
326
327 if (CONSP (name))
328 {
329 /* Decode a bitmap spec into a bitmap. */
330
331 int h, w;
332 Lisp_Object bits;
333
334 w = XINT (Fcar (name));
335 h = XINT (Fcar (Fcdr (name)));
336 bits = Fcar (Fcdr (Fcdr (name)));
337
338 bitmap_id = x_create_bitmap_from_data (f, XSTRING (bits)->data,
339 w, h);
340 }
341 else
342 {
343 /* It must be a string -- a file name. */
344 bitmap_id = x_create_bitmap_from_file (f, name);
345 }
346 UNBLOCK_INPUT;
347
348 if (bitmap_id < 0)
349 Fsignal (Qerror, Fcons (build_string ("invalid or undefined bitmap"),
350 Fcons (name, Qnil)));
351
352 *w_ptr = x_bitmap_width (f, bitmap_id);
353 *h_ptr = x_bitmap_height (f, bitmap_id);
354
355 return bitmap_id;
356}
357
358
359/* Managing parameter face arrays for frames. */
360
361void
362init_frame_faces (f)
363 FRAME_PTR f;
364{
365 ensure_face_ready (f, 0);
366 ensure_face_ready (f, 1);
367
368 FRAME_N_COMPUTED_FACES (f) = 0;
369 FRAME_SIZE_COMPUTED_FACES (f) = 0;
370
371 new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
372 new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
373 recompute_basic_faces (f);
374
375#ifdef MULTI_FRAME
376 /* Find another frame. */
377 {
378 Lisp_Object tail, frame, result;
379
380 result = Qnil;
381 FOR_EACH_FRAME (tail, frame)
382 if (FRAME_WIN32_P (XFRAME (frame))
383 && XFRAME (frame) != f)
384 {
385 result = frame;
386 break;
387 }
388
389 /* If we didn't find any X frames other than f, then we don't need
390 any faces other than 0 and 1, so we're okay. Otherwise, make
391 sure that all faces valid on the selected frame are also valid
392 on this new frame. */
393 if (FRAMEP (result))
394 {
395 int i;
396 int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
397 struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
398
399 for (i = 2; i < n_faces; i++)
400 if (faces[i])
401 ensure_face_ready (f, i);
402 }
403 }
404#endif /* MULTI_FRAME */
405}
406
407
408/* Called from Fdelete_frame. */
409
410void
411free_frame_faces (f)
412 struct frame *f;
413{
414 int i;
415
416 BLOCK_INPUT;
417
418 for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
419 {
420 struct face *face = FRAME_PARAM_FACES (f) [i];
421 if (face)
422 {
423 unload_font (f, face->font);
424 unload_color (f, face->foreground);
425 unload_color (f, face->background);
426 x_destroy_bitmap (f, face->stipple);
427 xfree (face);
428 }
429 }
430 xfree (FRAME_PARAM_FACES (f));
431 FRAME_PARAM_FACES (f) = 0;
432 FRAME_N_PARAM_FACES (f) = 0;
433
434 /* All faces in FRAME_COMPUTED_FACES use resources copied from
435 FRAME_PARAM_FACES; we can free them without fuss.
436 But we do free the GCs and the face objects themselves. */
437 for (i = 0; i < FRAME_N_COMPUTED_FACES (f); i++)
438 {
439 struct face *face = FRAME_COMPUTED_FACES (f) [i];
440 if (face)
441 {
442 xfree (face);
443 }
444 }
445 xfree (FRAME_COMPUTED_FACES (f));
446 FRAME_COMPUTED_FACES (f) = 0;
447 FRAME_N_COMPUTED_FACES (f) = 0;
448
449 UNBLOCK_INPUT;
450}
451
452/* Interning faces in a frame's face array. */
453
454static int
455new_computed_face (f, new_face)
456 struct frame *f;
457 struct face *new_face;
458{
459 int i = FRAME_N_COMPUTED_FACES (f);
460
461 if (i >= FRAME_SIZE_COMPUTED_FACES (f))
462 {
463 int new_size = i + 32;
464
465 FRAME_COMPUTED_FACES (f)
466 = (struct face **) (FRAME_SIZE_COMPUTED_FACES (f) == 0
467 ? xmalloc (new_size * sizeof (struct face *))
468 : xrealloc (FRAME_COMPUTED_FACES (f),
469 new_size * sizeof (struct face *)));
470 FRAME_SIZE_COMPUTED_FACES (f) = new_size;
471 }
472
473 i = FRAME_N_COMPUTED_FACES (f)++;
474 FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
475 return i;
476}
477
478
479/* Find a match for NEW_FACE in a FRAME's computed face array, and add
480 it if we don't find one. */
481static int
482intern_computed_face (f, new_face)
483 struct frame *f;
484 struct face *new_face;
485{
486 int len = FRAME_N_COMPUTED_FACES (f);
487 int i;
488
489 /* Search for a computed face already on F equivalent to FACE. */
490 for (i = 0; i < len; i++)
491 {
492 if (! FRAME_COMPUTED_FACES (f)[i])
493 abort ();
494 if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
495 return i;
496 }
497
498 /* We didn't find one; add a new one. */
499 return new_computed_face (f, new_face);
500}
501
502/* Make parameter face id ID valid on frame F. */
503
504static void
505ensure_face_ready (f, id)
506 struct frame *f;
507 int id;
508{
509 if (FRAME_N_PARAM_FACES (f) <= id)
510 {
511 int n = id + 10;
512 int i;
513 if (!FRAME_N_PARAM_FACES (f))
514 FRAME_PARAM_FACES (f)
515 = (struct face **) xmalloc (sizeof (struct face *) * n);
516 else
517 FRAME_PARAM_FACES (f)
518 = (struct face **) xrealloc (FRAME_PARAM_FACES (f),
519 sizeof (struct face *) * n);
520
521 bzero (FRAME_PARAM_FACES (f) + FRAME_N_PARAM_FACES (f),
522 (n - FRAME_N_PARAM_FACES (f)) * sizeof (struct face *));
523 FRAME_N_PARAM_FACES (f) = n;
524 }
525
526 if (FRAME_PARAM_FACES (f) [id] == 0)
527 FRAME_PARAM_FACES (f) [id] = allocate_face ();
528}
529
530/* Return non-zero if FONT1 and FONT2 have the same width.
531 We do not check the height, because we can now deal with
532 different heights.
533 We assume that they're both character-cell fonts. */
534
535int
536same_size_fonts (font1, font2)
537 XFontStruct *font1, *font2;
538{
539 return (FONT_WIDTH(font1) == FONT_WIDTH(font2));
540}
541
542/* Update the line_height of frame F according to the biggest font in
543 any face. Return nonzero if if line_height changes. */
544
545int
546frame_update_line_height (f)
547 FRAME_PTR f;
548{
549 int i;
550 int biggest = FONT_HEIGHT (f->output_data.win32->font);
551
552 for (i = 0; i < f->output_data.win32->n_param_faces; i++)
553 if (f->output_data.win32->param_faces[i] != 0
554 && f->output_data.win32->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
555 {
556 int height = FONT_HEIGHT (f->output_data.win32->param_faces[i]->font);
557 if (height > biggest)
558 biggest = height;
559 }
560
561 if (biggest == f->output_data.win32->line_height)
562 return 0;
563
564 f->output_data.win32->line_height = biggest;
565 return 1;
566}
567
568/* Modify face TO by copying from FROM all properties which have
569 nondefault settings. */
570
571static void
572merge_faces (from, to)
573 struct face *from, *to;
574{
575 /* Only merge the font if it's the same width as the base font.
576 Otherwise ignore it, since we can't handle it properly. */
577 if (from->font != (XFontStruct *) FACE_DEFAULT
578 && same_size_fonts (from->font, to->font))
579 to->font = from->font;
580 if (from->foreground != FACE_DEFAULT)
581 to->foreground = from->foreground;
582 if (from->background != FACE_DEFAULT)
583 to->background = from->background;
584 if (from->stipple != FACE_DEFAULT)
585 {
586 to->stipple = from->stipple;
587 to->pixmap_h = from->pixmap_h;
588 to->pixmap_w = from->pixmap_w;
589 }
590 if (from->underline)
591 to->underline = from->underline;
592}
593
594/* Set up the basic set of facial parameters, based on the frame's
595 data; all faces are deltas applied to this. */
596
597static void
598compute_base_face (f, face)
599 FRAME_PTR f;
600 struct face *face;
601{
602 face->gc = 0;
603 face->foreground = FRAME_FOREGROUND_PIXEL (f);
604 face->background = FRAME_BACKGROUND_PIXEL (f);
605 face->font = FRAME_FONT (f);
606 face->stipple = 0;
607 face->underline = 0;
608}
609
610/* Return the face ID to use to display a special glyph which selects
611 FACE_CODE as the face ID, assuming that ordinarily the face would
612 be CURRENT_FACE. F is the frame. */
613
614int
615compute_glyph_face (f, face_code, current_face)
616 struct frame *f;
617 int face_code, current_face;
618{
619 struct face face;
620
621 face = *FRAME_COMPUTED_FACES (f)[current_face];
622
623 if (face_code >= 0 && face_code < FRAME_N_PARAM_FACES (f)
624 && FRAME_PARAM_FACES (f) [face_code] != 0)
625 merge_faces (FRAME_PARAM_FACES (f) [face_code], &face);
626
627 return intern_computed_face (f, &face);
628}
629
630/* Return the face ID to use to display a special glyph which selects
631 FACE_CODE as the face ID, assuming that ordinarily the face would
632 be CURRENT_FACE. F is the frame. */
633
634int
635compute_glyph_face_1 (f, face_name, current_face)
636 struct frame *f;
637 Lisp_Object face_name;
638 int current_face;
639{
640 struct face face;
641
642 face = *FRAME_COMPUTED_FACES (f)[current_face];
643
644 if (!NILP (face_name))
645 {
646 int facecode = face_name_id_number (f, face_name);
647 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
648 && FRAME_PARAM_FACES (f) [facecode] != 0)
649 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
650 }
651
652 return intern_computed_face (f, &face);
653}
654
655/* Return the face ID associated with a buffer position POS.
656 Store into *ENDPTR the position at which a different face is needed.
657 This does not take account of glyphs that specify their own face codes.
658 F is the frame in use for display, and W is a window displaying
659 the current buffer.
660
661 REGION_BEG, REGION_END delimit the region, so it can be highlighted.
662
663 LIMIT is a position not to scan beyond. That is to limit
664 the time this function can take.
665
666 If MOUSE is nonzero, use the character's mouse-face, not its face. */
667
668int
669compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
670 struct frame *f;
671 struct window *w;
672 int pos;
673 int region_beg, region_end;
674 int *endptr;
675 int limit;
676 int mouse;
677{
678 struct face face;
679 Lisp_Object prop, position;
680 int i, j, noverlays;
681 int facecode;
682 Lisp_Object *overlay_vec;
683 Lisp_Object frame;
684 int endpos;
685 Lisp_Object propname;
686
687 /* W must display the current buffer. We could write this function
688 to use the frame and buffer of W, but right now it doesn't. */
689 if (XBUFFER (w->buffer) != current_buffer)
690 abort ();
691
692 XSETFRAME (frame, f);
693
694 endpos = ZV;
695 if (pos < region_beg && region_beg < endpos)
696 endpos = region_beg;
697
698 XSETFASTINT (position, pos);
699
700 if (mouse)
701 propname = Qmouse_face;
702 else
703 propname = Qface;
704
705 prop = Fget_text_property (position, propname, w->buffer);
706
707 {
708 Lisp_Object limit1, end;
709
710 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
711 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
712 if (INTEGERP (end))
713 endpos = XINT (end);
714 }
715
716 {
717 int next_overlay;
718 int len;
719
720 /* First try with room for 40 overlays. */
721 len = 40;
722 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
723
724 noverlays = overlays_at (pos, 0, &overlay_vec, &len,
725 &next_overlay, (int *) 0);
726
727 /* If there are more than 40,
728 make enough space for all, and try again. */
729 if (noverlays > len)
730 {
731 len = noverlays;
732 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
733 noverlays = overlays_at (pos, 0, &overlay_vec, &len,
734 &next_overlay, (int *) 0);
735 }
736
737 if (next_overlay < endpos)
738 endpos = next_overlay;
739 }
740
741 *endptr = endpos;
742
743 /* Optimize the default case. */
744 if (noverlays == 0 && NILP (prop)
745 && !(pos >= region_beg && pos < region_end))
746 return 0;
747
748 compute_base_face (f, &face);
749
750 if (CONSP (prop))
751 {
752 /* We have a list of faces, merge them in reverse order */
753 Lisp_Object length = Flength (prop);
754 int len = XINT (length);
755 Lisp_Object *faces;
756
757 /* Put them into an array */
758 faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
759 for (j = 0; j < len; j++)
760 {
761 faces[j] = Fcar (prop);
762 prop = Fcdr (prop);
763 }
764 /* So that we can merge them in the reverse order */
765 for (j = len - 1; j >= 0; j--)
766 {
767 facecode = face_name_id_number (f, faces[j]);
768 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
769 && FRAME_PARAM_FACES (f) [facecode] != 0)
770 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
771 }
772 }
773 else if (!NILP (prop))
774 {
775 facecode = face_name_id_number (f, prop);
776 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
777 && FRAME_PARAM_FACES (f) [facecode] != 0)
778 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
779 }
780
781 noverlays = sort_overlays (overlay_vec, noverlays, w);
782
783 /* Now merge the overlay data in that order. */
784 for (i = 0; i < noverlays; i++)
785 {
786 prop = Foverlay_get (overlay_vec[i], propname);
787 if (CONSP (prop))
788 {
789 /* We have a list of faces, merge them in reverse order */
790 Lisp_Object length = Flength (prop);
791 int len = XINT (length);
792 Lisp_Object *faces;
793 int i;
794
795 /* Put them into an array */
796 faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
797 for (j = 0; j < len; j++)
798 {
799 faces[j] = Fcar (prop);
800 prop = Fcdr (prop);
801 }
802 /* So that we can merge them in the reverse order */
803 for (j = len - 1; j >= 0; j--)
804 {
805 facecode = face_name_id_number (f, faces[j]);
806 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
807 && FRAME_PARAM_FACES (f) [facecode] != 0)
808 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
809 }
810 }
811 else if (!NILP (prop))
812 {
813 Lisp_Object oend;
814 int oendpos;
815
816 facecode = face_name_id_number (f, prop);
817 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
818 && FRAME_PARAM_FACES (f) [facecode] != 0)
819 merge_faces (FRAME_PARAM_FACES (f)[facecode], &face);
820
821 oend = OVERLAY_END (overlay_vec[i]);
822 oendpos = OVERLAY_POSITION (oend);
823 if (oendpos < endpos)
824 endpos = oendpos;
825 }
826 }
827
828 if (pos >= region_beg && pos < region_end)
829 {
830 if (region_end < endpos)
831 endpos = region_end;
832 if (region_face >= 0 && region_face < next_face_id)
833 merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
834 }
835
836 *endptr = endpos;
837
838 return intern_computed_face (f, &face);
839}
840
841/* Recompute the GC's for the default and modeline faces.
842 We call this after changing frame parameters on which those GC's
843 depend. */
844
845void
846recompute_basic_faces (f)
847 FRAME_PTR f;
848{
849 /* If the frame's faces haven't been initialized yet, don't worry about
850 this stuff. */
851 if (FRAME_N_PARAM_FACES (f) < 2)
852 return;
853
854 BLOCK_INPUT;
855
856 compute_base_face (f, FRAME_DEFAULT_FACE (f));
857 compute_base_face (f, FRAME_MODE_LINE_FACE (f));
858
859 merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
860 merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
861
862 intern_face (f, FRAME_DEFAULT_FACE (f));
863 intern_face (f, FRAME_MODE_LINE_FACE (f));
864
865 UNBLOCK_INPUT;
866}
867
868
869
870/* Lisp interface. */
871
872DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
873 "")
874 (frame)
875 Lisp_Object frame;
876{
877 CHECK_FRAME (frame, 0);
878 return XFRAME (frame)->face_alist;
879}
880
881DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
882 2, 2, 0, "")
883 (frame, value)
884 Lisp_Object frame, value;
885{
886 CHECK_FRAME (frame, 0);
887 XFRAME (frame)->face_alist = value;
888 return value;
889}
890
891
892DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
893 "Create face number FACE-ID on all frames.")
894 (face_id)
895 Lisp_Object face_id;
896{
897 Lisp_Object rest, frame;
898 int id = XINT (face_id);
899
900 CHECK_NUMBER (face_id, 0);
901 if (id < 0 || id >= next_face_id)
902 error ("Face id out of range");
903
904 FOR_EACH_FRAME (rest, frame)
905 {
906 if (FRAME_WIN32_P (XFRAME (frame)))
907 ensure_face_ready (XFRAME (frame), id);
908 }
909 return Qnil;
910}
911
912
913DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
914 Sset_face_attribute_internal, 4, 4, 0, "")
915 (face_id, attr_name, attr_value, frame)
916 Lisp_Object face_id, attr_name, attr_value, frame;
917{
918 struct face *face;
919 struct frame *f;
920 int magic_p;
921 int id;
922 int garbaged = 0;
923
924 CHECK_FRAME (frame, 0);
925 CHECK_NUMBER (face_id, 0);
926 CHECK_SYMBOL (attr_name, 0);
927
928 f = XFRAME (frame);
929 id = XINT (face_id);
930 if (id < 0 || id >= next_face_id)
931 error ("Face id out of range");
932
933 if (! FRAME_WIN32_P (f))
934 return Qnil;
935
936 ensure_face_ready (f, id);
937 face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
938
939 if (EQ (attr_name, intern ("font")))
940 {
941 XFontStruct *font = load_font (f, attr_value);
942 if (face->font != f->output_data.win32->font)
943 unload_font (f, face->font);
944 face->font = font;
945 if (frame_update_line_height (f))
946 x_set_window_size (f, 0, f->width, f->height);
947 /* Must clear cache, since it might contain the font
948 we just got rid of. */
949 garbaged = 1;
950 }
951 else if (EQ (attr_name, intern ("foreground")))
952 {
953 unsigned long new_color = load_color (f, attr_value);
954 unload_color (f, face->foreground);
955 face->foreground = new_color;
956 garbaged = 1;
957 }
958 else if (EQ (attr_name, intern ("background")))
959 {
960 unsigned long new_color = load_color (f, attr_value);
961 unload_color (f, face->background);
962 face->background = new_color;
963 garbaged = 1;
964 }
965 else if (EQ (attr_name, intern ("background-pixmap")))
966 {
967 unsigned int w, h;
968 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h);
969 x_destroy_bitmap (f, face->stipple);
970 face->stipple = (Pixmap) new_pixmap;
971 face->pixmap_w = w;
972 face->pixmap_h = h;
973 garbaged = 1;
974 }
975 else if (EQ (attr_name, intern ("underline")))
976 {
977 int new = !NILP (attr_value);
978 face->underline = new;
979 }
980 else
981 error ("unknown face attribute");
982
983 if (id == 0 || id == 1)
984 recompute_basic_faces (f);
985
986 /* We must redraw the frame whenever any face font or color changes,
987 because it's possible that a merged (display) face
988 contains the font or color we just replaced.
989 And we must inhibit any Expose events until the redraw is done,
990 since they would try to use the invalid display faces. */
991 if (garbaged)
992 SET_FRAME_GARBAGED (f);
993
994 return Qnil;
995}
996
997DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
998 0, 0, 0, "")
999 ()
1000{
1001 return make_number (next_face_id++);
1002}
1003
1004/* Return the face id for name NAME on frame FRAME.
1005 (It should be the same for all frames,
1006 but it's as easy to use the "right" frame to look it up
1007 as to use any other one.) */
1008
1009int
1010face_name_id_number (f, name)
1011 FRAME_PTR f;
1012 Lisp_Object name;
1013{
1014 Lisp_Object tem;
1015
1016 tem = Fcdr (assq_no_quit (name, f->face_alist));
1017 if (NILP (tem))
1018 return 0;
1019 CHECK_VECTOR (tem, 0);
1020 tem = XVECTOR (tem)->contents[2];
1021 CHECK_NUMBER (tem, 0);
1022 return XINT (tem);
1023}
1024
1025/* Emacs initialization. */
1026
1027void
1028syms_of_win32faces ()
1029{
1030 Qface = intern ("face");
1031 staticpro (&Qface);
1032 Qmouse_face = intern ("mouse-face");
1033 staticpro (&Qmouse_face);
1034 Qpixmap_spec_p = intern ("pixmap-spec-p");
1035 staticpro (&Qpixmap_spec_p);
1036
1037 DEFVAR_INT ("region-face", &region_face,
1038 "Face number to use to highlight the region\n\
1039The region is highlighted with this face\n\
1040when Transient Mark mode is enabled and the mark is active.");
1041
1042 defsubr (&Spixmap_spec_p);
1043 defsubr (&Sframe_face_alist);
1044 defsubr (&Sset_frame_face_alist);
1045 defsubr (&Smake_face_internal);
1046 defsubr (&Sset_face_attribute_internal);
1047 defsubr (&Sinternal_next_face_id);
1048}
diff --git a/src/w32fns.c b/src/w32fns.c
new file mode 100644
index 00000000000..22a5149c72d
--- /dev/null
+++ b/src/w32fns.c
@@ -0,0 +1,4308 @@
1/* Functions for the Win32 window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* Added by Kevin Gallo */
21
22#include <signal.h>
23#include <config.h>
24#include <stdio.h>
25
26#include "lisp.h"
27#include "w32term.h"
28#include "frame.h"
29#include "window.h"
30#include "buffer.h"
31#include "dispextern.h"
32#include "keyboard.h"
33#include "blockinput.h"
34#include "paths.h"
35#include "ntheap.h"
36#include "termhooks.h"
37
38#include <commdlg.h>
39
40extern void abort ();
41extern void free_frame_menubar ();
42extern struct scroll_bar *x_window_to_scroll_bar ();
43
44/* The colormap for converting color names to RGB values */
45Lisp_Object Vwin32_color_map;
46
47/* The name we're using in resource queries. */
48Lisp_Object Vx_resource_name;
49
50/* Non nil if no window manager is in use. */
51Lisp_Object Vx_no_window_manager;
52
53/* The background and shape of the mouse pointer, and shape when not
54 over text or in the modeline. */
55Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
56/* The shape when over mouse-sensitive text. */
57Lisp_Object Vx_sensitive_text_pointer_shape;
58
59/* Color of chars displayed in cursor box. */
60Lisp_Object Vx_cursor_fore_pixel;
61
62/* Search path for bitmap files. */
63Lisp_Object Vx_bitmap_file_path;
64
65/* Evaluate this expression to rebuild the section of syms_of_w32fns
66 that initializes and staticpros the symbols declared below. Note
67 that Emacs 18 has a bug that keeps C-x C-e from being able to
68 evaluate this expression.
69
70(progn
71 ;; Accumulate a list of the symbols we want to initialize from the
72 ;; declarations at the top of the file.
73 (goto-char (point-min))
74 (search-forward "/\*&&& symbols declared here &&&*\/\n")
75 (let (symbol-list)
76 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
77 (setq symbol-list
78 (cons (buffer-substring (match-beginning 1) (match-end 1))
79 symbol-list))
80 (forward-line 1))
81 (setq symbol-list (nreverse symbol-list))
82 ;; Delete the section of syms_of_... where we initialize the symbols.
83 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
84 (let ((start (point)))
85 (while (looking-at "^ Q")
86 (forward-line 2))
87 (kill-region start (point)))
88 ;; Write a new symbol initialization section.
89 (while symbol-list
90 (insert (format " %s = intern (\"" (car symbol-list)))
91 (let ((start (point)))
92 (insert (substring (car symbol-list) 1))
93 (subst-char-in-region start (point) ?_ ?-))
94 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
95 (setq symbol-list (cdr symbol-list)))))
96
97 */
98
99/*&&& symbols declared here &&&*/
100Lisp_Object Qauto_raise;
101Lisp_Object Qauto_lower;
102Lisp_Object Qbackground_color;
103Lisp_Object Qbar;
104Lisp_Object Qborder_color;
105Lisp_Object Qborder_width;
106Lisp_Object Qbox;
107Lisp_Object Qcursor_color;
108Lisp_Object Qcursor_type;
109Lisp_Object Qfont;
110Lisp_Object Qforeground_color;
111Lisp_Object Qgeometry;
112Lisp_Object Qicon_left;
113Lisp_Object Qicon_top;
114Lisp_Object Qicon_type;
115Lisp_Object Qicon_name;
116Lisp_Object Qinternal_border_width;
117Lisp_Object Qleft;
118Lisp_Object Qmouse_color;
119Lisp_Object Qnone;
120Lisp_Object Qparent_id;
121Lisp_Object Qscroll_bar_width;
122Lisp_Object Qsuppress_icon;
123Lisp_Object Qtop;
124Lisp_Object Qundefined_color;
125Lisp_Object Qvertical_scroll_bars;
126Lisp_Object Qvisibility;
127Lisp_Object Qwindow_id;
128Lisp_Object Qx_frame_parameter;
129Lisp_Object Qx_resource_name;
130Lisp_Object Quser_position;
131Lisp_Object Quser_size;
132Lisp_Object Qdisplay;
133
134/* The below are defined in frame.c. */
135extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
136extern Lisp_Object Qunsplittable, Qmenu_bar_lines;
137
138extern Lisp_Object Vwindow_system_version;
139
140extern Lisp_Object last_mouse_scroll_bar;
141extern int last_mouse_scroll_bar_pos;
142Time last_mouse_movement_time;
143
144
145/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
146 and checking validity for Win32. */
147
148FRAME_PTR
149check_x_frame (frame)
150 Lisp_Object frame;
151{
152 FRAME_PTR f;
153
154 if (NILP (frame))
155 f = selected_frame;
156 else
157 {
158 CHECK_LIVE_FRAME (frame, 0);
159 f = XFRAME (frame);
160 }
161 if (! FRAME_WIN32_P (f))
162 error ("non-win32 frame used");
163 return f;
164}
165
166/* Let the user specify an display with a frame.
167 nil stands for the selected frame--or, if that is not a win32 frame,
168 the first display on the list. */
169
170static struct win32_display_info *
171check_x_display_info (frame)
172 Lisp_Object frame;
173{
174 if (NILP (frame))
175 {
176 if (FRAME_WIN32_P (selected_frame))
177 return FRAME_WIN32_DISPLAY_INFO (selected_frame);
178 else
179 return &one_win32_display_info;
180 }
181 else if (STRINGP (frame))
182 return x_display_info_for_name (frame);
183 else
184 {
185 FRAME_PTR f;
186
187 CHECK_LIVE_FRAME (frame, 0);
188 f = XFRAME (frame);
189 if (! FRAME_WIN32_P (f))
190 error ("non-win32 frame used");
191 return FRAME_WIN32_DISPLAY_INFO (f);
192 }
193}
194
195/* Return the Emacs frame-object corresponding to an win32 window.
196 It could be the frame's main window or an icon window. */
197
198/* This function can be called during GC, so use GC_xxx type test macros. */
199
200struct frame *
201x_window_to_frame (dpyinfo, wdesc)
202 struct win32_display_info *dpyinfo;
203 HWND wdesc;
204{
205 Lisp_Object tail, frame;
206 struct frame *f;
207
208 for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
209 {
210 frame = XCONS (tail)->car;
211 if (!GC_FRAMEP (frame))
212 continue;
213 f = XFRAME (frame);
214 if (f->output_data.nothing == 1
215 || FRAME_WIN32_DISPLAY_INFO (f) != dpyinfo)
216 continue;
217 if (FRAME_WIN32_WINDOW (f) == wdesc)
218 return f;
219 }
220 return 0;
221}
222
223
224
225/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
226 id, which is just an int that this section returns. Bitmaps are
227 reference counted so they can be shared among frames.
228
229 Bitmap indices are guaranteed to be > 0, so a negative number can
230 be used to indicate no bitmap.
231
232 If you use x_create_bitmap_from_data, then you must keep track of
233 the bitmaps yourself. That is, creating a bitmap from the same
234 data more than once will not be caught. */
235
236
237/* Functions to access the contents of a bitmap, given an id. */
238
239int
240x_bitmap_height (f, id)
241 FRAME_PTR f;
242 int id;
243{
244 return FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
245}
246
247int
248x_bitmap_width (f, id)
249 FRAME_PTR f;
250 int id;
251{
252 return FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
253}
254
255int
256x_bitmap_pixmap (f, id)
257 FRAME_PTR f;
258 int id;
259{
260 return (int) FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
261}
262
263
264/* Allocate a new bitmap record. Returns index of new record. */
265
266static int
267x_allocate_bitmap_record (f)
268 FRAME_PTR f;
269{
270 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
271 int i;
272
273 if (dpyinfo->bitmaps == NULL)
274 {
275 dpyinfo->bitmaps_size = 10;
276 dpyinfo->bitmaps
277 = (struct win32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct win32_bitmap_record));
278 dpyinfo->bitmaps_last = 1;
279 return 1;
280 }
281
282 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
283 return ++dpyinfo->bitmaps_last;
284
285 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
286 if (dpyinfo->bitmaps[i].refcount == 0)
287 return i + 1;
288
289 dpyinfo->bitmaps_size *= 2;
290 dpyinfo->bitmaps
291 = (struct win32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
292 dpyinfo->bitmaps_size * sizeof (struct win32_bitmap_record));
293 return ++dpyinfo->bitmaps_last;
294}
295
296/* Add one reference to the reference count of the bitmap with id ID. */
297
298void
299x_reference_bitmap (f, id)
300 FRAME_PTR f;
301 int id;
302{
303 ++FRAME_WIN32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
304}
305
306/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
307
308int
309x_create_bitmap_from_data (f, bits, width, height)
310 struct frame *f;
311 char *bits;
312 unsigned int width, height;
313{
314 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
315 Pixmap bitmap;
316 int id;
317
318 bitmap = CreateBitmap (width, height,
319 FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_planes,
320 FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
321 bits);
322
323 if (! bitmap)
324 return -1;
325
326 id = x_allocate_bitmap_record (f);
327 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
328 dpyinfo->bitmaps[id - 1].file = NULL;
329 dpyinfo->bitmaps[id - 1].hinst = NULL;
330 dpyinfo->bitmaps[id - 1].refcount = 1;
331 dpyinfo->bitmaps[id - 1].depth = 1;
332 dpyinfo->bitmaps[id - 1].height = height;
333 dpyinfo->bitmaps[id - 1].width = width;
334
335 return id;
336}
337
338/* Create bitmap from file FILE for frame F. */
339
340int
341x_create_bitmap_from_file (f, file)
342 struct frame *f;
343 Lisp_Object file;
344{
345 return -1;
346#if 0
347 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
348 unsigned int width, height;
349 Pixmap bitmap;
350 int xhot, yhot, result, id;
351 Lisp_Object found;
352 int fd;
353 char *filename;
354 HINSTANCE hinst;
355
356 /* Look for an existing bitmap with the same name. */
357 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
358 {
359 if (dpyinfo->bitmaps[id].refcount
360 && dpyinfo->bitmaps[id].file
361 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
362 {
363 ++dpyinfo->bitmaps[id].refcount;
364 return id + 1;
365 }
366 }
367
368 /* Search bitmap-file-path for the file, if appropriate. */
369 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
370 if (fd < 0)
371 return -1;
372 close (fd);
373
374 filename = (char *) XSTRING (found)->data;
375
376 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
377
378 if (hinst == NULL)
379 return -1;
380
381
382 result = XReadBitmapFile (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f),
383 filename, &width, &height, &bitmap, &xhot, &yhot);
384 if (result != BitmapSuccess)
385 return -1;
386
387 id = x_allocate_bitmap_record (f);
388 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
389 dpyinfo->bitmaps[id - 1].refcount = 1;
390 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
391 dpyinfo->bitmaps[id - 1].depth = 1;
392 dpyinfo->bitmaps[id - 1].height = height;
393 dpyinfo->bitmaps[id - 1].width = width;
394 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
395
396 return id;
397#endif
398}
399
400/* Remove reference to bitmap with id number ID. */
401
402int
403x_destroy_bitmap (f, id)
404 FRAME_PTR f;
405 int id;
406{
407 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
408
409 if (id > 0)
410 {
411 --dpyinfo->bitmaps[id - 1].refcount;
412 if (dpyinfo->bitmaps[id - 1].refcount == 0)
413 {
414 BLOCK_INPUT;
415 DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
416 if (dpyinfo->bitmaps[id - 1].file)
417 {
418 free (dpyinfo->bitmaps[id - 1].file);
419 dpyinfo->bitmaps[id - 1].file = NULL;
420 }
421 UNBLOCK_INPUT;
422 }
423 }
424}
425
426/* Free all the bitmaps for the display specified by DPYINFO. */
427
428static void
429x_destroy_all_bitmaps (dpyinfo)
430 struct win32_display_info *dpyinfo;
431{
432 int i;
433 for (i = 0; i < dpyinfo->bitmaps_last; i++)
434 if (dpyinfo->bitmaps[i].refcount > 0)
435 {
436 DeleteObject (dpyinfo->bitmaps[i].pixmap);
437 if (dpyinfo->bitmaps[i].file)
438 free (dpyinfo->bitmaps[i].file);
439 }
440 dpyinfo->bitmaps_last = 0;
441}
442
443/* Connect the frame-parameter names for Win32 frames
444 to the ways of passing the parameter values to the window system.
445
446 The name of a parameter, as a Lisp symbol,
447 has an `x-frame-parameter' property which is an integer in Lisp
448 but can be interpreted as an `enum x_frame_parm' in C. */
449
450enum x_frame_parm
451{
452 X_PARM_FOREGROUND_COLOR,
453 X_PARM_BACKGROUND_COLOR,
454 X_PARM_MOUSE_COLOR,
455 X_PARM_CURSOR_COLOR,
456 X_PARM_BORDER_COLOR,
457 X_PARM_ICON_TYPE,
458 X_PARM_FONT,
459 X_PARM_BORDER_WIDTH,
460 X_PARM_INTERNAL_BORDER_WIDTH,
461 X_PARM_NAME,
462 X_PARM_AUTORAISE,
463 X_PARM_AUTOLOWER,
464 X_PARM_VERT_SCROLL_BAR,
465 X_PARM_VISIBILITY,
466 X_PARM_MENU_BAR_LINES
467};
468
469
470struct x_frame_parm_table
471{
472 char *name;
473 void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
474};
475
476void x_set_foreground_color ();
477void x_set_background_color ();
478void x_set_mouse_color ();
479void x_set_cursor_color ();
480void x_set_border_color ();
481void x_set_cursor_type ();
482void x_set_icon_type ();
483void x_set_icon_name ();
484void x_set_font ();
485void x_set_border_width ();
486void x_set_internal_border_width ();
487void x_explicitly_set_name ();
488void x_set_autoraise ();
489void x_set_autolower ();
490void x_set_vertical_scroll_bars ();
491void x_set_visibility ();
492void x_set_menu_bar_lines ();
493void x_set_scroll_bar_width ();
494void x_set_unsplittable ();
495
496static struct x_frame_parm_table x_frame_parms[] =
497{
498 "foreground-color", x_set_foreground_color,
499 "background-color", x_set_background_color,
500 "mouse-color", x_set_mouse_color,
501 "cursor-color", x_set_cursor_color,
502 "border-color", x_set_border_color,
503 "cursor-type", x_set_cursor_type,
504 "icon-type", x_set_icon_type,
505 "icon-name", x_set_icon_name,
506 "font", x_set_font,
507 "border-width", x_set_border_width,
508 "internal-border-width", x_set_internal_border_width,
509 "name", x_explicitly_set_name,
510 "auto-raise", x_set_autoraise,
511 "auto-lower", x_set_autolower,
512 "vertical-scroll-bars", x_set_vertical_scroll_bars,
513 "visibility", x_set_visibility,
514 "menu-bar-lines", x_set_menu_bar_lines,
515 "scroll-bar-width", x_set_scroll_bar_width,
516 "unsplittable", x_set_unsplittable,
517};
518
519/* Attach the `x-frame-parameter' properties to
520 the Lisp symbol names of parameters relevant to Win32. */
521
522init_x_parm_symbols ()
523{
524 int i;
525
526 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
527 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
528 make_number (i));
529}
530
531/* Change the parameters of FRAME as specified by ALIST.
532 If a parameter is not specially recognized, do nothing;
533 otherwise call the `x_set_...' function for that parameter. */
534
535void
536x_set_frame_parameters (f, alist)
537 FRAME_PTR f;
538 Lisp_Object alist;
539{
540 Lisp_Object tail;
541
542 /* If both of these parameters are present, it's more efficient to
543 set them both at once. So we wait until we've looked at the
544 entire list before we set them. */
545 Lisp_Object width, height;
546
547 /* Same here. */
548 Lisp_Object left, top;
549
550 /* Same with these. */
551 Lisp_Object icon_left, icon_top;
552
553 /* Record in these vectors all the parms specified. */
554 Lisp_Object *parms;
555 Lisp_Object *values;
556 int i;
557 int left_no_change = 0, top_no_change = 0;
558 int icon_left_no_change = 0, icon_top_no_change = 0;
559
560 i = 0;
561 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
562 i++;
563
564 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
565 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
566
567 /* Extract parm names and values into those vectors. */
568
569 i = 0;
570 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
571 {
572 Lisp_Object elt, prop, val;
573
574 elt = Fcar (tail);
575 parms[i] = Fcar (elt);
576 values[i] = Fcdr (elt);
577 i++;
578 }
579
580 width = height = top = left = Qunbound;
581 icon_left = icon_top = Qunbound;
582
583 /* Now process them in reverse of specified order. */
584 for (i--; i >= 0; i--)
585 {
586 Lisp_Object prop, val;
587
588 prop = parms[i];
589 val = values[i];
590
591 if (EQ (prop, Qwidth))
592 width = val;
593 else if (EQ (prop, Qheight))
594 height = val;
595 else if (EQ (prop, Qtop))
596 top = val;
597 else if (EQ (prop, Qleft))
598 left = val;
599 else if (EQ (prop, Qicon_top))
600 icon_top = val;
601 else if (EQ (prop, Qicon_left))
602 icon_left = val;
603 else
604 {
605 register Lisp_Object param_index, old_value;
606
607 param_index = Fget (prop, Qx_frame_parameter);
608 old_value = get_frame_param (f, prop);
609 store_frame_param (f, prop, val);
610 if (NATNUMP (param_index)
611 && (XFASTINT (param_index)
612 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
613 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
614 }
615 }
616
617 /* Don't die if just one of these was set. */
618 if (EQ (left, Qunbound))
619 {
620 left_no_change = 1;
621 if (f->output_data.win32->left_pos < 0)
622 left = Fcons (Qplus, Fcons (make_number (f->output_data.win32->left_pos), Qnil));
623 else
624 XSETINT (left, f->output_data.win32->left_pos);
625 }
626 if (EQ (top, Qunbound))
627 {
628 top_no_change = 1;
629 if (f->output_data.win32->top_pos < 0)
630 top = Fcons (Qplus, Fcons (make_number (f->output_data.win32->top_pos), Qnil));
631 else
632 XSETINT (top, f->output_data.win32->top_pos);
633 }
634
635 /* If one of the icon positions was not set, preserve or default it. */
636 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
637 {
638 icon_left_no_change = 1;
639 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
640 if (NILP (icon_left))
641 XSETINT (icon_left, 0);
642 }
643 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
644 {
645 icon_top_no_change = 1;
646 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
647 if (NILP (icon_top))
648 XSETINT (icon_top, 0);
649 }
650
651 /* Don't die if just one of these was set. */
652 if (EQ (width, Qunbound))
653 XSETINT (width, FRAME_WIDTH (f));
654 if (EQ (height, Qunbound))
655 XSETINT (height, FRAME_HEIGHT (f));
656
657 /* Don't set these parameters unless they've been explicitly
658 specified. The window might be mapped or resized while we're in
659 this function, and we don't want to override that unless the lisp
660 code has asked for it.
661
662 Don't set these parameters unless they actually differ from the
663 window's current parameters; the window may not actually exist
664 yet. */
665 {
666 Lisp_Object frame;
667
668 check_frame_size (f, &height, &width);
669
670 XSETFRAME (frame, f);
671
672 if ((NUMBERP (width) && XINT (width) != FRAME_WIDTH (f))
673 || (NUMBERP (height) && XINT (height) != FRAME_HEIGHT (f)))
674 Fset_frame_size (frame, width, height);
675
676 if ((!NILP (left) || !NILP (top))
677 && ! (left_no_change && top_no_change)
678 && ! (NUMBERP (left) && XINT (left) == f->output_data.win32->left_pos
679 && NUMBERP (top) && XINT (top) == f->output_data.win32->top_pos))
680 {
681 int leftpos = 0;
682 int toppos = 0;
683
684 /* Record the signs. */
685 f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
686 if (EQ (left, Qminus))
687 f->output_data.win32->size_hint_flags |= XNegative;
688 else if (INTEGERP (left))
689 {
690 leftpos = XINT (left);
691 if (leftpos < 0)
692 f->output_data.win32->size_hint_flags |= XNegative;
693 }
694 else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
695 && CONSP (XCONS (left)->cdr)
696 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
697 {
698 leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
699 f->output_data.win32->size_hint_flags |= XNegative;
700 }
701 else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
702 && CONSP (XCONS (left)->cdr)
703 && INTEGERP (XCONS (XCONS (left)->cdr)->car))
704 {
705 leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
706 }
707
708 if (EQ (top, Qminus))
709 f->output_data.win32->size_hint_flags |= YNegative;
710 else if (INTEGERP (top))
711 {
712 toppos = XINT (top);
713 if (toppos < 0)
714 f->output_data.win32->size_hint_flags |= YNegative;
715 }
716 else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
717 && CONSP (XCONS (top)->cdr)
718 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
719 {
720 toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
721 f->output_data.win32->size_hint_flags |= YNegative;
722 }
723 else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
724 && CONSP (XCONS (top)->cdr)
725 && INTEGERP (XCONS (XCONS (top)->cdr)->car))
726 {
727 toppos = XINT (XCONS (XCONS (top)->cdr)->car);
728 }
729
730
731 /* Store the numeric value of the position. */
732 f->output_data.win32->top_pos = toppos;
733 f->output_data.win32->left_pos = leftpos;
734
735 f->output_data.win32->win_gravity = NorthWestGravity;
736
737 /* Actually set that position, and convert to absolute. */
738 x_set_offset (f, leftpos, toppos, -1);
739 }
740
741 if ((!NILP (icon_left) || !NILP (icon_top))
742 && ! (icon_left_no_change && icon_top_no_change))
743 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
744 }
745}
746
747/* Store the screen positions of frame F into XPTR and YPTR.
748 These are the positions of the containing window manager window,
749 not Emacs's own window. */
750
751void
752x_real_positions (f, xptr, yptr)
753 FRAME_PTR f;
754 int *xptr, *yptr;
755{
756 POINT pt;
757
758 {
759 RECT rect;
760
761 GetClientRect(FRAME_WIN32_WINDOW(f), &rect);
762 AdjustWindowRect(&rect, f->output_data.win32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
763
764 pt.x = rect.left;
765 pt.y = rect.top;
766 }
767
768 ClientToScreen (FRAME_WIN32_WINDOW(f), &pt);
769
770 *xptr = pt.x;
771 *yptr = pt.y;
772}
773
774/* Insert a description of internally-recorded parameters of frame X
775 into the parameter alist *ALISTPTR that is to be given to the user.
776 Only parameters that are specific to Win32
777 and whose values are not correctly recorded in the frame's
778 param_alist need to be considered here. */
779
780x_report_frame_params (f, alistptr)
781 struct frame *f;
782 Lisp_Object *alistptr;
783{
784 char buf[16];
785 Lisp_Object tem;
786
787 /* Represent negative positions (off the top or left screen edge)
788 in a way that Fmodify_frame_parameters will understand correctly. */
789 XSETINT (tem, f->output_data.win32->left_pos);
790 if (f->output_data.win32->left_pos >= 0)
791 store_in_alist (alistptr, Qleft, tem);
792 else
793 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
794
795 XSETINT (tem, f->output_data.win32->top_pos);
796 if (f->output_data.win32->top_pos >= 0)
797 store_in_alist (alistptr, Qtop, tem);
798 else
799 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
800
801 store_in_alist (alistptr, Qborder_width,
802 make_number (f->output_data.win32->border_width));
803 store_in_alist (alistptr, Qinternal_border_width,
804 make_number (f->output_data.win32->internal_border_width));
805 sprintf (buf, "%ld", (long) FRAME_WIN32_WINDOW (f));
806 store_in_alist (alistptr, Qwindow_id,
807 build_string (buf));
808 store_in_alist (alistptr, Qicon_name, f->icon_name);
809 FRAME_SAMPLE_VISIBILITY (f);
810 store_in_alist (alistptr, Qvisibility,
811 (FRAME_VISIBLE_P (f) ? Qt
812 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
813 store_in_alist (alistptr, Qdisplay,
814 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->car);
815}
816
817
818#if 0
819DEFUN ("win32-rgb", Fwin32_rgb, Swin32_rgb, 3, 3, 0,
820 "Convert RGB numbers to a windows color reference.")
821 (red, green, blue)
822 Lisp_Object red, green, blue;
823{
824 Lisp_Object rgb;
825
826 CHECK_NUMBER (red, 0);
827 CHECK_NUMBER (green, 0);
828 CHECK_NUMBER (blue, 0);
829
830 XSET (rgb, Lisp_Int, RGB(XUINT(red), XUINT(green), XUINT(blue)));
831
832 return (rgb);
833}
834
835
836#else
837/* The default colors for the win32 color map */
838typedef struct colormap_t
839{
840 char *name;
841 COLORREF colorref;
842} colormap_t;
843
844colormap_t win32_color_map[] =
845{
846 {"snow" , RGB (255,250,250)},
847 {"ghost white" , RGB (248,248,255)},
848 {"GhostWhite" , RGB (248,248,255)},
849 {"white smoke" , RGB (245,245,245)},
850 {"WhiteSmoke" , RGB (245,245,245)},
851 {"gainsboro" , RGB (220,220,220)},
852 {"floral white" , RGB (255,250,240)},
853 {"FloralWhite" , RGB (255,250,240)},
854 {"old lace" , RGB (253,245,230)},
855 {"OldLace" , RGB (253,245,230)},
856 {"linen" , RGB (250,240,230)},
857 {"antique white" , RGB (250,235,215)},
858 {"AntiqueWhite" , RGB (250,235,215)},
859 {"papaya whip" , RGB (255,239,213)},
860 {"PapayaWhip" , RGB (255,239,213)},
861 {"blanched almond" , RGB (255,235,205)},
862 {"BlanchedAlmond" , RGB (255,235,205)},
863 {"bisque" , RGB (255,228,196)},
864 {"peach puff" , RGB (255,218,185)},
865 {"PeachPuff" , RGB (255,218,185)},
866 {"navajo white" , RGB (255,222,173)},
867 {"NavajoWhite" , RGB (255,222,173)},
868 {"moccasin" , RGB (255,228,181)},
869 {"cornsilk" , RGB (255,248,220)},
870 {"ivory" , RGB (255,255,240)},
871 {"lemon chiffon" , RGB (255,250,205)},
872 {"LemonChiffon" , RGB (255,250,205)},
873 {"seashell" , RGB (255,245,238)},
874 {"honeydew" , RGB (240,255,240)},
875 {"mint cream" , RGB (245,255,250)},
876 {"MintCream" , RGB (245,255,250)},
877 {"azure" , RGB (240,255,255)},
878 {"alice blue" , RGB (240,248,255)},
879 {"AliceBlue" , RGB (240,248,255)},
880 {"lavender" , RGB (230,230,250)},
881 {"lavender blush" , RGB (255,240,245)},
882 {"LavenderBlush" , RGB (255,240,245)},
883 {"misty rose" , RGB (255,228,225)},
884 {"MistyRose" , RGB (255,228,225)},
885 {"white" , RGB (255,255,255)},
886 {"black" , RGB ( 0, 0, 0)},
887 {"dark slate gray" , RGB ( 47, 79, 79)},
888 {"DarkSlateGray" , RGB ( 47, 79, 79)},
889 {"dark slate grey" , RGB ( 47, 79, 79)},
890 {"DarkSlateGrey" , RGB ( 47, 79, 79)},
891 {"dim gray" , RGB (105,105,105)},
892 {"DimGray" , RGB (105,105,105)},
893 {"dim grey" , RGB (105,105,105)},
894 {"DimGrey" , RGB (105,105,105)},
895 {"slate gray" , RGB (112,128,144)},
896 {"SlateGray" , RGB (112,128,144)},
897 {"slate grey" , RGB (112,128,144)},
898 {"SlateGrey" , RGB (112,128,144)},
899 {"light slate gray" , RGB (119,136,153)},
900 {"LightSlateGray" , RGB (119,136,153)},
901 {"light slate grey" , RGB (119,136,153)},
902 {"LightSlateGrey" , RGB (119,136,153)},
903 {"gray" , RGB (190,190,190)},
904 {"grey" , RGB (190,190,190)},
905 {"light grey" , RGB (211,211,211)},
906 {"LightGrey" , RGB (211,211,211)},
907 {"light gray" , RGB (211,211,211)},
908 {"LightGray" , RGB (211,211,211)},
909 {"midnight blue" , RGB ( 25, 25,112)},
910 {"MidnightBlue" , RGB ( 25, 25,112)},
911 {"navy" , RGB ( 0, 0,128)},
912 {"navy blue" , RGB ( 0, 0,128)},
913 {"NavyBlue" , RGB ( 0, 0,128)},
914 {"cornflower blue" , RGB (100,149,237)},
915 {"CornflowerBlue" , RGB (100,149,237)},
916 {"dark slate blue" , RGB ( 72, 61,139)},
917 {"DarkSlateBlue" , RGB ( 72, 61,139)},
918 {"slate blue" , RGB (106, 90,205)},
919 {"SlateBlue" , RGB (106, 90,205)},
920 {"medium slate blue" , RGB (123,104,238)},
921 {"MediumSlateBlue" , RGB (123,104,238)},
922 {"light slate blue" , RGB (132,112,255)},
923 {"LightSlateBlue" , RGB (132,112,255)},
924 {"medium blue" , RGB ( 0, 0,205)},
925 {"MediumBlue" , RGB ( 0, 0,205)},
926 {"royal blue" , RGB ( 65,105,225)},
927 {"RoyalBlue" , RGB ( 65,105,225)},
928 {"blue" , RGB ( 0, 0,255)},
929 {"dodger blue" , RGB ( 30,144,255)},
930 {"DodgerBlue" , RGB ( 30,144,255)},
931 {"deep sky blue" , RGB ( 0,191,255)},
932 {"DeepSkyBlue" , RGB ( 0,191,255)},
933 {"sky blue" , RGB (135,206,235)},
934 {"SkyBlue" , RGB (135,206,235)},
935 {"light sky blue" , RGB (135,206,250)},
936 {"LightSkyBlue" , RGB (135,206,250)},
937 {"steel blue" , RGB ( 70,130,180)},
938 {"SteelBlue" , RGB ( 70,130,180)},
939 {"light steel blue" , RGB (176,196,222)},
940 {"LightSteelBlue" , RGB (176,196,222)},
941 {"light blue" , RGB (173,216,230)},
942 {"LightBlue" , RGB (173,216,230)},
943 {"powder blue" , RGB (176,224,230)},
944 {"PowderBlue" , RGB (176,224,230)},
945 {"pale turquoise" , RGB (175,238,238)},
946 {"PaleTurquoise" , RGB (175,238,238)},
947 {"dark turquoise" , RGB ( 0,206,209)},
948 {"DarkTurquoise" , RGB ( 0,206,209)},
949 {"medium turquoise" , RGB ( 72,209,204)},
950 {"MediumTurquoise" , RGB ( 72,209,204)},
951 {"turquoise" , RGB ( 64,224,208)},
952 {"cyan" , RGB ( 0,255,255)},
953 {"light cyan" , RGB (224,255,255)},
954 {"LightCyan" , RGB (224,255,255)},
955 {"cadet blue" , RGB ( 95,158,160)},
956 {"CadetBlue" , RGB ( 95,158,160)},
957 {"medium aquamarine" , RGB (102,205,170)},
958 {"MediumAquamarine" , RGB (102,205,170)},
959 {"aquamarine" , RGB (127,255,212)},
960 {"dark green" , RGB ( 0,100, 0)},
961 {"DarkGreen" , RGB ( 0,100, 0)},
962 {"dark olive green" , RGB ( 85,107, 47)},
963 {"DarkOliveGreen" , RGB ( 85,107, 47)},
964 {"dark sea green" , RGB (143,188,143)},
965 {"DarkSeaGreen" , RGB (143,188,143)},
966 {"sea green" , RGB ( 46,139, 87)},
967 {"SeaGreen" , RGB ( 46,139, 87)},
968 {"medium sea green" , RGB ( 60,179,113)},
969 {"MediumSeaGreen" , RGB ( 60,179,113)},
970 {"light sea green" , RGB ( 32,178,170)},
971 {"LightSeaGreen" , RGB ( 32,178,170)},
972 {"pale green" , RGB (152,251,152)},
973 {"PaleGreen" , RGB (152,251,152)},
974 {"spring green" , RGB ( 0,255,127)},
975 {"SpringGreen" , RGB ( 0,255,127)},
976 {"lawn green" , RGB (124,252, 0)},
977 {"LawnGreen" , RGB (124,252, 0)},
978 {"green" , RGB ( 0,255, 0)},
979 {"chartreuse" , RGB (127,255, 0)},
980 {"medium spring green" , RGB ( 0,250,154)},
981 {"MediumSpringGreen" , RGB ( 0,250,154)},
982 {"green yellow" , RGB (173,255, 47)},
983 {"GreenYellow" , RGB (173,255, 47)},
984 {"lime green" , RGB ( 50,205, 50)},
985 {"LimeGreen" , RGB ( 50,205, 50)},
986 {"yellow green" , RGB (154,205, 50)},
987 {"YellowGreen" , RGB (154,205, 50)},
988 {"forest green" , RGB ( 34,139, 34)},
989 {"ForestGreen" , RGB ( 34,139, 34)},
990 {"olive drab" , RGB (107,142, 35)},
991 {"OliveDrab" , RGB (107,142, 35)},
992 {"dark khaki" , RGB (189,183,107)},
993 {"DarkKhaki" , RGB (189,183,107)},
994 {"khaki" , RGB (240,230,140)},
995 {"pale goldenrod" , RGB (238,232,170)},
996 {"PaleGoldenrod" , RGB (238,232,170)},
997 {"light goldenrod yellow" , RGB (250,250,210)},
998 {"LightGoldenrodYellow" , RGB (250,250,210)},
999 {"light yellow" , RGB (255,255,224)},
1000 {"LightYellow" , RGB (255,255,224)},
1001 {"yellow" , RGB (255,255, 0)},
1002 {"gold" , RGB (255,215, 0)},
1003 {"light goldenrod" , RGB (238,221,130)},
1004 {"LightGoldenrod" , RGB (238,221,130)},
1005 {"goldenrod" , RGB (218,165, 32)},
1006 {"dark goldenrod" , RGB (184,134, 11)},
1007 {"DarkGoldenrod" , RGB (184,134, 11)},
1008 {"rosy brown" , RGB (188,143,143)},
1009 {"RosyBrown" , RGB (188,143,143)},
1010 {"indian red" , RGB (205, 92, 92)},
1011 {"IndianRed" , RGB (205, 92, 92)},
1012 {"saddle brown" , RGB (139, 69, 19)},
1013 {"SaddleBrown" , RGB (139, 69, 19)},
1014 {"sienna" , RGB (160, 82, 45)},
1015 {"peru" , RGB (205,133, 63)},
1016 {"burlywood" , RGB (222,184,135)},
1017 {"beige" , RGB (245,245,220)},
1018 {"wheat" , RGB (245,222,179)},
1019 {"sandy brown" , RGB (244,164, 96)},
1020 {"SandyBrown" , RGB (244,164, 96)},
1021 {"tan" , RGB (210,180,140)},
1022 {"chocolate" , RGB (210,105, 30)},
1023 {"firebrick" , RGB (178,34, 34)},
1024 {"brown" , RGB (165,42, 42)},
1025 {"dark salmon" , RGB (233,150,122)},
1026 {"DarkSalmon" , RGB (233,150,122)},
1027 {"salmon" , RGB (250,128,114)},
1028 {"light salmon" , RGB (255,160,122)},
1029 {"LightSalmon" , RGB (255,160,122)},
1030 {"orange" , RGB (255,165, 0)},
1031 {"dark orange" , RGB (255,140, 0)},
1032 {"DarkOrange" , RGB (255,140, 0)},
1033 {"coral" , RGB (255,127, 80)},
1034 {"light coral" , RGB (240,128,128)},
1035 {"LightCoral" , RGB (240,128,128)},
1036 {"tomato" , RGB (255, 99, 71)},
1037 {"orange red" , RGB (255, 69, 0)},
1038 {"OrangeRed" , RGB (255, 69, 0)},
1039 {"red" , RGB (255, 0, 0)},
1040 {"hot pink" , RGB (255,105,180)},
1041 {"HotPink" , RGB (255,105,180)},
1042 {"deep pink" , RGB (255, 20,147)},
1043 {"DeepPink" , RGB (255, 20,147)},
1044 {"pink" , RGB (255,192,203)},
1045 {"light pink" , RGB (255,182,193)},
1046 {"LightPink" , RGB (255,182,193)},
1047 {"pale violet red" , RGB (219,112,147)},
1048 {"PaleVioletRed" , RGB (219,112,147)},
1049 {"maroon" , RGB (176, 48, 96)},
1050 {"medium violet red" , RGB (199, 21,133)},
1051 {"MediumVioletRed" , RGB (199, 21,133)},
1052 {"violet red" , RGB (208, 32,144)},
1053 {"VioletRed" , RGB (208, 32,144)},
1054 {"magenta" , RGB (255, 0,255)},
1055 {"violet" , RGB (238,130,238)},
1056 {"plum" , RGB (221,160,221)},
1057 {"orchid" , RGB (218,112,214)},
1058 {"medium orchid" , RGB (186, 85,211)},
1059 {"MediumOrchid" , RGB (186, 85,211)},
1060 {"dark orchid" , RGB (153, 50,204)},
1061 {"DarkOrchid" , RGB (153, 50,204)},
1062 {"dark violet" , RGB (148, 0,211)},
1063 {"DarkViolet" , RGB (148, 0,211)},
1064 {"blue violet" , RGB (138, 43,226)},
1065 {"BlueViolet" , RGB (138, 43,226)},
1066 {"purple" , RGB (160, 32,240)},
1067 {"medium purple" , RGB (147,112,219)},
1068 {"MediumPurple" , RGB (147,112,219)},
1069 {"thistle" , RGB (216,191,216)},
1070 {"gray0" , RGB ( 0, 0, 0)},
1071 {"grey0" , RGB ( 0, 0, 0)},
1072 {"dark grey" , RGB (169,169,169)},
1073 {"DarkGrey" , RGB (169,169,169)},
1074 {"dark gray" , RGB (169,169,169)},
1075 {"DarkGray" , RGB (169,169,169)},
1076 {"dark blue" , RGB ( 0, 0,139)},
1077 {"DarkBlue" , RGB ( 0, 0,139)},
1078 {"dark cyan" , RGB ( 0,139,139)},
1079 {"DarkCyan" , RGB ( 0,139,139)},
1080 {"dark magenta" , RGB (139, 0,139)},
1081 {"DarkMagenta" , RGB (139, 0,139)},
1082 {"dark red" , RGB (139, 0, 0)},
1083 {"DarkRed" , RGB (139, 0, 0)},
1084 {"light green" , RGB (144,238,144)},
1085 {"LightGreen" , RGB (144,238,144)},
1086};
1087
1088DEFUN ("win32-default-color-map", Fwin32_default_color_map, Swin32_default_color_map,
1089 0, 0, 0, "Return the default color map.")
1090 ()
1091{
1092 int i;
1093 colormap_t *pc = win32_color_map;
1094 Lisp_Object cmap;
1095
1096 BLOCK_INPUT;
1097
1098 cmap = Qnil;
1099
1100 for (i = 0; i < sizeof (win32_color_map) / sizeof (win32_color_map[0]);
1101 pc++, i++)
1102 cmap = Fcons (Fcons (build_string (pc->name),
1103 make_number (pc->colorref)),
1104 cmap);
1105
1106 UNBLOCK_INPUT;
1107
1108 return (cmap);
1109}
1110#endif
1111
1112Lisp_Object
1113win32_to_x_color (rgb)
1114 Lisp_Object rgb;
1115{
1116 Lisp_Object color;
1117
1118 CHECK_NUMBER (rgb, 0);
1119
1120 BLOCK_INPUT;
1121
1122 color = Frassq (rgb, Vwin32_color_map);
1123
1124 UNBLOCK_INPUT;
1125
1126 if (!NILP (color))
1127 return (Fcar (color));
1128 else
1129 return Qnil;
1130}
1131
1132COLORREF
1133x_to_win32_color (colorname)
1134 char * colorname;
1135{
1136 register Lisp_Object tail, ret = Qnil;
1137
1138 BLOCK_INPUT;
1139
1140 for (tail = Vwin32_color_map; !NILP (tail); tail = Fcdr (tail))
1141 {
1142 register Lisp_Object elt, tem;
1143
1144 elt = Fcar (tail);
1145 if (!CONSP (elt)) continue;
1146
1147 tem = Fcar (elt);
1148
1149 if (lstrcmpi (XSTRING (tem)->data, colorname) == 0)
1150 {
1151 ret = XUINT(Fcdr (elt));
1152 break;
1153 }
1154
1155 QUIT;
1156 }
1157
1158 UNBLOCK_INPUT;
1159
1160 return ret;
1161}
1162
1163/* Decide if color named COLOR is valid for the display associated with
1164 the selected frame; if so, return the rgb values in COLOR_DEF.
1165 If ALLOC is nonzero, allocate a new colormap cell. */
1166
1167int
1168defined_color (f, color, color_def, alloc)
1169 FRAME_PTR f;
1170 char *color;
1171 COLORREF *color_def;
1172 int alloc;
1173{
1174 register Lisp_Object tem;
1175
1176 tem = x_to_win32_color (color);
1177
1178 if (!NILP (tem))
1179 {
1180 *color_def = XUINT (tem);
1181 return 1;
1182 }
1183 else
1184 {
1185 return 0;
1186 }
1187}
1188
1189/* Given a string ARG naming a color, compute a pixel value from it
1190 suitable for screen F.
1191 If F is not a color screen, return DEF (default) regardless of what
1192 ARG says. */
1193
1194int
1195x_decode_color (f, arg, def)
1196 FRAME_PTR f;
1197 Lisp_Object arg;
1198 int def;
1199{
1200 COLORREF cdef;
1201
1202 CHECK_STRING (arg, 0);
1203
1204 if (strcmp (XSTRING (arg)->data, "black") == 0)
1205 return BLACK_PIX_DEFAULT (f);
1206 else if (strcmp (XSTRING (arg)->data, "white") == 0)
1207 return WHITE_PIX_DEFAULT (f);
1208
1209 if ((FRAME_WIN32_DISPLAY_INFO (f)->n_planes * FRAME_WIN32_DISPLAY_INFO (f)->n_cbits) == 1)
1210 return def;
1211
1212 /* defined_color is responsible for coping with failures
1213 by looking for a near-miss. */
1214 if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
1215 return cdef;
1216
1217 /* defined_color failed; return an ultimate default. */
1218 return def;
1219}
1220
1221/* Functions called only from `x_set_frame_param'
1222 to set individual parameters.
1223
1224 If FRAME_WIN32_WINDOW (f) is 0,
1225 the frame is being created and its window does not exist yet.
1226 In that case, just record the parameter's new value
1227 in the standard place; do not attempt to change the window. */
1228
1229void
1230x_set_foreground_color (f, arg, oldval)
1231 struct frame *f;
1232 Lisp_Object arg, oldval;
1233{
1234 f->output_data.win32->foreground_pixel
1235 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1236 if (FRAME_WIN32_WINDOW (f) != 0)
1237 {
1238 recompute_basic_faces (f);
1239 if (FRAME_VISIBLE_P (f))
1240 redraw_frame (f);
1241 }
1242}
1243
1244void
1245x_set_background_color (f, arg, oldval)
1246 struct frame *f;
1247 Lisp_Object arg, oldval;
1248{
1249 Pixmap temp;
1250 int mask;
1251
1252 f->output_data.win32->background_pixel
1253 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1254
1255 if (FRAME_WIN32_WINDOW (f) != 0)
1256 {
1257 SetWindowLong (FRAME_WIN32_WINDOW (f), WND_BACKGROUND_INDEX, f->output_data.win32->background_pixel);
1258
1259 recompute_basic_faces (f);
1260
1261 if (FRAME_VISIBLE_P (f))
1262 redraw_frame (f);
1263 }
1264}
1265
1266void
1267x_set_mouse_color (f, arg, oldval)
1268 struct frame *f;
1269 Lisp_Object arg, oldval;
1270{
1271#if 0
1272 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1273#endif
1274 int mask_color;
1275
1276 if (!EQ (Qnil, arg))
1277 f->output_data.win32->mouse_pixel
1278 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1279 mask_color = f->output_data.win32->background_pixel;
1280 /* No invisible pointers. */
1281 if (mask_color == f->output_data.win32->mouse_pixel
1282 && mask_color == f->output_data.win32->background_pixel)
1283 f->output_data.win32->mouse_pixel = f->output_data.win32->foreground_pixel;
1284
1285#if 0
1286 BLOCK_INPUT;
1287
1288 /* It's not okay to crash if the user selects a screwy cursor. */
1289 x_catch_errors (FRAME_WIN32_DISPLAY (f));
1290
1291 if (!EQ (Qnil, Vx_pointer_shape))
1292 {
1293 CHECK_NUMBER (Vx_pointer_shape, 0);
1294 cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XINT (Vx_pointer_shape));
1295 }
1296 else
1297 cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_xterm);
1298 x_check_errors (FRAME_WIN32_DISPLAY (f), "bad text pointer cursor: %s");
1299
1300 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1301 {
1302 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1303 nontext_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f),
1304 XINT (Vx_nontext_pointer_shape));
1305 }
1306 else
1307 nontext_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_left_ptr);
1308 x_check_errors (FRAME_WIN32_DISPLAY (f), "bad nontext pointer cursor: %s");
1309
1310 if (!EQ (Qnil, Vx_mode_pointer_shape))
1311 {
1312 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1313 mode_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f),
1314 XINT (Vx_mode_pointer_shape));
1315 }
1316 else
1317 mode_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_xterm);
1318 x_check_errors (FRAME_WIN32_DISPLAY (f), "bad modeline pointer cursor: %s");
1319
1320 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1321 {
1322 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1323 cross_cursor
1324 = XCreateFontCursor (FRAME_WIN32_DISPLAY (f),
1325 XINT (Vx_sensitive_text_pointer_shape));
1326 }
1327 else
1328 cross_cursor = XCreateFontCursor (FRAME_WIN32_DISPLAY (f), XC_crosshair);
1329
1330 /* Check and report errors with the above calls. */
1331 x_check_errors (FRAME_WIN32_DISPLAY (f), "can't set cursor shape: %s");
1332 x_uncatch_errors (FRAME_WIN32_DISPLAY (f));
1333
1334 {
1335 XColor fore_color, back_color;
1336
1337 fore_color.pixel = f->output_data.win32->mouse_pixel;
1338 back_color.pixel = mask_color;
1339 XQueryColor (FRAME_WIN32_DISPLAY (f),
1340 DefaultColormap (FRAME_WIN32_DISPLAY (f),
1341 DefaultScreen (FRAME_WIN32_DISPLAY (f))),
1342 &fore_color);
1343 XQueryColor (FRAME_WIN32_DISPLAY (f),
1344 DefaultColormap (FRAME_WIN32_DISPLAY (f),
1345 DefaultScreen (FRAME_WIN32_DISPLAY (f))),
1346 &back_color);
1347 XRecolorCursor (FRAME_WIN32_DISPLAY (f), cursor,
1348 &fore_color, &back_color);
1349 XRecolorCursor (FRAME_WIN32_DISPLAY (f), nontext_cursor,
1350 &fore_color, &back_color);
1351 XRecolorCursor (FRAME_WIN32_DISPLAY (f), mode_cursor,
1352 &fore_color, &back_color);
1353 XRecolorCursor (FRAME_WIN32_DISPLAY (f), cross_cursor,
1354 &fore_color, &back_color);
1355 }
1356
1357 if (FRAME_WIN32_WINDOW (f) != 0)
1358 {
1359 XDefineCursor (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f), cursor);
1360 }
1361
1362 if (cursor != f->output_data.win32->text_cursor && f->output_data.win32->text_cursor != 0)
1363 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->text_cursor);
1364 f->output_data.win32->text_cursor = cursor;
1365
1366 if (nontext_cursor != f->output_data.win32->nontext_cursor
1367 && f->output_data.win32->nontext_cursor != 0)
1368 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->nontext_cursor);
1369 f->output_data.win32->nontext_cursor = nontext_cursor;
1370
1371 if (mode_cursor != f->output_data.win32->modeline_cursor
1372 && f->output_data.win32->modeline_cursor != 0)
1373 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->modeline_cursor);
1374 f->output_data.win32->modeline_cursor = mode_cursor;
1375 if (cross_cursor != f->output_data.win32->cross_cursor
1376 && f->output_data.win32->cross_cursor != 0)
1377 XFreeCursor (FRAME_WIN32_DISPLAY (f), f->output_data.win32->cross_cursor);
1378 f->output_data.win32->cross_cursor = cross_cursor;
1379
1380 XFlush (FRAME_WIN32_DISPLAY (f));
1381 UNBLOCK_INPUT;
1382#endif
1383}
1384
1385void
1386x_set_cursor_color (f, arg, oldval)
1387 struct frame *f;
1388 Lisp_Object arg, oldval;
1389{
1390 unsigned long fore_pixel;
1391
1392 if (!EQ (Vx_cursor_fore_pixel, Qnil))
1393 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1394 WHITE_PIX_DEFAULT (f));
1395 else
1396 fore_pixel = f->output_data.win32->background_pixel;
1397 f->output_data.win32->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1398
1399 /* Make sure that the cursor color differs from the background color. */
1400 if (f->output_data.win32->cursor_pixel == f->output_data.win32->background_pixel)
1401 {
1402 f->output_data.win32->cursor_pixel = f->output_data.win32->mouse_pixel;
1403 if (f->output_data.win32->cursor_pixel == fore_pixel)
1404 fore_pixel = f->output_data.win32->background_pixel;
1405 }
1406 f->output_data.win32->cursor_foreground_pixel = fore_pixel;
1407
1408 if (FRAME_WIN32_WINDOW (f) != 0)
1409 {
1410 if (FRAME_VISIBLE_P (f))
1411 {
1412 x_display_cursor (f, 0);
1413 x_display_cursor (f, 1);
1414 }
1415 }
1416}
1417
1418/* Set the border-color of frame F to value described by ARG.
1419 ARG can be a string naming a color.
1420 The border-color is used for the border that is drawn by the server.
1421 Note that this does not fully take effect if done before
1422 F has a window; it must be redone when the window is created. */
1423
1424void
1425x_set_border_color (f, arg, oldval)
1426 struct frame *f;
1427 Lisp_Object arg, oldval;
1428{
1429 unsigned char *str;
1430 int pix;
1431
1432 CHECK_STRING (arg, 0);
1433 str = XSTRING (arg)->data;
1434
1435 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1436
1437 x_set_border_pixel (f, pix);
1438}
1439
1440/* Set the border-color of frame F to pixel value PIX.
1441 Note that this does not fully take effect if done before
1442 F has an window. */
1443
1444x_set_border_pixel (f, pix)
1445 struct frame *f;
1446 int pix;
1447{
1448 f->output_data.win32->border_pixel = pix;
1449
1450 if (FRAME_WIN32_WINDOW (f) != 0 && f->output_data.win32->border_width > 0)
1451 {
1452 if (FRAME_VISIBLE_P (f))
1453 redraw_frame (f);
1454 }
1455}
1456
1457void
1458x_set_cursor_type (f, arg, oldval)
1459 FRAME_PTR f;
1460 Lisp_Object arg, oldval;
1461{
1462 if (EQ (arg, Qbar))
1463 {
1464 FRAME_DESIRED_CURSOR (f) = bar_cursor;
1465 f->output_data.win32->cursor_width = 2;
1466 }
1467 else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
1468 && INTEGERP (XCONS (arg)->cdr))
1469 {
1470 FRAME_DESIRED_CURSOR (f) = bar_cursor;
1471 f->output_data.win32->cursor_width = XINT (XCONS (arg)->cdr);
1472 }
1473 else
1474 /* Treat anything unknown as "box cursor".
1475 It was bad to signal an error; people have trouble fixing
1476 .Xdefaults with Emacs, when it has something bad in it. */
1477 FRAME_DESIRED_CURSOR (f) = filled_box_cursor;
1478
1479 /* Make sure the cursor gets redrawn. This is overkill, but how
1480 often do people change cursor types? */
1481 update_mode_lines++;
1482}
1483
1484void
1485x_set_icon_type (f, arg, oldval)
1486 struct frame *f;
1487 Lisp_Object arg, oldval;
1488{
1489#if 0
1490 Lisp_Object tem;
1491 int result;
1492
1493 if (STRINGP (arg))
1494 {
1495 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1496 return;
1497 }
1498 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1499 return;
1500
1501 BLOCK_INPUT;
1502 if (NILP (arg))
1503 result = x_text_icon (f,
1504 (char *) XSTRING ((!NILP (f->icon_name)
1505 ? f->icon_name
1506 : f->name))->data);
1507 else
1508 result = x_bitmap_icon (f, arg);
1509
1510 if (result)
1511 {
1512 UNBLOCK_INPUT;
1513 error ("No icon window available");
1514 }
1515
1516 /* If the window was unmapped (and its icon was mapped),
1517 the new icon is not mapped, so map the window in its stead. */
1518 if (FRAME_VISIBLE_P (f))
1519 {
1520#ifdef USE_X_TOOLKIT
1521 XtPopup (f->output_data.win32->widget, XtGrabNone);
1522#endif
1523 XMapWindow (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f));
1524 }
1525
1526 XFlush (FRAME_WIN32_DISPLAY (f));
1527 UNBLOCK_INPUT;
1528#endif
1529}
1530
1531/* Return non-nil if frame F wants a bitmap icon. */
1532
1533Lisp_Object
1534x_icon_type (f)
1535 FRAME_PTR f;
1536{
1537 Lisp_Object tem;
1538
1539 tem = assq_no_quit (Qicon_type, f->param_alist);
1540 if (CONSP (tem))
1541 return XCONS (tem)->cdr;
1542 else
1543 return Qnil;
1544}
1545
1546void
1547x_set_icon_name (f, arg, oldval)
1548 struct frame *f;
1549 Lisp_Object arg, oldval;
1550{
1551 Lisp_Object tem;
1552 int result;
1553
1554 if (STRINGP (arg))
1555 {
1556 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1557 return;
1558 }
1559 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1560 return;
1561
1562 f->icon_name = arg;
1563
1564#if 0
1565 if (f->output_data.win32->icon_bitmap != 0)
1566 return;
1567
1568 BLOCK_INPUT;
1569
1570 result = x_text_icon (f,
1571 (char *) XSTRING ((!NILP (f->icon_name)
1572 ? f->icon_name
1573 : f->name))->data);
1574
1575 if (result)
1576 {
1577 UNBLOCK_INPUT;
1578 error ("No icon window available");
1579 }
1580
1581 /* If the window was unmapped (and its icon was mapped),
1582 the new icon is not mapped, so map the window in its stead. */
1583 if (FRAME_VISIBLE_P (f))
1584 {
1585#ifdef USE_X_TOOLKIT
1586 XtPopup (f->output_data.win32->widget, XtGrabNone);
1587#endif
1588 XMapWindow (FRAME_WIN32_DISPLAY (f), FRAME_WIN32_WINDOW (f));
1589 }
1590
1591 XFlush (FRAME_WIN32_DISPLAY (f));
1592 UNBLOCK_INPUT;
1593#endif
1594}
1595
1596extern Lisp_Object x_new_font ();
1597
1598void
1599x_set_font (f, arg, oldval)
1600 struct frame *f;
1601 Lisp_Object arg, oldval;
1602{
1603 Lisp_Object result;
1604
1605 CHECK_STRING (arg, 1);
1606
1607 BLOCK_INPUT;
1608 result = x_new_font (f, XSTRING (arg)->data);
1609 UNBLOCK_INPUT;
1610
1611 if (EQ (result, Qnil))
1612 error ("Font \"%s\" is not defined", XSTRING (arg)->data);
1613 else if (EQ (result, Qt))
1614 error ("the characters of the given font have varying widths");
1615 else if (STRINGP (result))
1616 {
1617 recompute_basic_faces (f);
1618 store_frame_param (f, Qfont, result);
1619 }
1620 else
1621 abort ();
1622}
1623
1624void
1625x_set_border_width (f, arg, oldval)
1626 struct frame *f;
1627 Lisp_Object arg, oldval;
1628{
1629 CHECK_NUMBER (arg, 0);
1630
1631 if (XINT (arg) == f->output_data.win32->border_width)
1632 return;
1633
1634 if (FRAME_WIN32_WINDOW (f) != 0)
1635 error ("Cannot change the border width of a window");
1636
1637 f->output_data.win32->border_width = XINT (arg);
1638}
1639
1640void
1641x_set_internal_border_width (f, arg, oldval)
1642 struct frame *f;
1643 Lisp_Object arg, oldval;
1644{
1645 int mask;
1646 int old = f->output_data.win32->internal_border_width;
1647
1648 CHECK_NUMBER (arg, 0);
1649 f->output_data.win32->internal_border_width = XINT (arg);
1650 if (f->output_data.win32->internal_border_width < 0)
1651 f->output_data.win32->internal_border_width = 0;
1652
1653 if (f->output_data.win32->internal_border_width == old)
1654 return;
1655
1656 if (FRAME_WIN32_WINDOW (f) != 0)
1657 {
1658 BLOCK_INPUT;
1659 x_set_window_size (f, 0, f->width, f->height);
1660 UNBLOCK_INPUT;
1661 SET_FRAME_GARBAGED (f);
1662 }
1663}
1664
1665void
1666x_set_visibility (f, value, oldval)
1667 struct frame *f;
1668 Lisp_Object value, oldval;
1669{
1670 Lisp_Object frame;
1671 XSETFRAME (frame, f);
1672
1673 if (NILP (value))
1674 Fmake_frame_invisible (frame, Qt);
1675 else if (EQ (value, Qicon))
1676 Ficonify_frame (frame);
1677 else
1678 Fmake_frame_visible (frame);
1679}
1680
1681void
1682x_set_menu_bar_lines (f, value, oldval)
1683 struct frame *f;
1684 Lisp_Object value, oldval;
1685{
1686 int nlines;
1687 int olines = FRAME_MENU_BAR_LINES (f);
1688
1689 /* Right now, menu bars don't work properly in minibuf-only frames;
1690 most of the commands try to apply themselves to the minibuffer
1691 frame itslef, and get an error because you can't switch buffers
1692 in or split the minibuffer window. */
1693 if (FRAME_MINIBUF_ONLY_P (f))
1694 return;
1695
1696 if (INTEGERP (value))
1697 nlines = XINT (value);
1698 else
1699 nlines = 0;
1700
1701 FRAME_MENU_BAR_LINES (f) = 0;
1702 if (nlines)
1703 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1704 else
1705 {
1706 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1707 free_frame_menubar (f);
1708 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1709 }
1710}
1711
1712/* Change the name of frame F to NAME. If NAME is nil, set F's name to
1713 win32_id_name.
1714
1715 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1716 name; if NAME is a string, set F's name to NAME and set
1717 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1718
1719 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1720 suggesting a new name, which lisp code should override; if
1721 F->explicit_name is set, ignore the new name; otherwise, set it. */
1722
1723void
1724x_set_name (f, name, explicit)
1725 struct frame *f;
1726 Lisp_Object name;
1727 int explicit;
1728{
1729 /* Make sure that requests from lisp code override requests from
1730 Emacs redisplay code. */
1731 if (explicit)
1732 {
1733 /* If we're switching from explicit to implicit, we had better
1734 update the mode lines and thereby update the title. */
1735 if (f->explicit_name && NILP (name))
1736 update_mode_lines = 1;
1737
1738 f->explicit_name = ! NILP (name);
1739 }
1740 else if (f->explicit_name)
1741 return;
1742
1743 /* If NAME is nil, set the name to the win32_id_name. */
1744 if (NILP (name))
1745 {
1746 /* Check for no change needed in this very common case
1747 before we do any consing. */
1748 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f)->win32_id_name,
1749 XSTRING (f->name)->data))
1750 return;
1751 name = build_string (FRAME_WIN32_DISPLAY_INFO (f)->win32_id_name);
1752 }
1753 else
1754 CHECK_STRING (name, 0);
1755
1756 /* Don't change the name if it's already NAME. */
1757 if (! NILP (Fstring_equal (name, f->name)))
1758 return;
1759
1760 if (FRAME_WIN32_WINDOW (f))
1761 {
1762 BLOCK_INPUT;
1763 SetWindowText(FRAME_WIN32_WINDOW (f), XSTRING (name)->data);
1764 UNBLOCK_INPUT;
1765 }
1766
1767 f->name = name;
1768}
1769
1770/* This function should be called when the user's lisp code has
1771 specified a name for the frame; the name will override any set by the
1772 redisplay code. */
1773void
1774x_explicitly_set_name (f, arg, oldval)
1775 FRAME_PTR f;
1776 Lisp_Object arg, oldval;
1777{
1778 x_set_name (f, arg, 1);
1779}
1780
1781/* This function should be called by Emacs redisplay code to set the
1782 name; names set this way will never override names set by the user's
1783 lisp code. */
1784void
1785x_implicitly_set_name (f, arg, oldval)
1786 FRAME_PTR f;
1787 Lisp_Object arg, oldval;
1788{
1789 x_set_name (f, arg, 0);
1790}
1791
1792void
1793x_set_autoraise (f, arg, oldval)
1794 struct frame *f;
1795 Lisp_Object arg, oldval;
1796{
1797 f->auto_raise = !EQ (Qnil, arg);
1798}
1799
1800void
1801x_set_autolower (f, arg, oldval)
1802 struct frame *f;
1803 Lisp_Object arg, oldval;
1804{
1805 f->auto_lower = !EQ (Qnil, arg);
1806}
1807
1808void
1809x_set_unsplittable (f, arg, oldval)
1810 struct frame *f;
1811 Lisp_Object arg, oldval;
1812{
1813 f->no_split = !NILP (arg);
1814}
1815
1816void
1817x_set_vertical_scroll_bars (f, arg, oldval)
1818 struct frame *f;
1819 Lisp_Object arg, oldval;
1820{
1821 if (NILP (arg) != ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1822 {
1823 FRAME_HAS_VERTICAL_SCROLL_BARS (f) = ! NILP (arg);
1824
1825 /* We set this parameter before creating the window for the
1826 frame, so we can get the geometry right from the start.
1827 However, if the window hasn't been created yet, we shouldn't
1828 call x_set_window_size. */
1829 if (FRAME_WIN32_WINDOW (f))
1830 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1831 }
1832}
1833
1834void
1835x_set_scroll_bar_width (f, arg, oldval)
1836 struct frame *f;
1837 Lisp_Object arg, oldval;
1838{
1839 if (NILP (arg))
1840 {
1841 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
1842 FRAME_SCROLL_BAR_COLS (f) = 2;
1843 }
1844 else if (INTEGERP (arg) && XINT (arg) > 0
1845 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
1846 {
1847 int wid = FONT_WIDTH (f->output_data.win32->font);
1848 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
1849 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
1850 if (FRAME_WIN32_WINDOW (f))
1851 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
1852 }
1853}
1854
1855/* Subroutines of creating an frame. */
1856
1857/* Make sure that Vx_resource_name is set to a reasonable value.
1858 Fix it up, or set it to `emacs' if it is too hopeless. */
1859
1860static void
1861validate_x_resource_name ()
1862{
1863 int len;
1864 /* Number of valid characters in the resource name. */
1865 int good_count = 0;
1866 /* Number of invalid characters in the resource name. */
1867 int bad_count = 0;
1868 Lisp_Object new;
1869 int i;
1870
1871 if (STRINGP (Vx_resource_name))
1872 {
1873 unsigned char *p = XSTRING (Vx_resource_name)->data;
1874 int i;
1875
1876 len = XSTRING (Vx_resource_name)->size;
1877
1878 /* Only letters, digits, - and _ are valid in resource names.
1879 Count the valid characters and count the invalid ones. */
1880 for (i = 0; i < len; i++)
1881 {
1882 int c = p[i];
1883 if (! ((c >= 'a' && c <= 'z')
1884 || (c >= 'A' && c <= 'Z')
1885 || (c >= '0' && c <= '9')
1886 || c == '-' || c == '_'))
1887 bad_count++;
1888 else
1889 good_count++;
1890 }
1891 }
1892 else
1893 /* Not a string => completely invalid. */
1894 bad_count = 5, good_count = 0;
1895
1896 /* If name is valid already, return. */
1897 if (bad_count == 0)
1898 return;
1899
1900 /* If name is entirely invalid, or nearly so, use `emacs'. */
1901 if (good_count == 0
1902 || (good_count == 1 && bad_count > 0))
1903 {
1904 Vx_resource_name = build_string ("emacs");
1905 return;
1906 }
1907
1908 /* Name is partly valid. Copy it and replace the invalid characters
1909 with underscores. */
1910
1911 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
1912
1913 for (i = 0; i < len; i++)
1914 {
1915 int c = XSTRING (new)->data[i];
1916 if (! ((c >= 'a' && c <= 'z')
1917 || (c >= 'A' && c <= 'Z')
1918 || (c >= '0' && c <= '9')
1919 || c == '-' || c == '_'))
1920 XSTRING (new)->data[i] = '_';
1921 }
1922}
1923
1924
1925extern char *x_get_string_resource ();
1926
1927DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
1928 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
1929This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
1930class, where INSTANCE is the name under which Emacs was invoked, or\n\
1931the name specified by the `-name' or `-rn' command-line arguments.\n\
1932\n\
1933The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
1934class, respectively. You must specify both of them or neither.\n\
1935If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
1936and the class is `Emacs.CLASS.SUBCLASS'.")
1937 (attribute, class, component, subclass)
1938 Lisp_Object attribute, class, component, subclass;
1939{
1940 register char *value;
1941 char *name_key;
1942 char *class_key;
1943
1944 CHECK_STRING (attribute, 0);
1945 CHECK_STRING (class, 0);
1946
1947 if (!NILP (component))
1948 CHECK_STRING (component, 1);
1949 if (!NILP (subclass))
1950 CHECK_STRING (subclass, 2);
1951 if (NILP (component) != NILP (subclass))
1952 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
1953
1954 validate_x_resource_name ();
1955
1956 /* Allocate space for the components, the dots which separate them,
1957 and the final '\0'. Make them big enough for the worst case. */
1958 name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
1959 + (STRINGP (component)
1960 ? XSTRING (component)->size : 0)
1961 + XSTRING (attribute)->size
1962 + 3);
1963
1964 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
1965 + XSTRING (class)->size
1966 + (STRINGP (subclass)
1967 ? XSTRING (subclass)->size : 0)
1968 + 3);
1969
1970 /* Start with emacs.FRAMENAME for the name (the specific one)
1971 and with `Emacs' for the class key (the general one). */
1972 strcpy (name_key, XSTRING (Vx_resource_name)->data);
1973 strcpy (class_key, EMACS_CLASS);
1974
1975 strcat (class_key, ".");
1976 strcat (class_key, XSTRING (class)->data);
1977
1978 if (!NILP (component))
1979 {
1980 strcat (class_key, ".");
1981 strcat (class_key, XSTRING (subclass)->data);
1982
1983 strcat (name_key, ".");
1984 strcat (name_key, XSTRING (component)->data);
1985 }
1986
1987 strcat (name_key, ".");
1988 strcat (name_key, XSTRING (attribute)->data);
1989
1990 value = x_get_string_resource (Qnil,
1991 name_key, class_key);
1992
1993 if (value != (char *) 0)
1994 return build_string (value);
1995 else
1996 return Qnil;
1997}
1998
1999/* Used when C code wants a resource value. */
2000
2001char *
2002x_get_resource_string (attribute, class)
2003 char *attribute, *class;
2004{
2005 register char *value;
2006 char *name_key;
2007 char *class_key;
2008
2009 /* Allocate space for the components, the dots which separate them,
2010 and the final '\0'. */
2011 name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
2012 + strlen (attribute) + 2);
2013 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2014 + strlen (class) + 2);
2015
2016 sprintf (name_key, "%s.%s",
2017 XSTRING (Vinvocation_name)->data,
2018 attribute);
2019 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2020
2021 return x_get_string_resource (selected_frame,
2022 name_key, class_key);
2023}
2024
2025/* Types we might convert a resource string into. */
2026enum resource_types
2027 {
2028 number, boolean, string, symbol
2029 };
2030
2031/* Return the value of parameter PARAM.
2032
2033 First search ALIST, then Vdefault_frame_alist, then the X defaults
2034 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2035
2036 Convert the resource to the type specified by desired_type.
2037
2038 If no default is specified, return Qunbound. If you call
2039 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2040 and don't let it get stored in any Lisp-visible variables! */
2041
2042static Lisp_Object
2043x_get_arg (alist, param, attribute, class, type)
2044 Lisp_Object alist, param;
2045 char *attribute;
2046 char *class;
2047 enum resource_types type;
2048{
2049 register Lisp_Object tem;
2050
2051 tem = Fassq (param, alist);
2052 if (EQ (tem, Qnil))
2053 tem = Fassq (param, Vdefault_frame_alist);
2054 if (EQ (tem, Qnil))
2055 {
2056
2057 if (attribute)
2058 {
2059 tem = Fx_get_resource (build_string (attribute),
2060 build_string (class),
2061 Qnil, Qnil);
2062
2063 if (NILP (tem))
2064 return Qunbound;
2065
2066 switch (type)
2067 {
2068 case number:
2069 return make_number (atoi (XSTRING (tem)->data));
2070
2071 case boolean:
2072 tem = Fdowncase (tem);
2073 if (!strcmp (XSTRING (tem)->data, "on")
2074 || !strcmp (XSTRING (tem)->data, "true"))
2075 return Qt;
2076 else
2077 return Qnil;
2078
2079 case string:
2080 return tem;
2081
2082 case symbol:
2083 /* As a special case, we map the values `true' and `on'
2084 to Qt, and `false' and `off' to Qnil. */
2085 {
2086 Lisp_Object lower;
2087 lower = Fdowncase (tem);
2088 if (!strcmp (XSTRING (lower)->data, "on")
2089 || !strcmp (XSTRING (lower)->data, "true"))
2090 return Qt;
2091 else if (!strcmp (XSTRING (lower)->data, "off")
2092 || !strcmp (XSTRING (lower)->data, "false"))
2093 return Qnil;
2094 else
2095 return Fintern (tem, Qnil);
2096 }
2097
2098 default:
2099 abort ();
2100 }
2101 }
2102 else
2103 return Qunbound;
2104 }
2105 return Fcdr (tem);
2106}
2107
2108/* Record in frame F the specified or default value according to ALIST
2109 of the parameter named PARAM (a Lisp symbol).
2110 If no value is specified for PARAM, look for an X default for XPROP
2111 on the frame named NAME.
2112 If that is not found either, use the value DEFLT. */
2113
2114static Lisp_Object
2115x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2116 struct frame *f;
2117 Lisp_Object alist;
2118 Lisp_Object prop;
2119 Lisp_Object deflt;
2120 char *xprop;
2121 char *xclass;
2122 enum resource_types type;
2123{
2124 Lisp_Object tem;
2125
2126 tem = x_get_arg (alist, prop, xprop, xclass, type);
2127 if (EQ (tem, Qunbound))
2128 tem = deflt;
2129 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2130 return tem;
2131}
2132
2133DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2134 "Parse an X-style geometry string STRING.\n\
2135Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2136The properties returned may include `top', `left', `height', and `width'.\n\
2137The value of `left' or `top' may be an integer,\n\
2138or a list (+ N) meaning N pixels relative to top/left corner,\n\
2139or a list (- N) meaning -N pixels relative to bottom/right corner.")
2140 (string)
2141 Lisp_Object string;
2142{
2143 int geometry, x, y;
2144 unsigned int width, height;
2145 Lisp_Object result;
2146
2147 CHECK_STRING (string, 0);
2148
2149 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2150 &x, &y, &width, &height);
2151
2152 result = Qnil;
2153 if (geometry & XValue)
2154 {
2155 Lisp_Object element;
2156
2157 if (x >= 0 && (geometry & XNegative))
2158 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2159 else if (x < 0 && ! (geometry & XNegative))
2160 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2161 else
2162 element = Fcons (Qleft, make_number (x));
2163 result = Fcons (element, result);
2164 }
2165
2166 if (geometry & YValue)
2167 {
2168 Lisp_Object element;
2169
2170 if (y >= 0 && (geometry & YNegative))
2171 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2172 else if (y < 0 && ! (geometry & YNegative))
2173 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2174 else
2175 element = Fcons (Qtop, make_number (y));
2176 result = Fcons (element, result);
2177 }
2178
2179 if (geometry & WidthValue)
2180 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2181 if (geometry & HeightValue)
2182 result = Fcons (Fcons (Qheight, make_number (height)), result);
2183
2184 return result;
2185}
2186
2187/* Calculate the desired size and position of this window,
2188 and return the flags saying which aspects were specified.
2189
2190 This function does not make the coordinates positive. */
2191
2192#define DEFAULT_ROWS 40
2193#define DEFAULT_COLS 80
2194
2195static int
2196x_figure_window_size (f, parms)
2197 struct frame *f;
2198 Lisp_Object parms;
2199{
2200 register Lisp_Object tem0, tem1, tem2;
2201 int height, width, left, top;
2202 register int geometry;
2203 long window_prompting = 0;
2204
2205 /* Default values if we fall through.
2206 Actually, if that happens we should get
2207 window manager prompting. */
2208 f->width = DEFAULT_COLS;
2209 f->height = DEFAULT_ROWS;
2210 /* Window managers expect that if program-specified
2211 positions are not (0,0), they're intentional, not defaults. */
2212 f->output_data.win32->top_pos = 0;
2213 f->output_data.win32->left_pos = 0;
2214
2215 tem0 = x_get_arg (parms, Qheight, 0, 0, number);
2216 tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
2217 tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
2218 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2219 {
2220 if (!EQ (tem0, Qunbound))
2221 {
2222 CHECK_NUMBER (tem0, 0);
2223 f->height = XINT (tem0);
2224 }
2225 if (!EQ (tem1, Qunbound))
2226 {
2227 CHECK_NUMBER (tem1, 0);
2228 f->width = XINT (tem1);
2229 }
2230 if (!NILP (tem2) && !EQ (tem2, Qunbound))
2231 window_prompting |= USSize;
2232 else
2233 window_prompting |= PSize;
2234 }
2235
2236 f->output_data.win32->vertical_scroll_bar_extra
2237 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2238 ? 0
2239 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2240 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2241 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
2242 f->output_data.win32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
2243 f->output_data.win32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
2244
2245 tem0 = x_get_arg (parms, Qtop, 0, 0, number);
2246 tem1 = x_get_arg (parms, Qleft, 0, 0, number);
2247 tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
2248 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
2249 {
2250 if (EQ (tem0, Qminus))
2251 {
2252 f->output_data.win32->top_pos = 0;
2253 window_prompting |= YNegative;
2254 }
2255 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
2256 && CONSP (XCONS (tem0)->cdr)
2257 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2258 {
2259 f->output_data.win32->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
2260 window_prompting |= YNegative;
2261 }
2262 else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
2263 && CONSP (XCONS (tem0)->cdr)
2264 && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
2265 {
2266 f->output_data.win32->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
2267 }
2268 else if (EQ (tem0, Qunbound))
2269 f->output_data.win32->top_pos = 0;
2270 else
2271 {
2272 CHECK_NUMBER (tem0, 0);
2273 f->output_data.win32->top_pos = XINT (tem0);
2274 if (f->output_data.win32->top_pos < 0)
2275 window_prompting |= YNegative;
2276 }
2277
2278 if (EQ (tem1, Qminus))
2279 {
2280 f->output_data.win32->left_pos = 0;
2281 window_prompting |= XNegative;
2282 }
2283 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
2284 && CONSP (XCONS (tem1)->cdr)
2285 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2286 {
2287 f->output_data.win32->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
2288 window_prompting |= XNegative;
2289 }
2290 else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
2291 && CONSP (XCONS (tem1)->cdr)
2292 && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
2293 {
2294 f->output_data.win32->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
2295 }
2296 else if (EQ (tem1, Qunbound))
2297 f->output_data.win32->left_pos = 0;
2298 else
2299 {
2300 CHECK_NUMBER (tem1, 0);
2301 f->output_data.win32->left_pos = XINT (tem1);
2302 if (f->output_data.win32->left_pos < 0)
2303 window_prompting |= XNegative;
2304 }
2305
2306 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
2307 window_prompting |= USPosition;
2308 else
2309 window_prompting |= PPosition;
2310 }
2311
2312 return window_prompting;
2313}
2314
2315
2316
2317extern LRESULT CALLBACK win32_wnd_proc ();
2318
2319BOOL
2320win32_init_class (hinst)
2321 HINSTANCE hinst;
2322{
2323 WNDCLASS wc;
2324
2325 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
2326 wc.lpfnWndProc = (WNDPROC) win32_wnd_proc;
2327 wc.cbClsExtra = 0;
2328 wc.cbWndExtra = WND_EXTRA_BYTES;
2329 wc.hInstance = hinst;
2330 wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
2331 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
2332 wc.hbrBackground = NULL; // GetStockObject (WHITE_BRUSH);
2333 wc.lpszMenuName = NULL;
2334 wc.lpszClassName = EMACS_CLASS;
2335
2336 return (RegisterClass (&wc));
2337}
2338
2339HWND
2340win32_createscrollbar (f, bar)
2341 struct frame *f;
2342 struct scroll_bar * bar;
2343{
2344 return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
2345 /* Position and size of scroll bar. */
2346 XINT(bar->left), XINT(bar->top),
2347 XINT(bar->width), XINT(bar->height),
2348 FRAME_WIN32_WINDOW (f),
2349 NULL,
2350 hinst,
2351 NULL));
2352}
2353
2354void
2355win32_createwindow (f)
2356 struct frame *f;
2357{
2358 HWND hwnd;
2359
2360 /* Do first time app init */
2361
2362 if (!hprevinst)
2363 {
2364 win32_init_class (hinst);
2365 }
2366
2367 FRAME_WIN32_WINDOW (f) = hwnd = CreateWindow (EMACS_CLASS,
2368 f->namebuf,
2369 f->output_data.win32->dwStyle | WS_CLIPCHILDREN,
2370 f->output_data.win32->left_pos,
2371 f->output_data.win32->top_pos,
2372 PIXEL_WIDTH (f),
2373 PIXEL_HEIGHT (f),
2374 NULL,
2375 NULL,
2376 hinst,
2377 NULL);
2378
2379 if (hwnd)
2380 {
2381 SetWindowLong (hwnd, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.win32->font));
2382 SetWindowLong (hwnd, WND_Y_UNITS_INDEX, f->output_data.win32->line_height);
2383 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, f->output_data.win32->background_pixel);
2384 }
2385}
2386
2387DWORD
2388win_msg_worker (dw)
2389 DWORD dw;
2390{
2391 MSG msg;
2392
2393 /* Ensure our message queue is created */
2394
2395 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2396
2397 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0);
2398
2399 while (GetMessage (&msg, NULL, 0, 0))
2400 {
2401 if (msg.hwnd == NULL)
2402 {
2403 switch (msg.message)
2404 {
2405 case WM_EMACS_CREATEWINDOW:
2406 win32_createwindow ((struct frame *) msg.wParam);
2407 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0);
2408 break;
2409 case WM_EMACS_CREATESCROLLBAR:
2410 {
2411 HWND hwnd = win32_createscrollbar ((struct frame *) msg.wParam,
2412 (struct scroll_bar *) msg.lParam);
2413 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, (WPARAM)hwnd, 0);
2414 }
2415 break;
2416 case WM_EMACS_KILL:
2417 return (0);
2418 }
2419 }
2420 else
2421 {
2422 DispatchMessage (&msg);
2423 }
2424 }
2425
2426 return (0);
2427}
2428
2429HDC
2430map_mode (hdc)
2431 HDC hdc;
2432{
2433 if (hdc)
2434 {
2435#if 0
2436 /* Make mapping mode be in 1/20 of point */
2437
2438 SetMapMode (hdc, MM_ANISOTROPIC);
2439 SetWindowExtEx (hdc, 1440, 1440, NULL);
2440 SetViewportExtEx (hdc,
2441 GetDeviceCaps (hdc, LOGPIXELSX),
2442 GetDeviceCaps (hdc, LOGPIXELSY),
2443 NULL);
2444#endif
2445 }
2446 return (hdc);
2447}
2448
2449/* Convert between the modifier bits Win32 uses and the modifier bits
2450 Emacs uses. */
2451unsigned int
2452win32_get_modifiers ()
2453{
2454 return (((GetKeyState (VK_SHIFT)&0x8000) ? shift_modifier : 0) |
2455 ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier : 0) |
2456 ((GetKeyState (VK_MENU)&0x8000) ? meta_modifier : 0));
2457}
2458
2459void
2460my_post_msg (wmsg, hwnd, msg, wParam, lParam)
2461 Win32Msg * wmsg;
2462 HWND hwnd;
2463 UINT msg;
2464 WPARAM wParam;
2465 LPARAM lParam;
2466{
2467 wmsg->msg.hwnd = hwnd;
2468 wmsg->msg.message = msg;
2469 wmsg->msg.wParam = wParam;
2470 wmsg->msg.lParam = lParam;
2471 wmsg->msg.time = GetMessageTime ();
2472
2473 post_msg (wmsg);
2474}
2475
2476/* Main window procedure */
2477
2478extern char *lispy_function_keys[];
2479
2480LRESULT CALLBACK
2481win32_wnd_proc (hwnd, msg, wParam, lParam)
2482 HWND hwnd;
2483 UINT msg;
2484 WPARAM wParam;
2485 LPARAM lParam;
2486{
2487 struct frame *f;
2488 LRESULT ret = 1;
2489 struct win32_display_info *dpyinfo = &one_win32_display_info;
2490 Win32Msg wmsg;
2491
2492 switch (msg)
2493 {
2494 case WM_ERASEBKGND:
2495 {
2496 HBRUSH hb;
2497 HANDLE oldobj;
2498 RECT rect;
2499
2500 GetClientRect (hwnd, &rect);
2501
2502 hb = CreateSolidBrush (GetWindowLong (hwnd, WND_BACKGROUND_INDEX));
2503
2504 oldobj = SelectObject ((HDC)wParam, hb);
2505
2506 FillRect((HDC)wParam, &rect, hb);
2507
2508 SelectObject((HDC)wParam, oldobj);
2509
2510 DeleteObject (hb);
2511
2512 return (0);
2513 }
2514 case WM_PAINT:
2515 {
2516 PAINTSTRUCT paintStruct;
2517
2518 BeginPaint (hwnd, &paintStruct);
2519 wmsg.rect = paintStruct.rcPaint;
2520 EndPaint (hwnd, &paintStruct);
2521
2522 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2523
2524 return (0);
2525 }
2526
2527 case WM_CREATE:
2528 {
2529 HDC hdc = my_get_dc (hwnd);
2530
2531 /* Make mapping mode be in 1/20 of point */
2532
2533 map_mode (hdc);
2534
2535 ReleaseDC (hwnd, hdc);
2536 }
2537
2538 return (0);
2539 case WM_KEYDOWN:
2540 case WM_SYSKEYDOWN:
2541#if 0
2542 if (! ((wParam >= VK_BACK && wParam <= VK_TAB)
2543 || (wParam >= VK_CLEAR && wParam <= VK_RETURN)
2544 || (wParam == VK_ESCAPE)
2545 || (wParam >= VK_PRIOR && wParam <= VK_HELP)
2546 || (wParam >= VK_LWIN && wParam <= VK_APPS)
2547 || (wParam >= VK_NUMPAD0 && wParam <= VK_F24)
2548 || (wParam >= VK_NUMLOCK && wParam <= VK_SCROLL)
2549 || (wParam >= VK_ATTN && wParam <= VK_OEM_CLEAR)
2550 || !TranslateMessage (&msg1)))
2551 {
2552 goto dflt;
2553 }
2554#endif
2555
2556 /* Check for special characters since translate message
2557 seems to always indicate true. */
2558
2559 if (wParam == VK_MENU
2560 || wParam == VK_SHIFT
2561 || wParam == VK_CONTROL
2562 || wParam == VK_CAPITAL)
2563 break;
2564
2565 /* Anything we do not have a name for needs to be translated or
2566 returned as ascii keystroke. */
2567
2568 if (lispy_function_keys[wParam] == 0)
2569 {
2570 MSG msg1;
2571
2572 msg1.hwnd = hwnd;
2573 msg1.message = msg;
2574 msg1.wParam = wParam;
2575 msg1.lParam = lParam;
2576
2577 if (TranslateMessage (&msg1))
2578 break;
2579 else
2580 msg = WM_CHAR;
2581 }
2582
2583 /* Fall through */
2584
2585 case WM_SYSCHAR:
2586 case WM_CHAR:
2587 wmsg.dwModifiers = win32_get_modifiers ();
2588
2589 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2590 break;
2591 case WM_LBUTTONDOWN:
2592 case WM_LBUTTONUP:
2593 case WM_MBUTTONDOWN:
2594 case WM_MBUTTONUP:
2595 case WM_RBUTTONDOWN:
2596 case WM_RBUTTONUP:
2597 {
2598 BOOL up;
2599
2600 if (parse_button (msg, NULL, &up))
2601 {
2602 if (up) ReleaseCapture ();
2603 else SetCapture (hwnd);
2604 }
2605 }
2606
2607 wmsg.dwModifiers = win32_get_modifiers ();
2608
2609 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2610 goto dflt;
2611 case WM_MOUSEMOVE:
2612 case WM_MOVE:
2613 case WM_SIZE:
2614 case WM_SETFOCUS:
2615 case WM_KILLFOCUS:
2616 case WM_CLOSE:
2617 case WM_VSCROLL:
2618 case WM_SYSCOMMAND:
2619 case WM_COMMAND:
2620 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2621 goto dflt;
2622 case WM_WINDOWPOSCHANGING:
2623 {
2624 WINDOWPLACEMENT wp;
2625 LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
2626
2627 GetWindowPlacement (hwnd, &wp);
2628
2629 if (wp.showCmd != SW_SHOWMINIMIZED && ! (lppos->flags & SWP_NOSIZE))
2630 {
2631 RECT rect;
2632 int wdiff;
2633 int hdiff;
2634 DWORD dwXUnits;
2635 DWORD dwYUnits;
2636 RECT wr;
2637
2638 GetWindowRect (hwnd, &wr);
2639
2640 enter_crit ();
2641
2642 dwXUnits = GetWindowLong (hwnd, WND_X_UNITS_INDEX);
2643 dwYUnits = GetWindowLong (hwnd, WND_Y_UNITS_INDEX);
2644
2645 leave_crit ();
2646
2647 memset (&rect, 0, sizeof (rect));
2648 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
2649 GetMenu (hwnd) != NULL);
2650
2651 /* All windows have an extra pixel so subtract 1 */
2652
2653 wdiff = (lppos->cx - (rect.right - rect.left) - 0) % dwXUnits;
2654 hdiff = (lppos->cy - (rect.bottom - rect.top) - 0) % dwYUnits;
2655
2656 if (wdiff || hdiff)
2657 {
2658 /* For right/bottom sizing we can just fix the sizes.
2659 However for top/left sizing we will need to fix the X
2660 and Y positions as well. */
2661
2662 lppos->cx -= wdiff;
2663 lppos->cy -= hdiff;
2664
2665 if (wp.showCmd != SW_SHOWMAXIMIZED
2666 && ! (lppos->flags & SWP_NOMOVE))
2667 {
2668 if (lppos->x != wr.left || lppos->y != wr.top)
2669 {
2670 lppos->x += wdiff;
2671 lppos->y += hdiff;
2672 }
2673 else
2674 {
2675 lppos->flags |= SWP_NOMOVE;
2676 }
2677 }
2678
2679 ret = 0;
2680 }
2681 }
2682 }
2683
2684 if (ret == 0) return (0);
2685
2686 goto dflt;
2687 case WM_EMACS_DESTROYWINDOW:
2688 DestroyWindow ((HWND) wParam);
2689 break;
2690 default:
2691 dflt:
2692 return DefWindowProc (hwnd, msg, wParam, lParam);
2693 }
2694
2695 return (1);
2696}
2697
2698void
2699my_create_window (f)
2700 struct frame * f;
2701{
2702 MSG msg;
2703
2704 PostThreadMessage (dwWinThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0);
2705 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
2706}
2707
2708/* Create and set up the win32 window for frame F. */
2709
2710static void
2711win32_window (f, window_prompting, minibuffer_only)
2712 struct frame *f;
2713 long window_prompting;
2714 int minibuffer_only;
2715{
2716 BLOCK_INPUT;
2717
2718 /* Use the resource name as the top-level window name
2719 for looking up resources. Make a non-Lisp copy
2720 for the window manager, so GC relocation won't bother it.
2721
2722 Elsewhere we specify the window name for the window manager. */
2723
2724 {
2725 char *str = (char *) XSTRING (Vx_resource_name)->data;
2726 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2727 strcpy (f->namebuf, str);
2728 }
2729
2730 my_create_window (f);
2731
2732 validate_x_resource_name ();
2733
2734 /* x_set_name normally ignores requests to set the name if the
2735 requested name is the same as the current name. This is the one
2736 place where that assumption isn't correct; f->name is set, but
2737 the server hasn't been told. */
2738 {
2739 Lisp_Object name;
2740 int explicit = f->explicit_name;
2741
2742 f->explicit_name = 0;
2743 name = f->name;
2744 f->name = Qnil;
2745 x_set_name (f, name, explicit);
2746 }
2747
2748 UNBLOCK_INPUT;
2749
2750 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
2751 initialize_frame_menubar (f);
2752
2753 if (FRAME_WIN32_WINDOW (f) == 0)
2754 error ("Unable to create window");
2755}
2756
2757/* Handle the icon stuff for this window. Perhaps later we might
2758 want an x_set_icon_position which can be called interactively as
2759 well. */
2760
2761static void
2762x_icon (f, parms)
2763 struct frame *f;
2764 Lisp_Object parms;
2765{
2766 Lisp_Object icon_x, icon_y;
2767
2768 /* Set the position of the icon. Note that win95 groups all
2769 icons in the tray. */
2770 icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
2771 icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
2772 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2773 {
2774 CHECK_NUMBER (icon_x, 0);
2775 CHECK_NUMBER (icon_y, 0);
2776 }
2777 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2778 error ("Both left and top icon corners of icon must be specified");
2779
2780 BLOCK_INPUT;
2781
2782 if (! EQ (icon_x, Qunbound))
2783 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2784
2785 UNBLOCK_INPUT;
2786}
2787
2788DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2789 1, 1, 0,
2790 "Make a new window, which is called a \"frame\" in Emacs terms.\n\
2791Returns an Emacs frame object.\n\
2792ALIST is an alist of frame parameters.\n\
2793If the parameters specify that the frame should not have a minibuffer,\n\
2794and do not specify a specific minibuffer window to use,\n\
2795then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
2796be shared by the new frame.\n\
2797\n\
2798This function is an internal primitive--use `make-frame' instead.")
2799 (parms)
2800 Lisp_Object parms;
2801{
2802 struct frame *f;
2803 Lisp_Object frame, tem;
2804 Lisp_Object name;
2805 int minibuffer_only = 0;
2806 long window_prompting = 0;
2807 int width, height;
2808 int count = specpdl_ptr - specpdl;
2809 struct gcpro gcpro1;
2810 Lisp_Object display;
2811 struct win32_display_info *dpyinfo;
2812 Lisp_Object parent;
2813 struct kboard *kb;
2814
2815 /* Use this general default value to start with
2816 until we know if this frame has a specified name. */
2817 Vx_resource_name = Vinvocation_name;
2818
2819 display = x_get_arg (parms, Qdisplay, 0, 0, string);
2820 if (EQ (display, Qunbound))
2821 display = Qnil;
2822 dpyinfo = check_x_display_info (display);
2823#ifdef MULTI_KBOARD
2824 kb = dpyinfo->kboard;
2825#else
2826 kb = &the_only_kboard;
2827#endif
2828
2829 name = x_get_arg (parms, Qname, "title", "Title", string);
2830 if (!STRINGP (name)
2831 && ! EQ (name, Qunbound)
2832 && ! NILP (name))
2833 error ("Invalid frame name--not a string or nil");
2834
2835 if (STRINGP (name))
2836 Vx_resource_name = name;
2837
2838 /* See if parent window is specified. */
2839 parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
2840 if (EQ (parent, Qunbound))
2841 parent = Qnil;
2842 if (! NILP (parent))
2843 CHECK_NUMBER (parent, 0);
2844
2845 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
2846 if (EQ (tem, Qnone) || NILP (tem))
2847 f = make_frame_without_minibuffer (Qnil, kb, display);
2848 else if (EQ (tem, Qonly))
2849 {
2850 f = make_minibuffer_frame ();
2851 minibuffer_only = 1;
2852 }
2853 else if (WINDOWP (tem))
2854 f = make_frame_without_minibuffer (tem, kb, display);
2855 else
2856 f = make_frame (1);
2857
2858 /* Note that Windows does support scroll bars. */
2859 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
2860
2861 XSETFRAME (frame, f);
2862 GCPRO1 (frame);
2863
2864 f->output_method = output_win32;
2865 f->output_data.win32 = (struct win32_output *) xmalloc (sizeof (struct win32_output));
2866 bzero (f->output_data.win32, sizeof (struct win32_output));
2867
2868/* FRAME_WIN32_DISPLAY_INFO (f) = dpyinfo; */
2869#ifdef MULTI_KBOARD
2870 FRAME_KBOARD (f) = kb;
2871#endif
2872
2873 /* Specify the parent under which to make this window. */
2874
2875 if (!NILP (parent))
2876 {
2877 f->output_data.win32->parent_desc = (Window) parent;
2878 f->output_data.win32->explicit_parent = 1;
2879 }
2880 else
2881 {
2882 f->output_data.win32->parent_desc = FRAME_WIN32_DISPLAY_INFO (f)->root_window;
2883 f->output_data.win32->explicit_parent = 0;
2884 }
2885
2886 /* Note that the frame has no physical cursor right now. */
2887 f->phys_cursor_x = -1;
2888
2889 /* Set the name; the functions to which we pass f expect the name to
2890 be set. */
2891 if (EQ (name, Qunbound) || NILP (name))
2892 {
2893 f->name = build_string (dpyinfo->win32_id_name);
2894 f->explicit_name = 0;
2895 }
2896 else
2897 {
2898 f->name = name;
2899 f->explicit_name = 1;
2900 /* use the frame's title when getting resources for this frame. */
2901 specbind (Qx_resource_name, name);
2902 }
2903
2904 /* Extract the window parameters from the supplied values
2905 that are needed to determine window geometry. */
2906 {
2907 Lisp_Object font;
2908
2909 font = x_get_arg (parms, Qfont, "font", "Font", string);
2910 BLOCK_INPUT;
2911 /* First, try whatever font the caller has specified. */
2912 if (STRINGP (font))
2913 font = x_new_font (f, XSTRING (font)->data);
2914#if 0
2915 /* Try out a font which we hope has bold and italic variations. */
2916 if (!STRINGP (font))
2917 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
2918 if (! STRINGP (font))
2919 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
2920 if (! STRINGP (font))
2921 /* This was formerly the first thing tried, but it finds too many fonts
2922 and takes too long. */
2923 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
2924 /* If those didn't work, look for something which will at least work. */
2925 if (! STRINGP (font))
2926 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
2927 if (! STRINGP (font))
2928 font = x_new_font (f, "-*-system-medium-r-normal-*-*-200-*-*-c-120-*-*");
2929#endif
2930 if (! STRINGP (font))
2931 font = x_new_font (f, "-*-terminal-medium-r-normal-*-*-180-*-*-c-120-*-*");
2932 UNBLOCK_INPUT;
2933 if (! STRINGP (font))
2934 font = build_string ("-*-system");
2935
2936 x_default_parameter (f, parms, Qfont, font,
2937 "font", "Font", string);
2938 }
2939
2940 x_default_parameter (f, parms, Qborder_width, make_number (2),
2941 "borderwidth", "BorderWidth", number);
2942 /* This defaults to 2 in order to match xterm. We recognize either
2943 internalBorderWidth or internalBorder (which is what xterm calls
2944 it). */
2945 if (NILP (Fassq (Qinternal_border_width, parms)))
2946 {
2947 Lisp_Object value;
2948
2949 value = x_get_arg (parms, Qinternal_border_width,
2950 "internalBorder", "BorderWidth", number);
2951 if (! EQ (value, Qunbound))
2952 parms = Fcons (Fcons (Qinternal_border_width, value),
2953 parms);
2954 }
2955 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
2956 "internalBorderWidth", "BorderWidth", number);
2957 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
2958 "verticalScrollBars", "ScrollBars", boolean);
2959
2960 /* Also do the stuff which must be set before the window exists. */
2961 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
2962 "foreground", "Foreground", string);
2963 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
2964 "background", "Background", string);
2965 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
2966 "pointerColor", "Foreground", string);
2967 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
2968 "cursorColor", "Foreground", string);
2969 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
2970 "borderColor", "BorderColor", string);
2971
2972 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
2973 "menuBar", "MenuBar", number);
2974 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
2975 "scrollBarWidth", "ScrollBarWidth", number);
2976
2977 f->output_data.win32->dwStyle = WS_OVERLAPPEDWINDOW;
2978 f->output_data.win32->parent_desc = FRAME_WIN32_DISPLAY_INFO (f)->root_window;
2979 window_prompting = x_figure_window_size (f, parms);
2980
2981 if (window_prompting & XNegative)
2982 {
2983 if (window_prompting & YNegative)
2984 f->output_data.win32->win_gravity = SouthEastGravity;
2985 else
2986 f->output_data.win32->win_gravity = NorthEastGravity;
2987 }
2988 else
2989 {
2990 if (window_prompting & YNegative)
2991 f->output_data.win32->win_gravity = SouthWestGravity;
2992 else
2993 f->output_data.win32->win_gravity = NorthWestGravity;
2994 }
2995
2996 f->output_data.win32->size_hint_flags = window_prompting;
2997
2998 win32_window (f, window_prompting, minibuffer_only);
2999 x_icon (f, parms);
3000 init_frame_faces (f);
3001
3002 /* We need to do this after creating the window, so that the
3003 icon-creation functions can say whose icon they're describing. */
3004 x_default_parameter (f, parms, Qicon_type, Qnil,
3005 "bitmapIcon", "BitmapIcon", symbol);
3006
3007 x_default_parameter (f, parms, Qauto_raise, Qnil,
3008 "autoRaise", "AutoRaiseLower", boolean);
3009 x_default_parameter (f, parms, Qauto_lower, Qnil,
3010 "autoLower", "AutoRaiseLower", boolean);
3011 x_default_parameter (f, parms, Qcursor_type, Qbox,
3012 "cursorType", "CursorType", symbol);
3013
3014 /* Dimensions, especially f->height, must be done via change_frame_size.
3015 Change will not be effected unless different from the current
3016 f->height. */
3017 width = f->width;
3018 height = f->height;
3019 f->height = f->width = 0;
3020 change_frame_size (f, height, width, 1, 0);
3021
3022 /* Tell the server what size and position, etc, we want,
3023 and how badly we want them. */
3024 BLOCK_INPUT;
3025 x_wm_set_size_hint (f, window_prompting, 0);
3026 UNBLOCK_INPUT;
3027
3028 tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
3029 f->no_split = minibuffer_only || EQ (tem, Qt);
3030
3031 UNGCPRO;
3032
3033 /* It is now ok to make the frame official
3034 even if we get an error below.
3035 And the frame needs to be on Vframe_list
3036 or making it visible won't work. */
3037 Vframe_list = Fcons (frame, Vframe_list);
3038
3039 /* Now that the frame is official, it counts as a reference to
3040 its display. */
3041 FRAME_WIN32_DISPLAY_INFO (f)->reference_count++;
3042
3043 /* Make the window appear on the frame and enable display,
3044 unless the caller says not to. However, with explicit parent,
3045 Emacs cannot control visibility, so don't try. */
3046 if (! f->output_data.win32->explicit_parent)
3047 {
3048 Lisp_Object visibility;
3049
3050 visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
3051 if (EQ (visibility, Qunbound))
3052 visibility = Qt;
3053
3054 if (EQ (visibility, Qicon))
3055 x_iconify_frame (f);
3056 else if (! NILP (visibility))
3057 x_make_frame_visible (f);
3058 else
3059 /* Must have been Qnil. */
3060 ;
3061 }
3062
3063 return unbind_to (count, frame);
3064}
3065
3066/* FRAME is used only to get a handle on the X display. We don't pass the
3067 display info directly because we're called from frame.c, which doesn't
3068 know about that structure. */
3069Lisp_Object
3070x_get_focus_frame (frame)
3071 struct frame *frame;
3072{
3073 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (frame);
3074 Lisp_Object xfocus;
3075 if (! dpyinfo->win32_focus_frame)
3076 return Qnil;
3077
3078 XSETFRAME (xfocus, dpyinfo->win32_focus_frame);
3079 return xfocus;
3080}
3081
3082DEFUN ("focus-frame", Ffocus_frame, Sfocus_frame, 1, 1, 0,
3083 "Set the focus on FRAME.")
3084 (frame)
3085 Lisp_Object frame;
3086{
3087 CHECK_LIVE_FRAME (frame, 0);
3088
3089 if (FRAME_WIN32_P (XFRAME (frame)))
3090 {
3091 BLOCK_INPUT;
3092 x_focus_on_frame (XFRAME (frame));
3093 UNBLOCK_INPUT;
3094 return frame;
3095 }
3096
3097 return Qnil;
3098}
3099
3100DEFUN ("unfocus-frame", Funfocus_frame, Sunfocus_frame, 0, 0, 0,
3101 "If a frame has been focused, release it.")
3102 ()
3103{
3104 if (FRAME_WIN32_P (selected_frame))
3105 {
3106 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (selected_frame);
3107
3108 if (dpyinfo->win32_focus_frame)
3109 {
3110 BLOCK_INPUT;
3111 x_unfocus_frame (dpyinfo->win32_focus_frame);
3112 UNBLOCK_INPUT;
3113 }
3114 }
3115
3116 return Qnil;
3117}
3118
3119XFontStruct
3120*win32_load_font (dpyinfo,name)
3121struct win32_display_info *dpyinfo;
3122char * name;
3123{
3124 XFontStruct * font = NULL;
3125 BOOL ok;
3126
3127 {
3128 LOGFONT lf;
3129
3130 if (!name || !x_to_win32_font(name, &lf))
3131 return (NULL);
3132
3133 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
3134
3135 if (!font) return (NULL);
3136
3137 BLOCK_INPUT;
3138
3139 font->hfont = CreateFontIndirect(&lf);
3140 }
3141
3142 if (font->hfont == NULL)
3143 {
3144 ok = FALSE;
3145 }
3146 else
3147 {
3148 HDC hdc;
3149 HANDLE oldobj;
3150
3151 hdc = my_get_dc (dpyinfo->root_window);
3152
3153 oldobj = SelectObject (hdc, font->hfont);
3154
3155 ok = GetTextMetrics (hdc, &font->tm);
3156
3157 SelectObject (hdc, oldobj);
3158
3159 ReleaseDC (dpyinfo->root_window, hdc);
3160 }
3161
3162 UNBLOCK_INPUT;
3163
3164 if (ok) return (font);
3165
3166 win32_unload_font(dpyinfo, font);
3167 return (NULL);
3168}
3169
3170void
3171win32_unload_font (dpyinfo, font)
3172 struct win32_display_info *dpyinfo;
3173 XFontStruct * font;
3174{
3175 if (font)
3176 {
3177 if (font->hfont) DeleteObject(font->hfont);
3178 xfree (font);
3179 }
3180}
3181
3182/* The font conversion stuff between x and win32 */
3183
3184/* X font string is as follows (from faces.el)
3185 * (let ((- "[-?]")
3186 * (foundry "[^-]+")
3187 * (family "[^-]+")
3188 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
3189 * (weight\? "\\([^-]*\\)") ; 1
3190 * (slant "\\([ior]\\)") ; 2
3191 * (slant\? "\\([^-]?\\)") ; 2
3192 * (swidth "\\([^-]*\\)") ; 3
3193 * (adstyle "[^-]*") ; 4
3194 * (pixelsize "[0-9]+")
3195 * (pointsize "[0-9][0-9]+")
3196 * (resx "[0-9][0-9]+")
3197 * (resy "[0-9][0-9]+")
3198 * (spacing "[cmp?*]")
3199 * (avgwidth "[0-9]+")
3200 * (registry "[^-]+")
3201 * (encoding "[^-]+")
3202 * )
3203 * (setq x-font-regexp
3204 * (concat "\\`\\*?[-?*]"
3205 * foundry - family - weight\? - slant\? - swidth - adstyle -
3206 * pixelsize - pointsize - resx - resy - spacing - registry -
3207 * encoding "[-?*]\\*?\\'"
3208 * ))
3209 * (setq x-font-regexp-head
3210 * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
3211 * "\\([-*?]\\|\\'\\)"))
3212 * (setq x-font-regexp-slant (concat - slant -))
3213 * (setq x-font-regexp-weight (concat - weight -))
3214 * nil)
3215 */
3216
3217#define FONT_START "[-?]"
3218#define FONT_FOUNDRY "[^-]+"
3219#define FONT_FAMILY "\\([^-]+\\)" /* 1 */
3220#define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
3221#define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
3222#define FONT_SLANT "\\([ior]\\)" /* 3 */
3223#define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
3224#define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
3225#define FONT_ADSTYLE "[^-]*"
3226#define FONT_PIXELSIZE "[^-]*"
3227#define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
3228#define FONT_RESX "[0-9][0-9]+"
3229#define FONT_RESY "[0-9][0-9]+"
3230#define FONT_SPACING "[cmp?*]"
3231#define FONT_AVGWIDTH "[0-9]+"
3232#define FONT_REGISTRY "[^-]+"
3233#define FONT_ENCODING "[^-]+"
3234
3235#define FONT_REGEXP ("\\`\\*?[-?*]" \
3236 FONT_FOUNDRY "-" \
3237 FONT_FAMILY "-" \
3238 FONT_WEIGHT_Q "-" \
3239 FONT_SLANT_Q "-" \
3240 FONT_SWIDTH "-" \
3241 FONT_ADSTYLE "-" \
3242 FONT_PIXELSIZE "-" \
3243 FONT_POINTSIZE "-" \
3244 "[-?*]\\|\\'")
3245
3246#define FONT_REGEXP_HEAD ("\\`[-?*]" \
3247 FONT_FOUNDRY "-" \
3248 FONT_FAMILY "-" \
3249 FONT_WEIGHT_Q "-" \
3250 FONT_SLANT_Q \
3251 "\\([-*?]\\|\\'\\)")
3252
3253#define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
3254#define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
3255
3256LONG
3257x_to_win32_weight (lpw)
3258 char * lpw;
3259{
3260 if (!lpw) return (FW_DONTCARE);
3261
3262 if (stricmp (lpw, "bold") == 0)
3263 return (FW_BOLD);
3264 else if (stricmp (lpw, "demibold") == 0)
3265 return (FW_SEMIBOLD);
3266 else if (stricmp (lpw, "medium") == 0)
3267 return (FW_MEDIUM);
3268 else if (stricmp (lpw, "normal") == 0)
3269 return (FW_NORMAL);
3270 else
3271 return (FW_DONTCARE);
3272}
3273
3274char *
3275win32_to_x_weight (fnweight)
3276 int fnweight;
3277{
3278 if (fnweight >= FW_BOLD)
3279 return ("bold");
3280 else if (fnweight >= FW_SEMIBOLD)
3281 return ("demibold");
3282 else if (fnweight >= FW_MEDIUM)
3283 return ("medium");
3284 else
3285 return ("normal");
3286}
3287
3288BOOL
3289win32_to_x_font (lplogfont, lpxstr, len)
3290 LOGFONT * lplogfont;
3291 char * lpxstr;
3292 int len;
3293{
3294 if (!lpxstr) return (FALSE);
3295
3296 if (lplogfont)
3297 {
3298 int height = (lplogfont->lfHeight * 1440)
3299 / one_win32_display_info.height_in;
3300 int width = (lplogfont->lfWidth * 1440)
3301 / one_win32_display_info.width_in;
3302
3303 height = abs (height);
3304 _snprintf (lpxstr, len - 1,
3305 "-*-%s-%s-%c-%s-%s-*-%d-*-*-%c-%d-*-*-",
3306 lplogfont->lfFaceName,
3307 win32_to_x_weight (lplogfont->lfWeight),
3308 lplogfont->lfItalic ? 'i' : 'r',
3309 "*", "*",
3310 height,
3311 ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH) ? 'p' : 'c',
3312 width);
3313 }
3314 else
3315 {
3316 strncpy (lpxstr, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-", len - 1);
3317 }
3318
3319 lpxstr[len - 1] = 0; /* just to be sure */
3320 return (TRUE);
3321}
3322
3323BOOL
3324x_to_win32_font (lpxstr, lplogfont)
3325 char * lpxstr;
3326 LOGFONT * lplogfont;
3327{
3328 if (!lplogfont) return (FALSE);
3329
3330 memset (lplogfont, 0, sizeof (*lplogfont));
3331
3332 lplogfont->lfCharSet = OEM_CHARSET;
3333 lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
3334 lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
3335 lplogfont->lfQuality = DEFAULT_QUALITY;
3336
3337 if (lpxstr && *lpxstr == '-') lpxstr++;
3338
3339 {
3340 int fields;
3341 char name[50], weight[20], slant, pitch, height[10], width[10];
3342
3343 fields = (lpxstr
3344 ? sscanf (lpxstr,
3345 "%*[^-]-%[^-]-%[^-]-%c-%*[^-]-%*[^-]-%*[^-]-%[^-]-%*[^-]-%*[^-]-%c-%[^-]",
3346 name, weight, &slant, height, &pitch, width)
3347 : 0);
3348
3349 if (fields == EOF) return (FALSE);
3350
3351 if (fields > 0 && name[0] != '*')
3352 {
3353 strncpy (lplogfont->lfFaceName, name, LF_FACESIZE);
3354 }
3355 else
3356 {
3357 lplogfont->lfFaceName[0] = 0;
3358 }
3359
3360 fields--;
3361
3362 lplogfont->lfWeight = x_to_win32_weight((fields > 0 ? weight : ""));
3363
3364 fields--;
3365
3366 lplogfont->lfItalic = (fields > 0 && slant == 'i');
3367
3368 fields--;
3369
3370 if (fields > 0 && height[0] != '*')
3371 lplogfont->lfHeight = (atoi (height) * one_win32_display_info.height_in) / 1440;
3372
3373 fields--;
3374
3375 lplogfont->lfPitchAndFamily = (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
3376
3377 fields--;
3378
3379 if (fields > 0 && width[0] != '*')
3380 lplogfont->lfWidth = (atoi (width) * one_win32_display_info.width_in) / 1440;
3381 }
3382
3383 return (TRUE);
3384}
3385
3386BOOL
3387win32_font_match (lpszfont1, lpszfont2)
3388 char * lpszfont1;
3389 char * lpszfont2;
3390{
3391 char * s1 = lpszfont1, *e1;
3392 char * s2 = lpszfont2, *e2;
3393
3394 if (s1 == NULL || s2 == NULL) return (FALSE);
3395
3396 if (*s1 == '-') s1++;
3397 if (*s2 == '-') s2++;
3398
3399 while (1)
3400 {
3401 int len1, len2;
3402
3403 e1 = strchr (s1, '-');
3404 e2 = strchr (s2, '-');
3405
3406 if (e1 == NULL || e2 == NULL) return (TRUE);
3407
3408 len1 = e1 - s1;
3409 len2 = e2 - s2;
3410
3411 if (*s1 != '*' && *s2 != '*'
3412 && (len1 != len2 || strnicmp (s1, s2, len1) != 0))
3413 return (FALSE);
3414
3415 s1 = e1 + 1;
3416 s2 = e2 + 1;
3417 }
3418}
3419
3420typedef struct enumfont_t
3421{
3422 HDC hdc;
3423 int numFonts;
3424 XFontStruct *size_ref;
3425 Lisp_Object *pattern;
3426 Lisp_Object *head;
3427 Lisp_Object *tail;
3428} enumfont_t;
3429
3430int CALLBACK
3431enum_font_cb2 (lplf, lptm, FontType, lpef)
3432 ENUMLOGFONT * lplf;
3433 NEWTEXTMETRIC * lptm;
3434 int FontType;
3435 enumfont_t * lpef;
3436{
3437 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline
3438 || (lplf->elfLogFont.lfCharSet != ANSI_CHARSET && lplf->elfLogFont.lfCharSet != OEM_CHARSET))
3439 return (1);
3440
3441 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */
3442 {
3443 char buf[100];
3444
3445 if (!win32_to_x_font (lplf, buf, 100)) return (0);
3446
3447 if (NILP (*(lpef->pattern)) || win32_font_match (buf, XSTRING (*(lpef->pattern))->data))
3448 {
3449 *lpef->tail = Fcons (build_string (buf), Qnil);
3450 lpef->tail = &XCONS (*lpef->tail)->cdr;
3451 lpef->numFonts++;
3452 }
3453 }
3454
3455 return (1);
3456}
3457
3458int CALLBACK
3459enum_font_cb1 (lplf, lptm, FontType, lpef)
3460 ENUMLOGFONT * lplf;
3461 NEWTEXTMETRIC * lptm;
3462 int FontType;
3463 enumfont_t * lpef;
3464{
3465 return EnumFontFamilies (lpef->hdc,
3466 lplf->elfLogFont.lfFaceName,
3467 (FONTENUMPROC) enum_font_cb2,
3468 (LPARAM) lpef);
3469}
3470
3471
3472DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 3, 0,
3473 "Return a list of the names of available fonts matching PATTERN.\n\
3474If optional arguments FACE and FRAME are specified, return only fonts\n\
3475the same size as FACE on FRAME.\n\
3476\n\
3477PATTERN is a string, perhaps with wildcard characters;\n\
3478 the * character matches any substring, and\n\
3479 the ? character matches any single character.\n\
3480 PATTERN is case-insensitive.\n\
3481FACE is a face name--a symbol.\n\
3482\n\
3483The return value is a list of strings, suitable as arguments to\n\
3484set-face-font.\n\
3485\n\
3486Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
3487even if they match PATTERN and FACE.")
3488 (pattern, face, frame)
3489 Lisp_Object pattern, face, frame;
3490{
3491 int num_fonts;
3492 char **names;
3493 XFontStruct *info;
3494 XFontStruct *size_ref;
3495 Lisp_Object namelist;
3496 Lisp_Object list;
3497 FRAME_PTR f;
3498 enumfont_t ef;
3499
3500 CHECK_STRING (pattern, 0);
3501 if (!NILP (face))
3502 CHECK_SYMBOL (face, 1);
3503
3504 f = check_x_frame (frame);
3505
3506 /* Determine the width standard for comparison with the fonts we find. */
3507
3508 if (NILP (face))
3509 size_ref = 0;
3510 else
3511 {
3512 int face_id;
3513
3514 /* Don't die if we get called with a terminal frame. */
3515 if (! FRAME_WIN32_P (f))
3516 error ("non-win32 frame used in `x-list-fonts'");
3517
3518 face_id = face_name_id_number (f, face);
3519
3520 if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
3521 || FRAME_PARAM_FACES (f) [face_id] == 0)
3522 size_ref = f->output_data.win32->font;
3523 else
3524 {
3525 size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
3526 if (size_ref == (XFontStruct *) (~0))
3527 size_ref = f->output_data.win32->font;
3528 }
3529 }
3530
3531 /* See if we cached the result for this particular query. */
3532 list = Fassoc (pattern,
3533 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->cdr);
3534
3535 /* We have info in the cache for this PATTERN. */
3536 if (!NILP (list))
3537 {
3538 Lisp_Object tem, newlist;
3539
3540 /* We have info about this pattern. */
3541 list = XCONS (list)->cdr;
3542
3543 if (size_ref == 0)
3544 return list;
3545
3546 BLOCK_INPUT;
3547
3548 /* Filter the cached info and return just the fonts that match FACE. */
3549 newlist = Qnil;
3550 for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
3551 {
3552 XFontStruct *thisinfo;
3553
3554 thisinfo = win32_load_font (FRAME_WIN32_DISPLAY_INFO (f), XSTRING (XCONS (tem)->car)->data);
3555
3556 if (thisinfo && same_size_fonts (thisinfo, size_ref))
3557 newlist = Fcons (XCONS (tem)->car, newlist);
3558
3559 win32_unload_font (FRAME_WIN32_DISPLAY_INFO (f), thisinfo);
3560 }
3561
3562 UNBLOCK_INPUT;
3563
3564 return newlist;
3565 }
3566
3567 BLOCK_INPUT;
3568
3569 namelist = Qnil;
3570 ef.pattern = &pattern;
3571 ef.tail = ef.head = &namelist;
3572 ef.numFonts = 0;
3573
3574 {
3575 ef.hdc = my_get_dc (FRAME_WIN32_WINDOW (f));
3576
3577 EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1, (LPARAM)&ef);
3578
3579 ReleaseDC (FRAME_WIN32_WINDOW (f), ef.hdc);
3580 }
3581
3582 UNBLOCK_INPUT;
3583
3584 if (ef.numFonts)
3585 {
3586 int i;
3587 Lisp_Object cur;
3588
3589 /* Make a list of all the fonts we got back.
3590 Store that in the font cache for the display. */
3591 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->cdr
3592 = Fcons (Fcons (pattern, namelist),
3593 XCONS (FRAME_WIN32_DISPLAY_INFO (f)->name_list_element)->cdr);
3594
3595 /* Make a list of the fonts that have the right width. */
3596 list = Qnil;
3597 cur=namelist;
3598 for (i = 0; i < ef.numFonts; i++)
3599 {
3600 int keeper;
3601
3602 if (!size_ref)
3603 keeper = 1;
3604 else
3605 {
3606 XFontStruct *thisinfo;
3607
3608 BLOCK_INPUT;
3609 thisinfo = win32_load_font (FRAME_WIN32_DISPLAY_INFO (f), XSTRING (Fcar (cur))->data);
3610
3611 keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
3612
3613 win32_unload_font (FRAME_WIN32_DISPLAY_INFO (f), thisinfo);
3614
3615 UNBLOCK_INPUT;
3616 }
3617 if (keeper)
3618 list = Fcons (build_string (XSTRING (Fcar (cur))->data), list);
3619
3620 cur = Fcdr (cur);
3621 }
3622 list = Fnreverse (list);
3623 }
3624
3625 return list;
3626}
3627
3628DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
3629 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3630If FRAME is omitted or nil, use the selected frame.")
3631 (color, frame)
3632 Lisp_Object color, frame;
3633{
3634 COLORREF foo;
3635 FRAME_PTR f = check_x_frame (frame);
3636
3637 CHECK_STRING (color, 1);
3638
3639 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3640 return Qt;
3641 else
3642 return Qnil;
3643}
3644
3645DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
3646 "Return a description of the color named COLOR on frame FRAME.\n\
3647The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3648These values appear to range from 0 to 65280 or 65535, depending\n\
3649on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3650If FRAME is omitted or nil, use the selected frame.")
3651 (color, frame)
3652 Lisp_Object color, frame;
3653{
3654 COLORREF foo;
3655 FRAME_PTR f = check_x_frame (frame);
3656
3657 CHECK_STRING (color, 1);
3658
3659 if (defined_color (f, XSTRING (color)->data, &foo, 0))
3660 {
3661 Lisp_Object rgb[3];
3662
3663 rgb[0] = make_number (GetRValue (foo));
3664 rgb[1] = make_number (GetGValue (foo));
3665 rgb[2] = make_number (GetBValue (foo));
3666 return Flist (3, rgb);
3667 }
3668 else
3669 return Qnil;
3670}
3671
3672DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
3673 "Return t if the X display supports color.\n\
3674The optional argument DISPLAY specifies which display to ask about.\n\
3675DISPLAY should be either a frame or a display name (a string).\n\
3676If omitted or nil, that stands for the selected frame's display.")
3677 (display)
3678 Lisp_Object display;
3679{
3680 struct win32_display_info *dpyinfo = check_x_display_info (display);
3681
3682 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
3683 return Qnil;
3684
3685 return Qt;
3686}
3687
3688DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3689 0, 1, 0,
3690 "Return t if the X display supports shades of gray.\n\
3691Note that color displays do support shades of gray.\n\
3692The optional argument DISPLAY specifies which display to ask about.\n\
3693DISPLAY should be either a frame or a display name (a string).\n\
3694If omitted or nil, that stands for the selected frame's display.")
3695 (display)
3696 Lisp_Object display;
3697{
3698 struct win32_display_info *dpyinfo = check_x_display_info (display);
3699
3700 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
3701 return Qnil;
3702
3703 return Qt;
3704}
3705
3706DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3707 0, 1, 0,
3708 "Returns the width in pixels of the X display DISPLAY.\n\
3709The optional argument DISPLAY specifies which display to ask about.\n\
3710DISPLAY should be either a frame or a display name (a string).\n\
3711If omitted or nil, that stands for the selected frame's display.")
3712 (display)
3713 Lisp_Object display;
3714{
3715 struct win32_display_info *dpyinfo = check_x_display_info (display);
3716
3717 return make_number (dpyinfo->width);
3718}
3719
3720DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3721 Sx_display_pixel_height, 0, 1, 0,
3722 "Returns the height in pixels of the X display DISPLAY.\n\
3723The optional argument DISPLAY specifies which display to ask about.\n\
3724DISPLAY should be either a frame or a display name (a string).\n\
3725If omitted or nil, that stands for the selected frame's display.")
3726 (display)
3727 Lisp_Object display;
3728{
3729 struct win32_display_info *dpyinfo = check_x_display_info (display);
3730
3731 return make_number (dpyinfo->height);
3732}
3733
3734DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3735 0, 1, 0,
3736 "Returns the number of bitplanes of the display DISPLAY.\n\
3737The optional argument DISPLAY specifies which display to ask about.\n\
3738DISPLAY should be either a frame or a display name (a string).\n\
3739If omitted or nil, that stands for the selected frame's display.")
3740 (display)
3741 Lisp_Object display;
3742{
3743 struct win32_display_info *dpyinfo = check_x_display_info (display);
3744
3745 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
3746}
3747
3748DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3749 0, 1, 0,
3750 "Returns the number of color cells of the display DISPLAY.\n\
3751The optional argument DISPLAY specifies which display to ask about.\n\
3752DISPLAY should be either a frame or a display name (a string).\n\
3753If omitted or nil, that stands for the selected frame's display.")
3754 (display)
3755 Lisp_Object display;
3756{
3757 struct win32_display_info *dpyinfo = check_x_display_info (display);
3758 HDC hdc;
3759 int cap;
3760
3761 hdc = my_get_dc (dpyinfo->root_window);
3762
3763 cap = GetDeviceCaps (hdc,NUMCOLORS);
3764
3765 ReleaseDC (dpyinfo->root_window, hdc);
3766
3767 return make_number (cap);
3768}
3769
3770DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3771 Sx_server_max_request_size,
3772 0, 1, 0,
3773 "Returns the maximum request size of the server of display DISPLAY.\n\
3774The optional argument DISPLAY specifies which display to ask about.\n\
3775DISPLAY should be either a frame or a display name (a string).\n\
3776If omitted or nil, that stands for the selected frame's display.")
3777 (display)
3778 Lisp_Object display;
3779{
3780 struct win32_display_info *dpyinfo = check_x_display_info (display);
3781
3782 return make_number (1);
3783}
3784
3785DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3786 "Returns the vendor ID string of the Win32 system (Microsoft).\n\
3787The optional argument DISPLAY specifies which display to ask about.\n\
3788DISPLAY should be either a frame or a display name (a string).\n\
3789If omitted or nil, that stands for the selected frame's display.")
3790 (display)
3791 Lisp_Object display;
3792{
3793 struct win32_display_info *dpyinfo = check_x_display_info (display);
3794 char *vendor = "Microsoft Corp.";
3795
3796 if (! vendor) vendor = "";
3797 return build_string (vendor);
3798}
3799
3800DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3801 "Returns the version numbers of the server of display DISPLAY.\n\
3802The value is a list of three integers: the major and minor\n\
3803version numbers, and the vendor-specific release\n\
3804number. See also the function `x-server-vendor'.\n\n\
3805The optional argument DISPLAY specifies which display to ask about.\n\
3806DISPLAY should be either a frame or a display name (a string).\n\
3807If omitted or nil, that stands for the selected frame's display.")
3808 (display)
3809 Lisp_Object display;
3810{
3811 struct win32_display_info *dpyinfo = check_x_display_info (display);
3812
3813 return Fcons (make_number (nt_major_version),
3814 Fcons (make_number (nt_minor_version), Qnil));
3815}
3816
3817DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3818 "Returns the number of screens on the server of display DISPLAY.\n\
3819The optional argument DISPLAY specifies which display to ask about.\n\
3820DISPLAY should be either a frame or a display name (a string).\n\
3821If omitted or nil, that stands for the selected frame's display.")
3822 (display)
3823 Lisp_Object display;
3824{
3825 struct win32_display_info *dpyinfo = check_x_display_info (display);
3826
3827 return make_number (1);
3828}
3829
3830DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3831 "Returns the height in millimeters of the X display DISPLAY.\n\
3832The optional argument DISPLAY specifies which display to ask about.\n\
3833DISPLAY should be either a frame or a display name (a string).\n\
3834If omitted or nil, that stands for the selected frame's display.")
3835 (display)
3836 Lisp_Object display;
3837{
3838 struct win32_display_info *dpyinfo = check_x_display_info (display);
3839 HDC hdc;
3840 int cap;
3841
3842 hdc = my_get_dc (dpyinfo->root_window);
3843
3844 cap = GetDeviceCaps (hdc, VERTSIZE);
3845
3846 ReleaseDC (dpyinfo->root_window, hdc);
3847
3848 return make_number (cap);
3849}
3850
3851DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3852 "Returns the width in millimeters of the X display DISPLAY.\n\
3853The optional argument DISPLAY specifies which display to ask about.\n\
3854DISPLAY should be either a frame or a display name (a string).\n\
3855If omitted or nil, that stands for the selected frame's display.")
3856 (display)
3857 Lisp_Object display;
3858{
3859 struct win32_display_info *dpyinfo = check_x_display_info (display);
3860
3861 HDC hdc;
3862 int cap;
3863
3864 hdc = my_get_dc (dpyinfo->root_window);
3865
3866 cap = GetDeviceCaps (hdc, HORZSIZE);
3867
3868 ReleaseDC (dpyinfo->root_window, hdc);
3869
3870 return make_number (cap);
3871}
3872
3873DEFUN ("x-display-backing-store", Fx_display_backing_store,
3874 Sx_display_backing_store, 0, 1, 0,
3875 "Returns an indication of whether display DISPLAY does backing store.\n\
3876The value may be `always', `when-mapped', or `not-useful'.\n\
3877The optional argument DISPLAY specifies which display to ask about.\n\
3878DISPLAY should be either a frame or a display name (a string).\n\
3879If omitted or nil, that stands for the selected frame's display.")
3880 (display)
3881 Lisp_Object display;
3882{
3883 return intern ("not-useful");
3884}
3885
3886DEFUN ("x-display-visual-class", Fx_display_visual_class,
3887 Sx_display_visual_class, 0, 1, 0,
3888 "Returns the visual class of the display DISPLAY.\n\
3889The value is one of the symbols `static-gray', `gray-scale',\n\
3890`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
3891The optional argument DISPLAY specifies which display to ask about.\n\
3892DISPLAY should be either a frame or a display name (a string).\n\
3893If omitted or nil, that stands for the selected frame's display.")
3894 (display)
3895 Lisp_Object display;
3896{
3897 struct win32_display_info *dpyinfo = check_x_display_info (display);
3898
3899#if 0
3900 switch (dpyinfo->visual->class)
3901 {
3902 case StaticGray: return (intern ("static-gray"));
3903 case GrayScale: return (intern ("gray-scale"));
3904 case StaticColor: return (intern ("static-color"));
3905 case PseudoColor: return (intern ("pseudo-color"));
3906 case TrueColor: return (intern ("true-color"));
3907 case DirectColor: return (intern ("direct-color"));
3908 default:
3909 error ("Display has an unknown visual class");
3910 }
3911#endif
3912
3913 error ("Display has an unknown visual class");
3914}
3915
3916DEFUN ("x-display-save-under", Fx_display_save_under,
3917 Sx_display_save_under, 0, 1, 0,
3918 "Returns t if the display DISPLAY supports the save-under feature.\n\
3919The optional argument DISPLAY specifies which display to ask about.\n\
3920DISPLAY should be either a frame or a display name (a string).\n\
3921If omitted or nil, that stands for the selected frame's display.")
3922 (display)
3923 Lisp_Object display;
3924{
3925 struct win32_display_info *dpyinfo = check_x_display_info (display);
3926
3927 return Qnil;
3928}
3929
3930int
3931x_pixel_width (f)
3932 register struct frame *f;
3933{
3934 return PIXEL_WIDTH (f);
3935}
3936
3937int
3938x_pixel_height (f)
3939 register struct frame *f;
3940{
3941 return PIXEL_HEIGHT (f);
3942}
3943
3944int
3945x_char_width (f)
3946 register struct frame *f;
3947{
3948 return FONT_WIDTH (f->output_data.win32->font);
3949}
3950
3951int
3952x_char_height (f)
3953 register struct frame *f;
3954{
3955 return f->output_data.win32->line_height;
3956}
3957
3958int
3959x_screen_planes (frame)
3960 Lisp_Object frame;
3961{
3962 return (FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_planes *
3963 FRAME_WIN32_DISPLAY_INFO (XFRAME (frame))->n_cbits);
3964}
3965
3966/* Return the display structure for the display named NAME.
3967 Open a new connection if necessary. */
3968
3969struct win32_display_info *
3970x_display_info_for_name (name)
3971 Lisp_Object name;
3972{
3973 Lisp_Object names;
3974 struct win32_display_info *dpyinfo;
3975
3976 CHECK_STRING (name, 0);
3977
3978 for (dpyinfo = &one_win32_display_info, names = win32_display_name_list;
3979 dpyinfo;
3980 dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
3981 {
3982 Lisp_Object tem;
3983 tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
3984 if (!NILP (tem))
3985 return dpyinfo;
3986 }
3987
3988 /* Use this general default value to start with. */
3989 Vx_resource_name = Vinvocation_name;
3990
3991 validate_x_resource_name ();
3992
3993 dpyinfo = win32_term_init (name, (unsigned char *)0,
3994 (char *) XSTRING (Vx_resource_name)->data);
3995
3996 if (dpyinfo == 0)
3997 error ("Cannot connect to server %s", XSTRING (name)->data);
3998
3999 XSETFASTINT (Vwindow_system_version, 3);
4000
4001 return dpyinfo;
4002}
4003
4004DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4005 1, 3, 0, "Open a connection to a server.\n\
4006DISPLAY is the name of the display to connect to.\n\
4007Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4008If the optional third arg MUST-SUCCEED is non-nil,\n\
4009terminate Emacs if we can't open the connection.")
4010 (display, xrm_string, must_succeed)
4011 Lisp_Object display, xrm_string, must_succeed;
4012{
4013 unsigned int n_planes;
4014 unsigned char *xrm_option;
4015 struct win32_display_info *dpyinfo;
4016
4017 CHECK_STRING (display, 0);
4018 if (! NILP (xrm_string))
4019 CHECK_STRING (xrm_string, 1);
4020
4021 Vwin32_color_map = Fwin32_default_color_map ();
4022
4023 if (! NILP (xrm_string))
4024 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4025 else
4026 xrm_option = (unsigned char *) 0;
4027
4028 /* Use this general default value to start with. */
4029 Vx_resource_name = Vinvocation_name;
4030
4031 validate_x_resource_name ();
4032
4033 /* This is what opens the connection and sets x_current_display.
4034 This also initializes many symbols, such as those used for input. */
4035 dpyinfo = win32_term_init (display, xrm_option,
4036 (char *) XSTRING (Vx_resource_name)->data);
4037
4038 if (dpyinfo == 0)
4039 {
4040 if (!NILP (must_succeed))
4041 fatal ("Cannot connect to server %s.\n",
4042 XSTRING (display)->data);
4043 else
4044 error ("Cannot connect to server %s", XSTRING (display)->data);
4045 }
4046
4047 XSETFASTINT (Vwindow_system_version, 3);
4048 return Qnil;
4049}
4050
4051DEFUN ("x-close-connection", Fx_close_connection,
4052 Sx_close_connection, 1, 1, 0,
4053 "Close the connection to DISPLAY's server.\n\
4054For DISPLAY, specify either a frame or a display name (a string).\n\
4055If DISPLAY is nil, that stands for the selected frame's display.")
4056 (display)
4057 Lisp_Object display;
4058{
4059 struct win32_display_info *dpyinfo = check_x_display_info (display);
4060 struct win32_display_info *tail;
4061 int i;
4062
4063 if (dpyinfo->reference_count > 0)
4064 error ("Display still has frames on it");
4065
4066 BLOCK_INPUT;
4067 /* Free the fonts in the font table. */
4068 for (i = 0; i < dpyinfo->n_fonts; i++)
4069 {
4070 if (dpyinfo->font_table[i].name)
4071 free (dpyinfo->font_table[i].name);
4072 /* Don't free the full_name string;
4073 it is always shared with something else. */
4074 win32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
4075 }
4076 x_destroy_all_bitmaps (dpyinfo);
4077
4078 x_delete_display (dpyinfo);
4079 UNBLOCK_INPUT;
4080
4081 return Qnil;
4082}
4083
4084DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4085 "Return the list of display names that Emacs has connections to.")
4086 ()
4087{
4088 Lisp_Object tail, result;
4089
4090 result = Qnil;
4091 for (tail = win32_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
4092 result = Fcons (XCONS (XCONS (tail)->car)->car, result);
4093
4094 return result;
4095}
4096
4097DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4098 "If ON is non-nil, report errors as soon as the erring request is made.\n\
4099If ON is nil, allow buffering of requests.\n\
4100This is a noop on Win32 systems.\n\
4101The optional second argument DISPLAY specifies which display to act on.\n\
4102DISPLAY should be either a frame or a display name (a string).\n\
4103If DISPLAY is omitted or nil, that stands for the selected frame's display.")
4104 (on, display)
4105 Lisp_Object display, on;
4106{
4107 struct win32_display_info *dpyinfo = check_x_display_info (display);
4108
4109 return Qnil;
4110}
4111
4112
4113/* These are the win32 specialized functions */
4114
4115DEFUN ("win32-select-font", Fwin32_select_font, Swin32_select_font, 0, 1, 0,
4116 "This will display the Win32 font dialog and return an X font string corresponding to the selection.")
4117 (frame)
4118 Lisp_Object frame;
4119{
4120 FRAME_PTR f = check_x_frame (frame);
4121 CHOOSEFONT cf;
4122 LOGFONT lf;
4123 char buf[100];
4124
4125 bzero (&cf, sizeof (cf));
4126
4127 cf.lStructSize = sizeof (cf);
4128 cf.hwndOwner = FRAME_WIN32_WINDOW (f);
4129 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST | CF_SCREENFONTS;
4130 cf.lpLogFont = &lf;
4131
4132 if (!ChooseFont (&cf) || !win32_to_x_font (&lf, buf, 100))
4133 return Qnil;
4134
4135 return build_string (buf);
4136}
4137
4138
4139syms_of_win32fns ()
4140{
4141 /* The section below is built by the lisp expression at the top of the file,
4142 just above where these variables are declared. */
4143 /*&&& init symbols here &&&*/
4144 Qauto_raise = intern ("auto-raise");
4145 staticpro (&Qauto_raise);
4146 Qauto_lower = intern ("auto-lower");
4147 staticpro (&Qauto_lower);
4148 Qbackground_color = intern ("background-color");
4149 staticpro (&Qbackground_color);
4150 Qbar = intern ("bar");
4151 staticpro (&Qbar);
4152 Qborder_color = intern ("border-color");
4153 staticpro (&Qborder_color);
4154 Qborder_width = intern ("border-width");
4155 staticpro (&Qborder_width);
4156 Qbox = intern ("box");
4157 staticpro (&Qbox);
4158 Qcursor_color = intern ("cursor-color");
4159 staticpro (&Qcursor_color);
4160 Qcursor_type = intern ("cursor-type");
4161 staticpro (&Qcursor_type);
4162 Qfont = intern ("font");
4163 staticpro (&Qfont);
4164 Qforeground_color = intern ("foreground-color");
4165 staticpro (&Qforeground_color);
4166 Qgeometry = intern ("geometry");
4167 staticpro (&Qgeometry);
4168 Qicon_left = intern ("icon-left");
4169 staticpro (&Qicon_left);
4170 Qicon_top = intern ("icon-top");
4171 staticpro (&Qicon_top);
4172 Qicon_type = intern ("icon-type");
4173 staticpro (&Qicon_type);
4174 Qicon_name = intern ("icon-name");
4175 staticpro (&Qicon_name);
4176 Qinternal_border_width = intern ("internal-border-width");
4177 staticpro (&Qinternal_border_width);
4178 Qleft = intern ("left");
4179 staticpro (&Qleft);
4180 Qmouse_color = intern ("mouse-color");
4181 staticpro (&Qmouse_color);
4182 Qnone = intern ("none");
4183 staticpro (&Qnone);
4184 Qparent_id = intern ("parent-id");
4185 staticpro (&Qparent_id);
4186 Qscroll_bar_width = intern ("scroll-bar-width");
4187 staticpro (&Qscroll_bar_width);
4188 Qsuppress_icon = intern ("suppress-icon");
4189 staticpro (&Qsuppress_icon);
4190 Qtop = intern ("top");
4191 staticpro (&Qtop);
4192 Qundefined_color = intern ("undefined-color");
4193 staticpro (&Qundefined_color);
4194 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
4195 staticpro (&Qvertical_scroll_bars);
4196 Qvisibility = intern ("visibility");
4197 staticpro (&Qvisibility);
4198 Qwindow_id = intern ("window-id");
4199 staticpro (&Qwindow_id);
4200 Qx_frame_parameter = intern ("x-frame-parameter");
4201 staticpro (&Qx_frame_parameter);
4202 Qx_resource_name = intern ("x-resource-name");
4203 staticpro (&Qx_resource_name);
4204 Quser_position = intern ("user-position");
4205 staticpro (&Quser_position);
4206 Quser_size = intern ("user-size");
4207 staticpro (&Quser_size);
4208 Qdisplay = intern ("display");
4209 staticpro (&Qdisplay);
4210 /* This is the end of symbol initialization. */
4211
4212 Fput (Qundefined_color, Qerror_conditions,
4213 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
4214 Fput (Qundefined_color, Qerror_message,
4215 build_string ("Undefined color"));
4216
4217 DEFVAR_LISP ("win32-color-map", &Vwin32_color_map,
4218 "A array of color name mappings for windows.");
4219 Vwin32_color_map = Qnil;
4220
4221 init_x_parm_symbols ();
4222
4223 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
4224 "List of directories to search for bitmap files for win32.");
4225 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
4226
4227 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
4228 "The shape of the pointer when over text.\n\
4229Changing the value does not affect existing frames\n\
4230unless you set the mouse color.");
4231 Vx_pointer_shape = Qnil;
4232
4233 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
4234 "The name Emacs uses to look up resources; for internal use only.\n\
4235`x-get-resource' uses this as the first component of the instance name\n\
4236when requesting resource values.\n\
4237Emacs initially sets `x-resource-name' to the name under which Emacs\n\
4238was invoked, or to the value specified with the `-name' or `-rn'\n\
4239switches, if present.");
4240 Vx_resource_name = Qnil;
4241
4242 Vx_nontext_pointer_shape = Qnil;
4243
4244 Vx_mode_pointer_shape = Qnil;
4245
4246 DEFVAR_INT ("x-sensitive-text-pointer-shape",
4247 &Vx_sensitive_text_pointer_shape,
4248 "The shape of the pointer when over mouse-sensitive text.\n\
4249This variable takes effect when you create a new frame\n\
4250or when you set the mouse color.");
4251 Vx_sensitive_text_pointer_shape = Qnil;
4252
4253 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
4254 "A string indicating the foreground color of the cursor box.");
4255 Vx_cursor_fore_pixel = Qnil;
4256
4257 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
4258 "Non-nil if no window manager is in use.\n\
4259Emacs doesn't try to figure this out; this is always nil\n\
4260unless you set it to something else.");
4261 /* We don't have any way to find this out, so set it to nil
4262 and maybe the user would like to set it to t. */
4263 Vx_no_window_manager = Qnil;
4264
4265 defsubr (&Sx_get_resource);
4266 defsubr (&Sx_list_fonts);
4267 defsubr (&Sx_display_color_p);
4268 defsubr (&Sx_display_grayscale_p);
4269 defsubr (&Sx_color_defined_p);
4270 defsubr (&Sx_color_values);
4271 defsubr (&Sx_server_max_request_size);
4272 defsubr (&Sx_server_vendor);
4273 defsubr (&Sx_server_version);
4274 defsubr (&Sx_display_pixel_width);
4275 defsubr (&Sx_display_pixel_height);
4276 defsubr (&Sx_display_mm_width);
4277 defsubr (&Sx_display_mm_height);
4278 defsubr (&Sx_display_screens);
4279 defsubr (&Sx_display_planes);
4280 defsubr (&Sx_display_color_cells);
4281 defsubr (&Sx_display_visual_class);
4282 defsubr (&Sx_display_backing_store);
4283 defsubr (&Sx_display_save_under);
4284 defsubr (&Sx_parse_geometry);
4285 defsubr (&Sx_create_frame);
4286 defsubr (&Sfocus_frame);
4287 defsubr (&Sunfocus_frame);
4288 defsubr (&Sx_open_connection);
4289 defsubr (&Sx_close_connection);
4290 defsubr (&Sx_display_list);
4291 defsubr (&Sx_synchronize);
4292
4293 /* Win32 specific functions */
4294
4295 defsubr (&Swin32_select_font);
4296}
4297
4298#undef abort
4299
4300void
4301win32_abort()
4302{
4303 MessageBox (NULL,
4304 "A fatal error has occurred - aborting!",
4305 "Emacs Abort Dialog",
4306 MB_OK|MB_ICONEXCLAMATION);
4307 abort();
4308}
diff --git a/src/w32gui.h b/src/w32gui.h
new file mode 100644
index 00000000000..ba04d1ac615
--- /dev/null
+++ b/src/w32gui.h
@@ -0,0 +1,83 @@
1/* Definitions and headers for communication with Win32 GUI.
2 Copyright (C) 1995 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#ifndef __WIN32_H__
21#define __WIN32_H__
22
23#include <windows.h>
24
25typedef struct W32FontStruct {
26 TEXTMETRIC tm;
27 HFONT hfont;
28} W32FontStruct;
29
30typedef HBITMAP Pixmap;
31typedef HBITMAP Bitmap;
32typedef struct W32FontStruct XFontStruct;
33typedef HDC GC;
34typedef COLORREF Color;
35typedef DWORD Time;
36typedef HWND Window;
37typedef HCURSOR Cursor;
38
39#define FACE_DEFAULT (~0)
40
41extern HINSTANCE hinst;
42extern HINSTANCE hprevinst;
43extern LPSTR lpCmdLine;
44extern int nCmdShow;
45
46/* Bit Gravity */
47
48#define ForgetGravity 0
49#define NorthWestGravity 1
50#define NorthGravity 2
51#define NorthEastGravity 3
52#define WestGravity 4
53#define CenterGravity 5
54#define EastGravity 6
55#define SouthWestGravity 7
56#define SouthGravity 8
57#define SouthEastGravity 9
58#define StaticGravity 10
59
60#define NoValue 0x0000
61#define XValue 0x0001
62#define YValue 0x0002
63#define WidthValue 0x0004
64#define HeightValue 0x0008
65#define AllValues 0x000F
66#define XNegative 0x0010
67#define YNegative 0x0020
68
69#define USPosition (1L << 0) /* user specified x, y */
70#define USSize (1L << 1) /* user specified width, height */
71
72#define PPosition (1L << 2) /* program specified position */
73#define PSize (1L << 3) /* program specified size */
74#define PMinSize (1L << 4) /* program specified minimum size */
75#define PMaxSize (1L << 5) /* program specified maximum size */
76#define PResizeInc (1L << 6) /* program specified resize increments */
77#define PAspect (1L << 7) /* program specified min and max aspect ratios */
78#define PBaseSize (1L << 8) /* program specified base for incrementing */
79#define PWinGravity (1L << 9) /* program specified window gravity */
80
81extern int XParseGeometry ();
82
83#endif
diff --git a/src/w32menu.c b/src/w32menu.c
new file mode 100644
index 00000000000..e07255021e6
--- /dev/null
+++ b/src/w32menu.c
@@ -0,0 +1,1917 @@
1/* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1986, 1988, 1993, 1994 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* Written by Kevin Gallo. */
21
22#include <signal.h>
23#include <config.h>
24
25#include <stdio.h>
26#include "lisp.h"
27#include "termhooks.h"
28#include "frame.h"
29#include "window.h"
30#include "keyboard.h"
31#include "blockinput.h"
32
33/* This may include sys/types.h, and that somehow loses
34 if this is not done before the other system files. */
35#include "w32term.h"
36
37/* Load sys/types.h if not already loaded.
38 In some systems loading it twice is suicidal. */
39#ifndef makedev
40#include <sys/types.h>
41#endif
42
43#include "dispextern.h"
44
45#define min(x, y) (((x) < (y)) ? (x) : (y))
46#define max(x, y) (((x) > (y)) ? (x) : (y))
47
48typedef struct menu_map
49{
50 Lisp_Object menu_items;
51 int menu_items_allocated;
52 int menu_items_used;
53} menu_map;
54
55extern Lisp_Object Qmenu_enable;
56extern Lisp_Object Qmenu_bar;
57
58static Lisp_Object win32_dialog_show ();
59static Lisp_Object win32menu_show ();
60
61static HMENU keymap_panes ();
62static HMENU single_keymap_panes ();
63static HMENU list_of_panes ();
64static HMENU list_of_items ();
65
66static HMENU create_menu_items ();
67
68/* Initialize the menu_items structure if we haven't already done so.
69 Also mark it as currently empty. */
70
71static void
72init_menu_items (lpmm)
73 menu_map * lpmm;
74{
75 if (NILP (lpmm->menu_items))
76 {
77 lpmm->menu_items_allocated = 60;
78 lpmm->menu_items = Fmake_vector (make_number (lpmm->menu_items_allocated),
79 Qnil);
80 }
81
82 lpmm->menu_items_used = 0;
83}
84
85/* Call when finished using the data for the current menu
86 in menu_items. */
87
88static void
89discard_menu_items (lpmm)
90 menu_map * lpmm;
91{
92 lpmm->menu_items = Qnil;
93 lpmm->menu_items_allocated = lpmm->menu_items_used = 0;
94}
95
96/* Make the menu_items vector twice as large. */
97
98static void
99grow_menu_items (lpmm)
100 menu_map * lpmm;
101{
102 Lisp_Object new;
103 int old_size = lpmm->menu_items_allocated;
104
105 lpmm->menu_items_allocated *= 2;
106 new = Fmake_vector (make_number (lpmm->menu_items_allocated), Qnil);
107 bcopy (XVECTOR (lpmm->menu_items)->contents, XVECTOR (new)->contents,
108 old_size * sizeof (Lisp_Object));
109
110 lpmm->menu_items = new;
111}
112
113/* Indicate boundary between left and right. */
114
115static void
116add_left_right_boundary (hmenu)
117 HMENU hmenu;
118{
119 AppendMenu (hmenu, MF_MENUBARBREAK, 0, NULL);
120}
121
122/* Push one menu item into the current pane.
123 NAME is the string to display. ENABLE if non-nil means
124 this item can be selected. KEY is the key generated by
125 choosing this item. EQUIV is the textual description
126 of the keyboard equivalent for this item (or nil if none). */
127
128static void
129add_menu_item (lpmm, hmenu, name, enable, key)
130 menu_map * lpmm;
131 HMENU hmenu;
132 Lisp_Object name;
133 UINT enable;
134 Lisp_Object key;
135{
136 UINT fuFlags;
137
138 if (NILP (name)
139 || ((char *) XSTRING (name)->data)[0] == 0
140 || strcmp ((char *) XSTRING (name)->data, "--") == 0)
141 fuFlags = MF_SEPARATOR;
142 else if (enable)
143 fuFlags = MF_STRING;
144 else
145 fuFlags = MF_STRING | MF_GRAYED;
146
147 AppendMenu (hmenu,
148 fuFlags,
149 lpmm->menu_items_used + 1,
150 (fuFlags == MF_SEPARATOR)?NULL: (char *) XSTRING (name)->data);
151
152 lpmm->menu_items_used++;
153#if 0
154 if (lpmm->menu_items_used >= lpmm->menu_items_allocated)
155 grow_menu_items (lpmm);
156
157 XSET (XVECTOR (lpmm->menu_items)->contents[lpmm->menu_items_used++],
158 Lisp_Cons,
159 key);
160#endif
161}
162
163/* Figure out the current keyboard equivalent of a menu item ITEM1.
164 The item string for menu display should be ITEM_STRING.
165 Store the equivalent keyboard key sequence's
166 textual description into *DESCRIP_PTR.
167 Also cache them in the item itself.
168 Return the real definition to execute. */
169
170static Lisp_Object
171menu_item_equiv_key (item_string, item1, descrip_ptr)
172 Lisp_Object item_string;
173 Lisp_Object item1;
174 Lisp_Object *descrip_ptr;
175{
176 /* This is the real definition--the function to run. */
177 Lisp_Object def;
178 /* This is the sublist that records cached equiv key data
179 so we can save time. */
180 Lisp_Object cachelist;
181 /* These are the saved equivalent keyboard key sequence
182 and its key-description. */
183 Lisp_Object savedkey, descrip;
184 Lisp_Object def1;
185 int changed = 0;
186 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
187
188 /* If a help string follows the item string, skip it. */
189 if (CONSP (XCONS (item1)->cdr)
190 && STRINGP (XCONS (XCONS (item1)->cdr)->car))
191 item1 = XCONS (item1)->cdr;
192
193 def = Fcdr (item1);
194
195 /* Get out the saved equivalent-keyboard-key info. */
196 cachelist = savedkey = descrip = Qnil;
197 if (CONSP (def) && CONSP (XCONS (def)->car)
198 && (NILP (XCONS (XCONS (def)->car)->car)
199 || VECTORP (XCONS (XCONS (def)->car)->car)))
200 {
201 cachelist = XCONS (def)->car;
202 def = XCONS (def)->cdr;
203 savedkey = XCONS (cachelist)->car;
204 descrip = XCONS (cachelist)->cdr;
205 }
206
207 GCPRO4 (def, def1, savedkey, descrip);
208
209 /* Is it still valid? */
210 def1 = Qnil;
211 if (!NILP (savedkey))
212 def1 = Fkey_binding (savedkey, Qnil);
213 /* If not, update it. */
214 if (! EQ (def1, def)
215 /* If the command is an alias for another
216 (such as easymenu.el and lmenu.el set it up),
217 check if the original command matches the cached command. */
218 && !(SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function)
219 && EQ (def1, XSYMBOL (def)->function))
220 /* If something had no key binding before, don't recheck it--
221 doing that takes too much time and makes menus too slow. */
222 && !(!NILP (cachelist) && NILP (savedkey)))
223 {
224 changed = 1;
225 descrip = Qnil;
226 savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil);
227 /* If the command is an alias for another
228 (such as easymenu.el and lmenu.el set it up),
229 see if the original command name has equivalent keys. */
230 if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function))
231 savedkey = Fwhere_is_internal (XSYMBOL (def)->function,
232 Qnil, Qt, Qnil);
233
234 if (VECTORP (savedkey)
235 && EQ (XVECTOR (savedkey)->contents[0], Qmenu_bar))
236 savedkey = Qnil;
237 if (!NILP (savedkey))
238 {
239 descrip = Fkey_description (savedkey);
240 descrip = concat2 (make_string (" (", 3), descrip);
241 descrip = concat2 (descrip, make_string (")", 1));
242 }
243 }
244
245 /* Cache the data we just got in a sublist of the menu binding. */
246 if (NILP (cachelist))
247 XCONS (item1)->cdr = Fcons (Fcons (savedkey, descrip), def);
248 else if (changed)
249 {
250 XCONS (cachelist)->car = savedkey;
251 XCONS (cachelist)->cdr = descrip;
252 }
253
254 UNGCPRO;
255 *descrip_ptr = descrip;
256 return def;
257}
258
259/* This is used as the handler when calling internal_condition_case_1. */
260
261static Lisp_Object
262menu_item_enabled_p_1 (arg)
263 Lisp_Object arg;
264{
265 return Qnil;
266}
267
268/* Return non-nil if the command DEF is enabled when used as a menu item.
269 This is based on looking for a menu-enable property.
270 If NOTREAL is set, don't bother really computing this. */
271
272static Lisp_Object
273menu_item_enabled_p (def, notreal)
274 Lisp_Object def;
275{
276 Lisp_Object enabled, tem;
277
278 enabled = Qt;
279 if (notreal)
280 return enabled;
281 if (XTYPE (def) == Lisp_Symbol)
282 {
283 /* No property, or nil, means enable.
284 Otherwise, enable if value is not nil. */
285 tem = Fget (def, Qmenu_enable);
286 if (!NILP (tem))
287 /* (condition-case nil (eval tem)
288 (error nil)) */
289 enabled = internal_condition_case_1 (Feval, tem, Qerror,
290 menu_item_enabled_p_1);
291 }
292 return enabled;
293}
294
295/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
296 and generate menu panes for them in menu_items.
297 If NOTREAL is nonzero,
298 don't bother really computing whether an item is enabled. */
299
300static HMENU
301keymap_panes (lpmm, keymaps, nmaps, notreal)
302 menu_map * lpmm;
303 Lisp_Object *keymaps;
304 int nmaps;
305 int notreal;
306{
307 int mapno;
308
309 // init_menu_items (lpmm);
310
311 if (nmaps > 1)
312 {
313 HMENU hmenu;
314
315 if (!notreal)
316 {
317 hmenu = CreateMenu ();
318
319 if (!hmenu) return (NULL);
320 }
321 else
322 {
323 hmenu = NULL;
324 }
325
326 /* Loop over the given keymaps, making a pane for each map.
327 But don't make a pane that is empty--ignore that map instead.
328 P is the number of panes we have made so far. */
329 for (mapno = 0; mapno < nmaps; mapno++)
330 {
331 HMENU new_hmenu;
332
333 new_hmenu = single_keymap_panes (lpmm, keymaps[mapno],
334 Qnil, Qnil, notreal);
335
336 if (!notreal && new_hmenu)
337 {
338 AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu, "");
339 }
340 }
341
342 return (hmenu);
343 }
344 else
345 {
346 return (single_keymap_panes (lpmm, keymaps[0], Qnil, Qnil, notreal));
347 }
348}
349
350/* This is a recursive subroutine of keymap_panes.
351 It handles one keymap, KEYMAP.
352 The other arguments are passed along
353 or point to local variables of the previous function.
354 If NOTREAL is nonzero,
355 don't bother really computing whether an item is enabled. */
356
357HMENU
358single_keymap_panes (lpmm, keymap, pane_name, prefix, notreal)
359 menu_map * lpmm;
360 Lisp_Object keymap;
361 Lisp_Object pane_name;
362 Lisp_Object prefix;
363 int notreal;
364{
365 Lisp_Object pending_maps;
366 Lisp_Object tail, item, item1, item_string, table;
367 HMENU hmenu;
368 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
369
370 if (!notreal)
371 {
372 hmenu = CreateMenu ();
373 if (hmenu == NULL) return NULL;
374 }
375 else
376 {
377 hmenu = NULL;
378 }
379
380 pending_maps = Qnil;
381
382 for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr)
383 {
384 /* Look at each key binding, and if it has a menu string,
385 make a menu item from it. */
386
387 item = XCONS (tail)->car;
388
389 if (CONSP (item))
390 {
391 item1 = XCONS (item)->cdr;
392
393 if (XTYPE (item1) == Lisp_Cons)
394 {
395 item_string = XCONS (item1)->car;
396 if (XTYPE (item_string) == Lisp_String)
397 {
398 /* This is the real definition--the function to run. */
399
400 Lisp_Object def;
401
402 /* These are the saved equivalent keyboard key sequence
403 and its key-description. */
404
405 Lisp_Object descrip;
406 Lisp_Object tem, enabled;
407
408 /* GCPRO because ...enabled_p will call eval
409 and ..._equiv_key may autoload something.
410 Protecting KEYMAP preserves everything we use;
411 aside from that, must protect whatever might be
412 a string. Since there's no GCPRO5, we refetch
413 item_string instead of protecting it. */
414
415 descrip = def = Qnil;
416 GCPRO4 (keymap, pending_maps, def, prefix);
417
418 def = menu_item_equiv_key (item_string, item1, &descrip);
419 enabled = menu_item_enabled_p (def, notreal);
420
421 UNGCPRO;
422
423 item_string = XCONS (item1)->car;
424
425 tem = Fkeymapp (def);
426 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
427 {
428 pending_maps = Fcons (Fcons (def,
429 Fcons (item_string,
430 XCONS (item)->car)),
431 pending_maps);
432 }
433 else
434 {
435 Lisp_Object submap;
436
437 GCPRO4 (keymap, pending_maps, item, item_string);
438
439 submap = get_keymap_1 (def, 0, 1);
440
441 UNGCPRO;
442
443 if (NILP (submap))
444 {
445 if (!notreal)
446 {
447 add_menu_item (lpmm,
448 hmenu,
449 item_string,
450 !NILP (enabled),
451 Fcons (XCONS (item)->car, prefix));
452 }
453 }
454 else
455 /* Display a submenu. */
456 {
457 HMENU new_hmenu = single_keymap_panes (lpmm,
458 submap,
459 item_string,
460 XCONS (item)->car,
461 notreal);
462
463 if (!notreal)
464 {
465 AppendMenu (hmenu, MF_POPUP,
466 (UINT)new_hmenu,
467 (char *) XSTRING (item_string)->data);
468 }
469 }
470 }
471 }
472 }
473 }
474 else if (VECTORP (item))
475 {
476 /* Loop over the char values represented in the vector. */
477 int len = XVECTOR (item)->size;
478 int c;
479 for (c = 0; c < len; c++)
480 {
481 Lisp_Object character;
482 XSETFASTINT (character, c);
483 item1 = XVECTOR (item)->contents[c];
484 if (CONSP (item1))
485 {
486 item_string = XCONS (item1)->car;
487 if (STRINGP (item_string))
488 {
489 Lisp_Object def;
490
491 /* These are the saved equivalent keyboard key sequence
492 and its key-description. */
493 Lisp_Object descrip;
494 Lisp_Object tem, enabled;
495
496 /* GCPRO because ...enabled_p will call eval
497 and ..._equiv_key may autoload something.
498 Protecting KEYMAP preserves everything we use;
499 aside from that, must protect whatever might be
500 a string. Since there's no GCPRO5, we refetch
501 item_string instead of protecting it. */
502 GCPRO4 (keymap, pending_maps, def, descrip);
503 descrip = def = Qnil;
504
505 def = menu_item_equiv_key (item_string, item1, &descrip);
506 enabled = menu_item_enabled_p (def, notreal);
507
508 UNGCPRO;
509
510 item_string = XCONS (item1)->car;
511
512 tem = Fkeymapp (def);
513 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
514 pending_maps = Fcons (Fcons (def, Fcons (item_string, character)),
515 pending_maps);
516 else
517 {
518 Lisp_Object submap;
519
520 GCPRO4 (keymap, pending_maps, descrip, item_string);
521
522 submap = get_keymap_1 (def, 0, 1);
523
524 UNGCPRO;
525
526 if (NILP (submap))
527 {
528 if (!notreal)
529 {
530 add_menu_item (lpmm,
531 hmenu,
532 item_string,
533 !NILP (enabled),
534 character);
535 }
536 }
537 else
538 /* Display a submenu. */
539 {
540 HMENU new_hmenu = single_keymap_panes (lpmm,
541 submap,
542 Qnil,
543 character,
544 notreal);
545
546 if (!notreal)
547 {
548 AppendMenu (hmenu,MF_POPUP,
549 (UINT)new_hmenu,
550 (char *)XSTRING (item_string)->data);
551 }
552 }
553 }
554 }
555 }
556 }
557 }
558 }
559
560 /* Process now any submenus which want to be panes at this level. */
561 while (!NILP (pending_maps))
562 {
563 Lisp_Object elt, eltcdr, string;
564 elt = Fcar (pending_maps);
565 eltcdr = XCONS (elt)->cdr;
566 string = XCONS (eltcdr)->car;
567 /* We no longer discard the @ from the beginning of the string here.
568 Instead, we do this in win32menu_show. */
569 {
570 HMENU new_hmenu = single_keymap_panes (lpmm,
571 Fcar (elt),
572 string,
573 XCONS (eltcdr)->cdr, notreal);
574
575 if (!notreal)
576 {
577 AppendMenu (hmenu, MF_POPUP,
578 (UINT)new_hmenu,
579 (char *) XSTRING (string)->data);
580 }
581 }
582
583 pending_maps = Fcdr (pending_maps);
584 }
585
586 return (hmenu);
587}
588
589/* Push all the panes and items of a menu decsribed by the
590 alist-of-alists MENU.
591 This handles old-fashioned calls to x-popup-menu. */
592
593static HMENU
594list_of_panes (lpmm, menu)
595 menu_map * lpmm;
596 Lisp_Object menu;
597{
598 Lisp_Object tail;
599 HMENU hmenu;
600
601 hmenu = CreateMenu ();
602 if (hmenu == NULL) return NULL;
603
604 // init_menu_items (lpmm);
605
606 for (tail = menu; !NILP (tail); tail = Fcdr (tail))
607 {
608 Lisp_Object elt, pane_name, pane_data;
609 HMENU new_hmenu;
610
611 elt = Fcar (tail);
612 pane_name = Fcar (elt);
613 CHECK_STRING (pane_name, 0);
614 pane_data = Fcdr (elt);
615 CHECK_CONS (pane_data, 0);
616
617 new_hmenu = list_of_items (lpmm, pane_data);
618 if (new_hmenu == NULL) goto error;
619
620 AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu,
621 (char *) XSTRING (pane_name)->data);
622 }
623
624 return (hmenu);
625
626 error:
627 DestroyMenu (hmenu);
628
629 return (NULL);
630}
631
632/* Push the items in a single pane defined by the alist PANE. */
633
634static HMENU
635list_of_items (lpmm, pane)
636 menu_map * lpmm;
637 Lisp_Object pane;
638{
639 Lisp_Object tail, item, item1;
640 HMENU hmenu;
641
642 hmenu = CreateMenu ();
643 if (hmenu == NULL) return NULL;
644
645 for (tail = pane; !NILP (tail); tail = Fcdr (tail))
646 {
647 item = Fcar (tail);
648 if (STRINGP (item))
649 add_menu_item (lpmm, hmenu, item, Qnil, Qnil);
650 else if (NILP (item))
651 add_left_right_boundary ();
652 else
653 {
654 CHECK_CONS (item, 0);
655 item1 = Fcar (item);
656 CHECK_STRING (item1, 1);
657 add_menu_item (lpmm, hmenu, item1, Qt, Fcdr (item));
658 }
659 }
660
661 return (hmenu);
662}
663
664
665HMENU
666create_menu_items (lpmm, menu, notreal)
667 menu_map * lpmm;
668 Lisp_Object menu;
669 int notreal;
670{
671 Lisp_Object title;
672 Lisp_Object keymap, tem;
673 HMENU hmenu;
674
675 title = Qnil;
676
677 /* Decode the menu items from what was specified. */
678
679 keymap = Fkeymapp (menu);
680 tem = Qnil;
681 if (XTYPE (menu) == Lisp_Cons)
682 tem = Fkeymapp (Fcar (menu));
683
684 if (!NILP (keymap))
685 {
686 /* We were given a keymap. Extract menu info from the keymap. */
687 Lisp_Object prompt;
688 keymap = get_keymap (menu);
689
690 /* Extract the detailed info to make one pane. */
691 hmenu = keymap_panes (lpmm, &keymap, 1, notreal);
692
693#if 0
694 /* Search for a string appearing directly as an element of the keymap.
695 That string is the title of the menu. */
696 prompt = map_prompt (keymap);
697
698 /* Make that be the pane title of the first pane. */
699 if (!NILP (prompt) && menu_items_n_panes >= 0)
700 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
701#endif
702 }
703 else if (!NILP (tem))
704 {
705 /* We were given a list of keymaps. */
706 int nmaps = XFASTINT (Flength (menu));
707 Lisp_Object *maps
708 = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
709 int i;
710
711 title = Qnil;
712
713 /* The first keymap that has a prompt string
714 supplies the menu title. */
715 for (tem = menu, i = 0; XTYPE (tem) == Lisp_Cons; tem = Fcdr (tem))
716 {
717 Lisp_Object prompt;
718
719 maps[i++] = keymap = get_keymap (Fcar (tem));
720#if 0
721 prompt = map_prompt (keymap);
722 if (NILP (title) && !NILP (prompt))
723 title = prompt;
724#endif
725 }
726
727 /* Extract the detailed info to make one pane. */
728 hmenu = keymap_panes (lpmm, maps, nmaps, notreal);
729
730#if 0
731 /* Make the title be the pane title of the first pane. */
732 if (!NILP (title) && menu_items_n_panes >= 0)
733 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
734#endif
735 }
736 else
737 {
738 /* We were given an old-fashioned menu. */
739 title = Fcar (menu);
740 CHECK_STRING (title, 1);
741
742 hmenu = list_of_panes (lpmm, Fcdr (menu));
743 }
744
745 return (hmenu);
746}
747
748/* This is a recursive subroutine of keymap_panes.
749 It handles one keymap, KEYMAP.
750 The other arguments are passed along
751 or point to local variables of the previous function.
752 If NOTREAL is nonzero,
753 don't bother really computing whether an item is enabled. */
754
755Lisp_Object
756get_single_keymap_event (keymap, lpnum)
757 Lisp_Object keymap;
758 int * lpnum;
759{
760 Lisp_Object pending_maps;
761 Lisp_Object tail, item, item1, item_string, table;
762 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
763
764 pending_maps = Qnil;
765
766 for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr)
767 {
768 /* Look at each key binding, and if it has a menu string,
769 make a menu item from it. */
770
771 item = XCONS (tail)->car;
772
773 if (XTYPE (item) == Lisp_Cons)
774 {
775 item1 = XCONS (item)->cdr;
776
777 if (CONSP (item1))
778 {
779 item_string = XCONS (item1)->car;
780 if (XTYPE (item_string) == Lisp_String)
781 {
782 /* This is the real definition--the function to run. */
783
784 Lisp_Object def;
785
786 /* These are the saved equivalent keyboard key sequence
787 and its key-description. */
788
789 Lisp_Object descrip;
790 Lisp_Object tem, enabled;
791
792 /* GCPRO because ...enabled_p will call eval
793 and ..._equiv_key may autoload something.
794 Protecting KEYMAP preserves everything we use;
795 aside from that, must protect whatever might be
796 a string. Since there's no GCPRO5, we refetch
797 item_string instead of protecting it. */
798
799 descrip = def = Qnil;
800 GCPRO3 (keymap, pending_maps, def);
801
802 def = menu_item_equiv_key (item_string, item1, &descrip);
803
804 UNGCPRO;
805
806 item_string = XCONS (item1)->car;
807
808 tem = Fkeymapp (def);
809 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
810 {
811 pending_maps = Fcons (Fcons (def,
812 Fcons (item_string,
813 XCONS (item)->car)),
814 pending_maps);
815 }
816 else
817 {
818 Lisp_Object submap;
819
820 GCPRO4 (keymap, pending_maps, item, item_string);
821
822 submap = get_keymap_1 (def, 0, 1);
823
824 UNGCPRO;
825
826 if (NILP (submap))
827 {
828 if (--(*lpnum) == 0)
829 {
830 return (Fcons (XCONS (item)->car, Qnil));
831 }
832 }
833 else
834 /* Display a submenu. */
835 {
836 Lisp_Object event = get_single_keymap_event (submap,
837 lpnum);
838
839 if (*lpnum <= 0)
840 {
841 if (!NILP (XCONS (item)->car))
842 event = Fcons (XCONS (item)->car, event);
843
844 return (event);
845 }
846 }
847 }
848 }
849 }
850 }
851 else if (VECTORP (item))
852 {
853 /* Loop over the char values represented in the vector. */
854 int len = XVECTOR (item)->size;
855 int c;
856 for (c = 0; c < len; c++)
857 {
858 Lisp_Object character;
859 XSETFASTINT (character, c);
860 item1 = XVECTOR (item)->contents[c];
861 if (XTYPE (item1) == Lisp_Cons)
862 {
863 item_string = XCONS (item1)->car;
864 if (XTYPE (item_string) == Lisp_String)
865 {
866 Lisp_Object def;
867
868 /* These are the saved equivalent keyboard key sequence
869 and its key-description. */
870 Lisp_Object descrip;
871 Lisp_Object tem, enabled;
872
873 /* GCPRO because ...enabled_p will call eval
874 and ..._equiv_key may autoload something.
875 Protecting KEYMAP preserves everything we use;
876 aside from that, must protect whatever might be
877 a string. Since there's no GCPRO5, we refetch
878 item_string instead of protecting it. */
879 GCPRO4 (keymap, pending_maps, def, descrip);
880 descrip = def = Qnil;
881
882 def = menu_item_equiv_key (item_string, item1, &descrip);
883
884 UNGCPRO;
885
886 item_string = XCONS (item1)->car;
887
888 tem = Fkeymapp (def);
889 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
890 pending_maps = Fcons (Fcons (def, Fcons (item_string, character)),
891 pending_maps);
892 else
893 {
894 Lisp_Object submap;
895
896 GCPRO4 (keymap, pending_maps, descrip, item_string);
897
898 submap = get_keymap_1 (def, 0, 1);
899
900 UNGCPRO;
901
902 if (NILP (submap))
903 {
904 if (--(*lpnum) == 0)
905 {
906 return (Fcons (character, Qnil));
907 }
908 }
909 else
910 /* Display a submenu. */
911 {
912 Lisp_Object event = get_single_keymap_event (submap,
913 lpnum);
914
915 if (*lpnum <= 0)
916 {
917 if (!NILP (character))
918 event = Fcons (character, event);
919
920 return (event);
921 }
922 }
923 }
924 }
925 }
926 }
927 }
928 }
929
930 /* Process now any submenus which want to be panes at this level. */
931 while (!NILP (pending_maps))
932 {
933 Lisp_Object elt, eltcdr, string;
934 elt = Fcar (pending_maps);
935 eltcdr = XCONS (elt)->cdr;
936 string = XCONS (eltcdr)->car;
937 /* We no longer discard the @ from the beginning of the string here.
938 Instead, we do this in win32menu_show. */
939 {
940 Lisp_Object event = get_single_keymap_event (Fcar (elt), lpnum);
941
942 if (*lpnum <= 0)
943 {
944 if (!NILP (XCONS (eltcdr)->cdr))
945 event = Fcons (XCONS (eltcdr)->cdr, event);
946
947 return (event);
948 }
949 }
950
951 pending_maps = Fcdr (pending_maps);
952 }
953
954 return (Qnil);
955}
956
957/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
958 and generate menu panes for them in menu_items.
959 If NOTREAL is nonzero,
960 don't bother really computing whether an item is enabled. */
961
962static Lisp_Object
963get_keymap_event (keymaps, nmaps, lpnum)
964 Lisp_Object *keymaps;
965 int nmaps;
966 int * lpnum;
967{
968 int mapno;
969 Lisp_Object event = Qnil;
970
971 /* Loop over the given keymaps, making a pane for each map.
972 But don't make a pane that is empty--ignore that map instead.
973 P is the number of panes we have made so far. */
974 for (mapno = 0; mapno < nmaps; mapno++)
975 {
976 event = get_single_keymap_event (keymaps[mapno], lpnum);
977
978 if (*lpnum <= 0) break;
979 }
980
981 return (event);
982}
983
984static Lisp_Object
985get_list_of_items_event (pane, lpnum)
986 Lisp_Object pane;
987 int * lpnum;
988{
989 Lisp_Object tail, item, item1;
990
991 for (tail = pane; !NILP (tail); tail = Fcdr (tail))
992 {
993 item = Fcar (tail);
994 if (STRINGP (item))
995 {
996 if (-- (*lpnum) == 0)
997 {
998 return (Qnil);
999 }
1000 }
1001 else if (!NILP (item))
1002 {
1003 if (--(*lpnum) == 0)
1004 {
1005 CHECK_CONS (item, 0);
1006 return (Fcdr (item));
1007 }
1008 }
1009 }
1010
1011 return (Qnil);
1012}
1013
1014/* Push all the panes and items of a menu decsribed by the
1015 alist-of-alists MENU.
1016 This handles old-fashioned calls to x-popup-menu. */
1017
1018static Lisp_Object
1019get_list_of_panes_event (menu, lpnum)
1020 Lisp_Object menu;
1021 int * lpnum;
1022{
1023 Lisp_Object tail;
1024
1025 for (tail = menu; !NILP (tail); tail = Fcdr (tail))
1026 {
1027 Lisp_Object elt, pane_name, pane_data;
1028 Lisp_Object event;
1029
1030 elt = Fcar (tail);
1031 pane_data = Fcdr (elt);
1032 CHECK_CONS (pane_data, 0);
1033
1034 event = get_list_of_items_event (pane_data, lpnum);
1035
1036 if (*lpnum <= 0)
1037 {
1038 return (event);
1039 }
1040 }
1041
1042 return (Qnil);
1043}
1044
1045Lisp_Object
1046get_menu_event (menu, lpnum)
1047 Lisp_Object menu;
1048 int * lpnum;
1049{
1050 Lisp_Object keymap, tem;
1051 Lisp_Object event;
1052
1053 /* Decode the menu items from what was specified. */
1054
1055 keymap = Fkeymapp (menu);
1056 tem = Qnil;
1057 if (XTYPE (menu) == Lisp_Cons)
1058 tem = Fkeymapp (Fcar (menu));
1059
1060 if (!NILP (keymap))
1061 {
1062 keymap = get_keymap (menu);
1063
1064 event = get_keymap_event (menu, 1, lpnum);
1065 }
1066 else if (!NILP (tem))
1067 {
1068 /* We were given a list of keymaps. */
1069 int nmaps = XFASTINT (Flength (menu));
1070 Lisp_Object *maps
1071 = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
1072 int i;
1073
1074 /* The first keymap that has a prompt string
1075 supplies the menu title. */
1076 for (tem = menu, i = 0; XTYPE (tem) == Lisp_Cons; tem = Fcdr (tem))
1077 {
1078 Lisp_Object prompt;
1079
1080 maps[i++] = keymap = get_keymap (Fcar (tem));
1081 }
1082
1083 event = get_keymap_event (maps, nmaps, lpnum);
1084 }
1085 else
1086 {
1087 /* We were given an old-fashioned menu. */
1088 event = get_list_of_panes_event (Fcdr (menu), lpnum);
1089 }
1090
1091 return (event);
1092}
1093
1094DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
1095 "Pop up a deck-of-cards menu and return user's selection.\n\
1096POSITION is a position specification. This is either a mouse button event\n\
1097or a list ((XOFFSET YOFFSET) WINDOW)\n\
1098where XOFFSET and YOFFSET are positions in pixels from the top left\n\
1099corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
1100This controls the position of the center of the first line\n\
1101in the first pane of the menu, not the top left of the menu as a whole.\n\
1102If POSITION is t, it means to use the current mouse position.\n\
1103\n\
1104MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
1105The menu items come from key bindings that have a menu string as well as\n\
1106a definition; actually, the \"definition\" in such a key binding looks like\n\
1107\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
1108the keymap as a top-level element.\n\n\
1109You can also use a list of keymaps as MENU.\n\
1110 Then each keymap makes a separate pane.\n\
1111When MENU is a keymap or a list of keymaps, the return value\n\
1112is a list of events.\n\n\
1113Alternatively, you can specify a menu of multiple panes\n\
1114 with a list of the form (TITLE PANE1 PANE2...),\n\
1115where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
1116Each ITEM is normally a cons cell (STRING . VALUE);\n\
1117but a string can appear as an item--that makes a nonselectable line\n\
1118in the menu.\n\
1119With this form of menu, the return value is VALUE from the chosen item.\n\
1120\n\
1121If POSITION is nil, don't display the menu at all, just precalculate the\n\
1122cached information about equivalent key sequences.")
1123 (position, menu)
1124 Lisp_Object position, menu;
1125{
1126 int number_of_panes, panes;
1127 Lisp_Object keymap, tem;
1128 int xpos, ypos;
1129 Lisp_Object title;
1130 char *error_name;
1131 Lisp_Object selection;
1132 int i, j;
1133 FRAME_PTR f;
1134 Lisp_Object x, y, window;
1135 int keymaps = 0;
1136 int menubarp = 0;
1137 struct gcpro gcpro1;
1138 HMENU hmenu;
1139 menu_map mm;
1140
1141 if (! NILP (position))
1142 {
1143 /* Decode the first argument: find the window and the coordinates. */
1144 if (EQ (position, Qt))
1145 {
1146 /* Use the mouse's current position. */
1147 FRAME_PTR new_f = 0;
1148 Lisp_Object bar_window;
1149 int part;
1150 unsigned long time;
1151
1152 if (mouse_position_hook)
1153 (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
1154 if (new_f != 0)
1155 XSETFRAME (window, new_f);
1156 else
1157 {
1158 window = selected_window;
1159 XSETFASTINT (x, 0);
1160 XSETFASTINT (y, 0);
1161 }
1162 }
1163 else
1164 {
1165 tem = Fcar (position);
1166 if (CONSP (tem))
1167 {
1168 window = Fcar (Fcdr (position));
1169 x = Fcar (tem);
1170 y = Fcar (Fcdr (tem));
1171 }
1172 else
1173 {
1174 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
1175 window = Fcar (tem); /* POSN_WINDOW (tem) */
1176 tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
1177 x = Fcar (tem);
1178 y = Fcdr (tem);
1179
1180 /* Determine whether this menu is handling a menu bar click. */
1181 tem = Fcar (Fcdr (Fcar (Fcdr (position))));
1182 if (CONSP (tem) && EQ (Fcar (tem), Qmenu_bar))
1183 menubarp = 1;
1184 }
1185 }
1186
1187 CHECK_NUMBER (x, 0);
1188 CHECK_NUMBER (y, 0);
1189
1190 /* Decode where to put the menu. */
1191
1192 if (FRAMEP (window))
1193 {
1194 f = XFRAME (window);
1195
1196 xpos = 0;
1197 ypos = 0;
1198 }
1199 else if (WINDOWP (window))
1200 {
1201 CHECK_LIVE_WINDOW (window, 0);
1202 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1203
1204 xpos = (FONT_WIDTH (f->output_data.win32->font) * XWINDOW (window)->left);
1205 ypos = (f->output_data.win32->line_height * XWINDOW (window)->top);
1206 }
1207 else
1208 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
1209 but I don't want to make one now. */
1210 CHECK_WINDOW (window, 0);
1211
1212 xpos += XINT (x);
1213 ypos += XINT (y);
1214 }
1215
1216 title = Qnil;
1217 GCPRO1 (title);
1218
1219 discard_menu_items (&mm);
1220 hmenu = create_menu_items (&mm, menu, NILP (position));
1221
1222 if (NILP (position))
1223 {
1224 discard_menu_items (&mm);
1225 UNGCPRO;
1226 return Qnil;
1227 }
1228
1229 /* Display them in a menu. */
1230 BLOCK_INPUT;
1231
1232 selection = win32menu_show (f, xpos, ypos, menu, &hmenu, &error_name);
1233
1234 UNBLOCK_INPUT;
1235
1236 discard_menu_items (&mm);
1237 DestroyMenu (hmenu);
1238
1239 UNGCPRO;
1240
1241 if (error_name) error (error_name);
1242 return selection;
1243}
1244
1245DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
1246 "Pop up a dialog box and return user's selection.\n\
1247POSITION specifies which frame to use.\n\
1248This is normally a mouse button event or a window or frame.\n\
1249If POSITION is t, it means to use the frame the mouse is on.\n\
1250The dialog box appears in the middle of the specified frame.\n\
1251\n\
1252CONTENTS specifies the alternatives to display in the dialog box.\n\
1253It is a list of the form (TITLE ITEM1 ITEM2...).\n\
1254Each ITEM is a cons cell (STRING . VALUE).\n\
1255The return value is VALUE from the chosen item.\n\n\
1256An ITEM may also be just a string--that makes a nonselectable item.\n\
1257An ITEM may also be nil--that means to put all preceding items\n\
1258on the left of the dialog box and all following items on the right.\n\
1259\(By default, approximately half appear on each side.)")
1260 (position, contents)
1261 Lisp_Object position, contents;
1262{
1263 FRAME_PTR f;
1264 Lisp_Object window;
1265
1266 /* Decode the first argument: find the window or frame to use. */
1267 if (EQ (position, Qt))
1268 {
1269 /* Decode the first argument: find the window and the coordinates. */
1270 if (EQ (position, Qt))
1271 window = selected_window;
1272 }
1273 else if (CONSP (position))
1274 {
1275 Lisp_Object tem;
1276 tem = Fcar (position);
1277 if (XTYPE (tem) == Lisp_Cons)
1278 window = Fcar (Fcdr (position));
1279 else
1280 {
1281 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
1282 window = Fcar (tem); /* POSN_WINDOW (tem) */
1283 }
1284 }
1285 else if (WINDOWP (position) || FRAMEP (position))
1286 window = position;
1287
1288 /* Decode where to put the menu. */
1289
1290 if (FRAMEP (window))
1291 f = XFRAME (window);
1292 else if (WINDOWP (window))
1293 {
1294 CHECK_LIVE_WINDOW (window, 0);
1295 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1296 }
1297 else
1298 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
1299 but I don't want to make one now. */
1300 CHECK_WINDOW (window, 0);
1301
1302#if 1
1303 /* Display a menu with these alternatives
1304 in the middle of frame F. */
1305 {
1306 Lisp_Object x, y, frame, newpos;
1307 XSETFRAME (frame, f);
1308 XSETINT (x, x_pixel_width (f) / 2);
1309 XSETINT (y, x_pixel_height (f) / 2);
1310 newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
1311
1312 return Fx_popup_menu (newpos,
1313 Fcons (Fcar (contents), Fcons (contents, Qnil)));
1314 }
1315#else
1316 {
1317 Lisp_Object title;
1318 char *error_name;
1319 Lisp_Object selection;
1320
1321 /* Decode the dialog items from what was specified. */
1322 title = Fcar (contents);
1323 CHECK_STRING (title, 1);
1324
1325 list_of_panes (Fcons (contents, Qnil));
1326
1327 /* Display them in a dialog box. */
1328 BLOCK_INPUT;
1329 selection = win32_dialog_show (f, 0, 0, title, &error_name);
1330 UNBLOCK_INPUT;
1331
1332 discard_menu_items ();
1333
1334 if (error_name) error (error_name);
1335 return selection;
1336 }
1337#endif
1338}
1339
1340Lisp_Object
1341get_frame_menubar_event (f, num)
1342 FRAME_PTR f;
1343 int num;
1344{
1345 Lisp_Object tail, items;
1346 int i;
1347 struct gcpro gcpro1;
1348
1349 BLOCK_INPUT;
1350
1351 GCPRO1 (items);
1352
1353 if (NILP (items = FRAME_MENU_BAR_ITEMS (f)))
1354 items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1355
1356 for (i = 0; i < XVECTOR (items)->size; i += 3)
1357 {
1358 Lisp_Object event;
1359
1360 event = get_menu_event (XVECTOR (items)->contents[i + 2], &num);
1361
1362 if (num <= 0)
1363 {
1364 UNGCPRO;
1365 UNBLOCK_INPUT;
1366 return (Fcons (XVECTOR (items)->contents[i], event));
1367 }
1368 }
1369
1370 UNGCPRO;
1371 UNBLOCK_INPUT;
1372
1373 return (Qnil);
1374}
1375
1376void
1377set_frame_menubar (f, first_time)
1378 FRAME_PTR f;
1379 int first_time;
1380{
1381 Lisp_Object tail, items;
1382 HMENU hmenu;
1383 int i;
1384 struct gcpro gcpro1;
1385 menu_map mm;
1386
1387 BLOCK_INPUT;
1388
1389 GCPRO1 (items);
1390
1391 if (NILP (items = FRAME_MENU_BAR_ITEMS (f)))
1392 items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1393
1394 hmenu = CreateMenu ();
1395
1396 if (!hmenu) goto error;
1397
1398 discard_menu_items (&mm);
1399
1400 for (i = 0; i < XVECTOR (items)->size; i += 3)
1401 {
1402 Lisp_Object string;
1403 int keymaps;
1404 CHAR *error;
1405 HMENU new_hmenu;
1406
1407 string = XVECTOR (items)->contents[i + 1];
1408 if (NILP (string))
1409 break;
1410
1411 new_hmenu = create_menu_items (&mm,
1412 XVECTOR (items)->contents[i + 2],
1413 0);
1414
1415 if (!new_hmenu)
1416 continue;
1417
1418 AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu,
1419 (char *) XSTRING (string)->data);
1420 }
1421
1422 {
1423 HMENU old = GetMenu (FRAME_WIN32_WINDOW (f));
1424 SetMenu (FRAME_WIN32_WINDOW (f), hmenu);
1425 DestroyMenu (old);
1426 }
1427
1428 error:
1429 UNGCPRO;
1430 UNBLOCK_INPUT;
1431}
1432
1433void
1434free_frame_menubar (f)
1435 FRAME_PTR f;
1436{
1437 BLOCK_INPUT;
1438
1439 {
1440 HMENU old = GetMenu (FRAME_WIN32_WINDOW (f));
1441 SetMenu (FRAME_WIN32_WINDOW (f), NULL);
1442 DestroyMenu (old);
1443 }
1444
1445 UNBLOCK_INPUT;
1446}
1447/* Called from Fwin32_create_frame to create the inital menubar of a frame
1448 before it is mapped, so that the window is mapped with the menubar already
1449 there instead of us tacking it on later and thrashing the window after it
1450 is visible. */
1451void
1452initialize_frame_menubar (f)
1453 FRAME_PTR f;
1454{
1455 set_frame_menubar (f, 1);
1456}
1457
1458#if 0
1459/* If the mouse has moved to another menu bar item,
1460 return 1 and unread a button press event for that item.
1461 Otherwise return 0. */
1462
1463static int
1464check_mouse_other_menu_bar (f)
1465 FRAME_PTR f;
1466{
1467 FRAME_PTR new_f;
1468 Lisp_Object bar_window;
1469 int part;
1470 Lisp_Object x, y;
1471 unsigned long time;
1472
1473 (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
1474
1475 if (f == new_f && other_menu_bar_item_p (f, x, y))
1476 {
1477 unread_menu_bar_button (f, x);
1478 return 1;
1479 }
1480
1481 return 0;
1482}
1483#endif
1484
1485
1486#if 0
1487static HMENU
1488create_menu (keymaps, error)
1489 int keymaps;
1490 char **error;
1491{
1492 HMENU hmenu = NULL; /* the menu we are currently working on */
1493 HMENU first_hmenu = NULL;
1494
1495 HMENU *submenu_stack = (HMENU *) alloca (menu_items_used * sizeof (HMENU));
1496 Lisp_Object *subprefix_stack = (Lisp_Object *) alloca (menu_items_used *
1497 sizeof (Lisp_Object));
1498 int submenu_depth = 0;
1499 int i;
1500
1501 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
1502 {
1503 *error = "Empty menu";
1504 return NULL;
1505 }
1506
1507 i = 0;
1508
1509 /* Loop over all panes and items, filling in the tree. */
1510
1511 while (i < menu_items_used)
1512 {
1513 if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
1514 {
1515 submenu_stack[submenu_depth++] = hmenu;
1516 i++;
1517 }
1518 else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
1519 {
1520 hmenu = submenu_stack[--submenu_depth];
1521 i++;
1522 }
1523#if 0
1524else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
1525 && submenu_depth != 0)
1526 i += MENU_ITEMS_PANE_LENGTH;
1527#endif
1528 /* Ignore a nil in the item list.
1529 It's meaningful only for dialog boxes. */
1530else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
1531 i += 1;
1532else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
1533 {
1534 /* Create a new pane. */
1535
1536 Lisp_Object pane_name;
1537 char *pane_string;
1538
1539 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
1540 pane_string = (NILP (pane_name) ? "" : (char *) XSTRING (pane_name)->data);
1541
1542 if (!hmenu || strcmp (pane_string, ""))
1543 {
1544 HMENU new_hmenu = CreateMenu ();
1545
1546 if (!new_hmenu)
1547 {
1548 *error = "Could not create menu pane";
1549 goto error;
1550 }
1551
1552 if (hmenu)
1553 {
1554 AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu, pane_string);
1555 }
1556
1557 hmenu = new_hmenu;
1558
1559 if (!first_hmenu) first_hmenu = hmenu;
1560 }
1561 i += MENU_ITEMS_PANE_LENGTH;
1562 }
1563else
1564 {
1565 /* Create a new item within current pane. */
1566
1567 Lisp_Object item_name, enable, descrip;
1568 UINT fuFlags;
1569
1570 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
1571 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
1572 // descrip = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
1573
1574 if (((char *) XSTRING (item_name)->data)[0] == 0
1575 || strcmp ((char *) XSTRING (item_name)->data, "--") == 0)
1576 fuFlags = MF_SEPARATOR;
1577 else if (NILP (enable) || !XUINT(enable))
1578 fuFlags = MF_STRING | MF_GRAYED;
1579 else
1580 fuFlags = MF_STRING;
1581
1582 AppendMenu (hmenu,
1583 fuFlags,
1584 i,
1585 (char *) XSTRING (item_name)->data);
1586
1587 // if (!NILP (descrip))
1588 // hmenu->key = (char *) XSTRING (descrip)->data;
1589
1590 i += MENU_ITEMS_ITEM_LENGTH;
1591 }
1592}
1593
1594 return (first_hmenu);
1595
1596 error:
1597 if (first_hmenu) DestroyMenu (first_hmenu);
1598 return (NULL);
1599}
1600
1601#endif
1602
1603/* win32menu_show actually displays a menu using the panes and items in
1604 menu_items and returns the value selected from it.
1605 There are two versions of win32menu_show, one for Xt and one for Xlib.
1606 Both assume input is blocked by the caller. */
1607
1608/* F is the frame the menu is for.
1609 X and Y are the frame-relative specified position,
1610 relative to the inside upper left corner of the frame F.
1611 MENUBARP is 1 if the click that asked for this menu came from the menu bar.
1612 KEYMAPS is 1 if this menu was specified with keymaps;
1613 in that case, we return a list containing the chosen item's value
1614 and perhaps also the pane's prefix.
1615 TITLE is the specified menu title.
1616 ERROR is a place to store an error message string in case of failure.
1617 (We return nil on failure, but the value doesn't actually matter.) */
1618
1619
1620static Lisp_Object
1621win32menu_show (f, x, y, menu, hmenu, error)
1622 FRAME_PTR f;
1623 int x;
1624 int y;
1625 Lisp_Object menu;
1626 HMENU hmenu;
1627 char **error;
1628{
1629 int i , menu_selection;
1630 POINT pos;
1631
1632 *error = NULL;
1633
1634 if (!hmenu)
1635 {
1636 *error = "Empty menu";
1637 return Qnil;
1638 }
1639
1640 pos.x = x;
1641 pos.y = y;
1642
1643 /* Offset the coordinates to root-relative. */
1644 ClientToScreen (FRAME_WIN32_WINDOW (f), &pos);
1645
1646#if 0
1647 /* If the mouse moves out of the menu before we show the menu,
1648 don't show it at all. */
1649 if (check_mouse_other_menu_bar (f))
1650 {
1651 DestroyMenu (hmenu);
1652 return Qnil;
1653 }
1654#endif
1655
1656 /* Display the menu. */
1657 menu_selection = TrackPopupMenu (hmenu,
1658 0x10,
1659 pos.x, pos.y,
1660 0,
1661 FRAME_WIN32_WINDOW (f),
1662 NULL);
1663 if (menu_selection == -1)
1664 {
1665 *error = "Invalid menu specification";
1666 return Qnil;
1667 }
1668
1669 /* Find the selected item, and its pane, to return
1670 the proper value. */
1671
1672#if 1
1673 if (menu_selection > 0)
1674 {
1675 return get_menu_event (menu, menu_selection);
1676 }
1677#else
1678 if (menu_selection > 0 && menu_selection <= lpmm->menu_items_used)
1679 {
1680 return (XVECTOR (lpmm->menu_items)->contents[menu_selection - 1]);
1681 }
1682#endif
1683
1684 return Qnil;
1685}
1686
1687#if 0
1688static char * button_names [] =
1689{
1690 "button1", "button2", "button3", "button4", "button5",
1691 "button6", "button7", "button8", "button9", "button10"
1692};
1693
1694static Lisp_Object
1695win32_dialog_show (f, menubarp, keymaps, title, error)
1696 FRAME_PTR f;
1697 int menubarp;
1698 int keymaps;
1699 Lisp_Object title;
1700 char **error;
1701{
1702 int i, nb_buttons=0;
1703 HMENU hmenu;
1704 char dialog_name[6];
1705
1706 /* Number of elements seen so far, before boundary. */
1707 int left_count = 0;
1708 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
1709 int boundary_seen = 0;
1710
1711 *error = NULL;
1712
1713 if (menu_items_n_panes > 1)
1714 {
1715 *error = "Multiple panes in dialog box";
1716 return Qnil;
1717 }
1718
1719 /* Create a tree of widget_value objects
1720 representing the text label and buttons. */
1721 {
1722 Lisp_Object pane_name, prefix;
1723 char *pane_string;
1724 pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
1725 prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
1726 pane_string = (NILP (pane_name)
1727 ? "" : (char *) XSTRING (pane_name)->data);
1728 prev_wv = malloc_widget_value ();
1729 prev_wv->value = pane_string;
1730 if (keymaps && !NILP (prefix))
1731 prev_wv->name++;
1732 prev_wv->enabled = 1;
1733 prev_wv->name = "message";
1734 first_wv = prev_wv;
1735
1736 /* Loop over all panes and items, filling in the tree. */
1737 i = MENU_ITEMS_PANE_LENGTH;
1738 while (i < menu_items_used)
1739 {
1740
1741 /* Create a new item within current pane. */
1742 Lisp_Object item_name, enable, descrip;
1743 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
1744 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
1745 descrip
1746 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
1747
1748 if (NILP (item_name))
1749 {
1750 free_menubar_widget_value_tree (first_wv);
1751 *error = "Submenu in dialog items";
1752 return Qnil;
1753 }
1754 if (EQ (item_name, Qquote))
1755 {
1756 /* This is the boundary between left-side elts
1757 and right-side elts. Stop incrementing right_count. */
1758 boundary_seen = 1;
1759 i++;
1760 continue;
1761 }
1762 if (nb_buttons >= 10)
1763 {
1764 free_menubar_widget_value_tree (first_wv);
1765 *error = "Too many dialog items";
1766 return Qnil;
1767 }
1768
1769 wv = malloc_widget_value ();
1770 prev_wv->next = wv;
1771 wv->name = (char *) button_names[nb_buttons];
1772 if (!NILP (descrip))
1773 wv->key = (char *) XSTRING (descrip)->data;
1774 wv->value = (char *) XSTRING (item_name)->data;
1775 wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
1776 wv->enabled = !NILP (enable);
1777 prev_wv = wv;
1778
1779 if (! boundary_seen)
1780 left_count++;
1781
1782 nb_buttons++;
1783 i += MENU_ITEMS_ITEM_LENGTH;
1784 }
1785
1786 /* If the boundary was not specified,
1787 by default put half on the left and half on the right. */
1788 if (! boundary_seen)
1789 left_count = nb_buttons - nb_buttons / 2;
1790
1791 wv = malloc_widget_value ();
1792 wv->name = dialog_name;
1793
1794 /* Dialog boxes use a really stupid name encoding
1795 which specifies how many buttons to use
1796 and how many buttons are on the right.
1797 The Q means something also. */
1798 dialog_name[0] = 'Q';
1799 dialog_name[1] = '0' + nb_buttons;
1800 dialog_name[2] = 'B';
1801 dialog_name[3] = 'R';
1802 /* Number of buttons to put on the right. */
1803 dialog_name[4] = '0' + nb_buttons - left_count;
1804 dialog_name[5] = 0;
1805 wv->contents = first_wv;
1806 first_wv = wv;
1807 }
1808
1809 /* Actually create the dialog. */
1810 dialog_id = ++popup_id_tick;
1811 menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
1812 f->output_data.win32->widget, 1, 0,
1813 dialog_selection_callback, 0);
1814#if 0 /* This causes crashes, and seems to be redundant -- rms. */
1815 lw_modify_all_widgets (dialog_id, first_wv, True);
1816#endif
1817 lw_modify_all_widgets (dialog_id, first_wv->contents, True);
1818 /* Free the widget_value objects we used to specify the contents. */
1819 free_menubar_widget_value_tree (first_wv);
1820
1821 /* No selection has been chosen yet. */
1822 menu_item_selection = 0;
1823
1824 /* Display the menu. */
1825 lw_pop_up_all_widgets (dialog_id);
1826
1827 /* Process events that apply to the menu. */
1828 while (1)
1829 {
1830 XEvent event;
1831
1832 XtAppNextEvent (Xt_app_con, &event);
1833 if (event.type == ButtonRelease)
1834 {
1835 XtDispatchEvent (&event);
1836 break;
1837 }
1838 else if (event.type == Expose)
1839 process_expose_from_menu (event);
1840 XtDispatchEvent (&event);
1841 if (XtWindowToWidget(XDISPLAY event.xany.window) != menu)
1842 {
1843 queue_tmp = (struct event_queue *) malloc (sizeof (struct event_queue));
1844
1845 if (queue_tmp != NULL)
1846 {
1847 queue_tmp->event = event;
1848 queue_tmp->next = queue;
1849 queue = queue_tmp;
1850 }
1851 }
1852 }
1853 pop_down:
1854
1855 /* State that no mouse buttons are now held.
1856 That is not necessarily true, but the fiction leads to reasonable
1857 results, and it is a pain to ask which are actually held now
1858 or track this in the loop above. */
1859 win32_mouse_grabbed = 0;
1860
1861 /* Unread any events that we got but did not handle. */
1862 while (queue != NULL)
1863 {
1864 queue_tmp = queue;
1865 XPutBackEvent (XDISPLAY &queue_tmp->event);
1866 queue = queue_tmp->next;
1867 free ((char *)queue_tmp);
1868 /* Cause these events to get read as soon as we UNBLOCK_INPUT. */
1869 interrupt_input_pending = 1;
1870 }
1871
1872 /* Find the selected item, and its pane, to return
1873 the proper value. */
1874 if (menu_item_selection != 0)
1875 {
1876 Lisp_Object prefix;
1877
1878 prefix = Qnil;
1879 i = 0;
1880 while (i < menu_items_used)
1881 {
1882 Lisp_Object entry;
1883
1884 if (EQ (XVECTOR (menu_items)->contents[i], Qt))
1885 {
1886 prefix
1887 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1888 i += MENU_ITEMS_PANE_LENGTH;
1889 }
1890 else
1891 {
1892 entry
1893 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
1894 if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
1895 {
1896 if (keymaps != 0)
1897 {
1898 entry = Fcons (entry, Qnil);
1899 if (!NILP (prefix))
1900 entry = Fcons (prefix, entry);
1901 }
1902 return entry;
1903 }
1904 i += MENU_ITEMS_ITEM_LENGTH;
1905 }
1906 }
1907 }
1908
1909 return Qnil;
1910}
1911#endif
1912
1913syms_of_win32menu ()
1914{
1915 defsubr (&Sx_popup_menu);
1916 defsubr (&Sx_popup_dialog);
1917}
diff --git a/src/w32reg.c b/src/w32reg.c
new file mode 100644
index 00000000000..2b6fbb8acc3
--- /dev/null
+++ b/src/w32reg.c
@@ -0,0 +1,94 @@
1/* Emulate the X Resource Manager through the registry.
2 Copyright (C) 1990, 1993, 1994 Free Software Foundation.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2, or (at your option)
7any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; see the file COPYING. If not, write to
16the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18/* Written by Kevin Gallo */
19
20#include <config.h>
21#include "lisp.h"
22#include "w32term.h"
23#include "blockinput.h"
24
25#include <stdio.h>
26#include <string.h>
27
28#define REG_ROOT "SOFTWARE\\GNU\\Emacs\\"
29
30LPBYTE
31win32_get_string_resource (name, class, dwexptype)
32 char *name, *class;
33 DWORD dwexptype;
34{
35 LPBYTE lpvalue = NULL;
36 HKEY hrootkey = NULL;
37 DWORD dwType;
38 DWORD cbData;
39 BOOL ok = FALSE;
40
41 BLOCK_INPUT;
42
43 /* Check both the current user and the local machine to see if we have any resources */
44
45 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS
46 || RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
47 {
48 char *keyname;
49
50 if (RegQueryValueEx (hrootkey, name, NULL, &dwType, NULL, &cbData) == ERROR_SUCCESS
51 && dwType == dwexptype)
52 {
53 keyname = name;
54 }
55 else if (RegQueryValueEx (hrootkey, class, NULL, &dwType, NULL, &cbData) == ERROR_SUCCESS
56 && dwType == dwexptype)
57 {
58 keyname = class;
59 }
60 else
61 {
62 keyname = NULL;
63 }
64
65 ok = (keyname
66 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
67 && RegQueryValueEx (hrootkey, keyname, NULL, NULL, lpvalue, &cbData) == ERROR_SUCCESS);
68
69 RegCloseKey (hrootkey);
70 }
71
72 UNBLOCK_INPUT;
73
74 if (!ok)
75 {
76 if (lpvalue) xfree (lpvalue);
77 return (NULL);
78 }
79 else
80 {
81 return (lpvalue);
82 }
83}
84
85/* Retrieve the string resource specified by NAME with CLASS from
86 database RDB. */
87
88char *
89x_get_string_resource (rdb, name, class)
90 int rdb;
91 char *name, *class;
92{
93 return (win32_get_string_resource (name, class, REG_SZ));
94}
diff --git a/src/w32select.c b/src/w32select.c
new file mode 100644
index 00000000000..54201417337
--- /dev/null
+++ b/src/w32select.c
@@ -0,0 +1,226 @@
1/* Win32 Selection processing for emacs
2 Copyright (C) 1993, 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* Written by Kevin Gallo */
21
22#include <config.h>
23#include "lisp.h"
24#include "w32term.h" /* for all of the win32 includes */
25#include "dispextern.h" /* frame.h seems to want this */
26#include "frame.h" /* Need this to get the X window of selected_frame */
27#include "blockinput.h"
28
29#if 0
30DEFUN ("win32-open-clipboard", Fwin32_open_clipboard, Swin32_open_clipboard, 0, 1, 0,
31 "This opens the clipboard with the given frame pointer.")
32 (frame)
33 Lisp_Object frame;
34{
35 BOOL ok = FALSE;
36
37 if (!NILP (frame))
38 CHECK_LIVE_FRAME (frame, 0);
39
40 BLOCK_INPUT;
41
42 ok = OpenClipboard ((!NILP (frame) && FRAME_WIN32_P (XFRAME (frame))) ? FRAME_WIN32_WINDOW (XFRAME (frame)) : NULL);
43
44 UNBLOCK_INPUT;
45
46 return (ok ? frame : Qnil);
47}
48
49DEFUN ("win32-empty-clipboard", Fwin32_empty_clipboard, Swin32_empty_clipboard, 0, 0, 0,
50 "This empties the clipboard and assigns ownership to the window which opened the clipboard.")
51 ()
52{
53 BOOL ok = FALSE;
54
55 BLOCK_INPUT;
56
57 ok = EmptyClipboard ();
58
59 UNBLOCK_INPUT;
60
61 return (ok ? Qt : Qnil);
62}
63
64DEFUN ("win32-close-clipboard", Fwin32_close_clipboard, Swin32_close_clipboard, 0, 0, 0,
65 "This closes the clipboard.")
66 ()
67{
68 BOOL ok = FALSE;
69
70 BLOCK_INPUT;
71
72 ok = CloseClipboard ();
73
74 UNBLOCK_INPUT;
75
76 return (ok ? Qt : Qnil);
77}
78
79#endif
80
81DEFUN ("win32-set-clipboard-data", Fwin32_set_clipboard_data, Swin32_set_clipboard_data, 1, 2, 0,
82 "This sets the clipboard data to the given text.")
83 (string, frame)
84 Lisp_Object string, frame;
85{
86 BOOL ok = TRUE;
87 HANDLE htext;
88
89 CHECK_STRING (string, 0);
90
91 if (!NILP (frame))
92 CHECK_LIVE_FRAME (frame, 0);
93
94 BLOCK_INPUT;
95
96 /* Allocate twice the amount so we can convert lf to cr-lf */
97
98 if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, (2 * XSTRING (string)->size) + 1)) == NULL)
99 goto error;
100
101 {
102 unsigned char *lptext;
103
104 if ((lptext = (unsigned char *)GlobalLock (htext)) == NULL)
105 goto error;
106
107 {
108 int i = XSTRING (string)->size;
109 int newsize = XSTRING (string)->size;
110 register char *p1 = XSTRING (string)->data;
111 register char *p2 = lptext;
112
113 while (i--)
114 {
115 if (*p1 == '\n')
116 {
117 newsize++;
118 *p2++ = '\r';
119 }
120
121 *p2++ = *p1++;
122 }
123
124 *p2 = 0;
125 }
126
127 GlobalUnlock (htext);
128 }
129
130 if (!OpenClipboard ((!NILP (frame) && FRAME_WIN32_P (XFRAME (frame))) ? FRAME_WIN32_WINDOW (XFRAME (frame)) : NULL))
131 goto error;
132
133 ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext);
134
135 CloseClipboard ();
136
137 if (ok) goto done;
138
139 error:
140
141 ok = FALSE;
142 if (htext) GlobalFree (htext);
143
144 done:
145 UNBLOCK_INPUT;
146
147 return (ok ? string : Qnil);
148}
149
150DEFUN ("win32-get-clipboard-data", Fwin32_get_clipboard_data, Swin32_get_clipboard_data, 0, 1, 0,
151 "This gets the clipboard data in text format.")
152 (frame)
153 Lisp_Object frame;
154{
155 HANDLE htext;
156 Lisp_Object ret = Qnil;
157
158 if (!NILP (frame))
159 CHECK_LIVE_FRAME (frame, 0);
160
161 BLOCK_INPUT;
162
163 if (!OpenClipboard ((!NILP (frame) && FRAME_WIN32_P (XFRAME (frame))) ? FRAME_WIN32_WINDOW (XFRAME (frame)) : NULL))
164 goto done;
165
166 if ((htext = GetClipboardData (CF_TEXT)) == NULL)
167 goto closeclip;
168
169
170 {
171 unsigned char *lptext;
172 int nbytes;
173
174 if ((lptext = (unsigned char *)GlobalLock (htext)) == NULL)
175 goto closeclip;
176
177 nbytes = strlen (lptext);
178
179 {
180 char *buf = (char *) xmalloc (nbytes);
181 register char *p1 = lptext;
182 register char *p2 = buf;
183 int i = nbytes;
184
185 if (buf == NULL) goto closeclip;
186
187 while (i--)
188 {
189 if (p1[0] == '\r' && i && p1[1] == '\n')
190 {
191 p1++;
192 i--;
193 nbytes--;
194 }
195
196 *p2++ = *p1++;
197 }
198
199 ret = make_string (buf, nbytes);
200
201 xfree (buf);
202 }
203
204 GlobalUnlock (htext);
205 }
206
207 closeclip:
208 CloseClipboard ();
209
210 done:
211 UNBLOCK_INPUT;
212
213 return (ret);
214}
215
216void
217syms_of_win32select ()
218{
219#if 0
220 defsubr (&Swin32_open_clipboard);
221 defsubr (&Swin32_empty_clipboard);
222 defsubr (&Swin32_close_clipboard);
223#endif
224 defsubr (&Swin32_set_clipboard_data);
225 defsubr (&Swin32_get_clipboard_data);
226}
diff --git a/src/w32term.c b/src/w32term.c
new file mode 100644
index 00000000000..c864d180b62
--- /dev/null
+++ b/src/w32term.c
@@ -0,0 +1,3711 @@
1/* Implementation of Win32 GUI terminal
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* Added by Kevin Gallo */
21
22#include <signal.h>
23#include <config.h>
24#include <stdio.h>
25#include "lisp.h"
26#include "blockinput.h"
27
28#include <w32term.h>
29
30#include "systty.h"
31#include "systime.h"
32
33#include <ctype.h>
34#include <errno.h>
35#include <setjmp.h>
36#include <sys/stat.h>
37
38#include "frame.h"
39#include "dispextern.h"
40#include "termhooks.h"
41#include "termopts.h"
42#include "termchar.h"
43#include "gnu.h"
44#include "disptab.h"
45#include "buffer.h"
46#include "window.h"
47#include "keyboard.h"
48#include "intervals.h"
49
50extern void free_frame_menubar ();
51
52#define x_any_window_to_frame x_window_to_frame
53#define x_top_window_to_frame x_window_to_frame
54
55
56/* This is display since win32 does not support multiple ones. */
57struct win32_display_info one_win32_display_info;
58
59/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
60 one for each element of win32_display_list and in the same order.
61 NAME is the name of the frame.
62 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
63Lisp_Object win32_display_name_list;
64
65/* Frame being updated by update_frame. This is declared in term.c.
66 This is set by update_begin and looked at by all the
67 win32 functions. It is zero while not inside an update.
68 In that case, the win32 functions assume that `selected_frame'
69 is the frame to apply to. */
70extern struct frame *updating_frame;
71
72/* This is a frame waiting to be autoraised, within w32_read_socket. */
73struct frame *pending_autoraise_frame;
74
75/* During an update, maximum vpos for ins/del line operations to affect. */
76
77static int flexlines;
78
79/* During an update, nonzero if chars output now should be highlighted. */
80
81static int highlight;
82
83/* Nominal cursor position -- where to draw output.
84 During an update, these are different from the cursor-box position. */
85
86static int curs_x;
87static int curs_y;
88
89DWORD dwWinThreadId = 0;
90HANDLE hWinThread = NULL;
91DWORD dwMainThreadId = 0;
92HANDLE hMainThread = NULL;
93
94/* Mouse movement. */
95
96/* Where the mouse was last time we reported a mouse event. */
97static FRAME_PTR last_mouse_frame;
98static RECT last_mouse_glyph;
99
100/* The scroll bar in which the last motion event occurred.
101
102 If the last motion event occurred in a scroll bar, we set this
103 so win32_mouse_position can know whether to report a scroll bar motion or
104 an ordinary motion.
105
106 If the last motion event didn't occur in a scroll bar, we set this
107 to Qnil, to tell win32_mouse_position to return an ordinary motion event. */
108Lisp_Object last_mouse_scroll_bar;
109int last_mouse_scroll_bar_pos;
110
111/* This is a hack. We would really prefer that win32_mouse_position would
112 return the time associated with the position it returns, but there
113 doesn't seem to be any way to wrest the timestamp from the server
114 along with the position query. So, we just keep track of the time
115 of the last movement we received, and return that in hopes that
116 it's somewhat accurate. */
117Time last_mouse_movement_time;
118
119/* Incremented by w32_read_socket whenever it really tries to read events. */
120#ifdef __STDC__
121static int volatile input_signal_count;
122#else
123static int input_signal_count;
124#endif
125
126extern Lisp_Object Vcommand_line_args, Vsystem_name;
127
128extern Lisp_Object Qface, Qmouse_face;
129
130extern int errno;
131
132/* A mask of extra modifier bits to put into every keyboard char. */
133extern int extra_keyboard_modifiers;
134
135static Lisp_Object Qvendor_specific_keysyms;
136
137void win32_delete_display ();
138
139static void redraw_previous_char ();
140static void redraw_following_char ();
141static unsigned int win32_get_modifiers ();
142
143static int fast_find_position ();
144static void note_mouse_highlight ();
145static void clear_mouse_face ();
146static void show_mouse_face ();
147static void do_line_dance ();
148
149static int win32_cursor_to ();
150static int win32_clear_end_of_line ();
151
152#if 0
153/* This is a function useful for recording debugging information
154 about the sequence of occurrences in this file. */
155
156struct record
157{
158 char *locus;
159 int type;
160};
161
162struct record event_record[100];
163
164int event_record_index;
165
166record_event (locus, type)
167 char *locus;
168 int type;
169{
170 if (event_record_index == sizeof (event_record) / sizeof (struct record))
171 event_record_index = 0;
172
173 event_record[event_record_index].locus = locus;
174 event_record[event_record_index].type = type;
175 event_record_index++;
176}
177
178#endif /* 0 */
179
180/* Return the struct win32_display_info. */
181
182struct win32_display_info *
183win32_display_info_for_display ()
184{
185 return (&one_win32_display_info);
186}
187
188void
189win32_fill_rect (f, _hdc, pix, lprect)
190 FRAME_PTR f;
191 HDC _hdc;
192 COLORREF pix;
193 RECT * lprect;
194{
195 HDC hdc;
196 HBRUSH hb;
197 HANDLE oldobj;
198 RECT rect;
199
200 if (_hdc)
201 hdc = _hdc;
202 else
203 {
204 if (!f) return;
205 hdc = my_get_dc (FRAME_WIN32_WINDOW (f));
206 }
207
208 hb = CreateSolidBrush (pix);
209 oldobj = SelectObject (hdc, hb);
210
211 FillRect (hdc, lprect, hb);
212 SelectObject (hdc, oldobj);
213 DeleteObject (hb);
214
215 if (!_hdc)
216 ReleaseDC (FRAME_WIN32_WINDOW (f), hdc);
217}
218
219void
220win32_clear_window (f)
221 FRAME_PTR f;
222{
223 RECT rect;
224
225 GetClientRect (FRAME_WIN32_WINDOW (f), &rect);
226 win32_clear_rect (f, NULL, &rect);
227}
228
229
230/* Starting and ending updates.
231
232 These hooks are called by update_frame at the beginning and end
233 of a frame update. We record in `updating_frame' the identity
234 of the frame being updated, so that the win32_... functions do not
235 need to take a frame as argument. Most of the win32_... functions
236 should never be called except during an update, the only exceptions
237 being win32_cursor_to, win32_write_glyphs and win32_reassert_line_highlight. */
238
239static
240win32_update_begin (f)
241 struct frame *f;
242{
243 if (f == 0)
244 abort ();
245
246 flexlines = f->height;
247 highlight = 0;
248
249 BLOCK_INPUT;
250
251 if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
252 {
253 /* Don't do highlighting for mouse motion during the update. */
254 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer = 1;
255
256 /* If the frame needs to be redrawn,
257 simply forget about any prior mouse highlighting. */
258 if (FRAME_GARBAGED_P (f))
259 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
260
261 if (!NILP (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window))
262 {
263 int firstline, lastline, i;
264 struct window *w = XWINDOW (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window);
265
266 /* Find the first, and the last+1, lines affected by redisplay. */
267 for (firstline = 0; firstline < f->height; firstline++)
268 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
269 break;
270
271 lastline = f->height;
272 for (i = f->height - 1; i >= 0; i--)
273 {
274 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
275 break;
276 else
277 lastline = i;
278 }
279
280 /* Can we tell that this update does not affect the window
281 where the mouse highlight is? If so, no need to turn off.
282 Likewise, don't do anything if the frame is garbaged;
283 in that case, the FRAME_CURRENT_GLYPHS that we would use
284 are all wrong, and we will redisplay that line anyway. */
285 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
286 || lastline < XFASTINT (w->top)))
287 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
288 }
289 }
290
291 UNBLOCK_INPUT;
292}
293
294static
295win32_update_end (f)
296 struct frame *f;
297{
298 BLOCK_INPUT;
299
300 do_line_dance ();
301 x_display_cursor (f, 1);
302
303 if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
304 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer = 0;
305
306 UNBLOCK_INPUT;
307}
308
309/* This is called after a redisplay on frame F. */
310
311static
312win32_frame_up_to_date (f)
313 FRAME_PTR f;
314{
315 if (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc
316 || f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
317 {
318 note_mouse_highlight (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
319 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_x,
320 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_y);
321 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
322 }
323}
324
325/* External interface to control of standout mode.
326 Call this when about to modify line at position VPOS
327 and not change whether it is highlighted. */
328
329win32_reassert_line_highlight (new, vpos)
330 int new, vpos;
331{
332 highlight = new;
333}
334
335/* Call this when about to modify line at position VPOS
336 and change whether it is highlighted. */
337
338static
339win32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
340 int new_highlight, vpos, first_unused_hpos;
341{
342 highlight = new_highlight;
343 win32_cursor_to (vpos, 0);
344 win32_clear_end_of_line (updating_frame->width);
345}
346
347/* This is used when starting Emacs and when restarting after suspend.
348 When starting Emacs, no window is mapped. And nothing must be done
349 to Emacs's own window if it is suspended (though that rarely happens). */
350
351static
352win32_set_terminal_modes ()
353{
354}
355
356/* This is called when exiting or suspending Emacs.
357 Exiting will make the Win32 windows go away, and suspending
358 requires no action. */
359
360static
361win32_reset_terminal_modes ()
362{
363}
364
365/* Set the nominal cursor position of the frame.
366 This is where display update commands will take effect.
367 This does not affect the place where the cursor-box is displayed. */
368
369static int
370win32_cursor_to (row, col)
371 register int row, col;
372{
373 int orow = row;
374
375 curs_x = col;
376 curs_y = row;
377
378 if (updating_frame == 0)
379 {
380 BLOCK_INPUT;
381 x_display_cursor (selected_frame, 1);
382 UNBLOCK_INPUT;
383 }
384}
385
386/* Display a sequence of N glyphs found at GP.
387 WINDOW is the window to output to. LEFT and TOP are starting coords.
388 HL is 1 if this text is highlighted, 2 if the cursor is on it,
389 3 if should appear in its mouse-face.
390 JUST_FOREGROUND if 1 means draw only the foreground;
391 don't alter the background.
392
393 FONT is the default font to use (for glyphs whose font-code is 0).
394
395 Since the display generation code is responsible for calling
396 compute_char_face and compute_glyph_face on everything it puts in
397 the display structure, we can assume that the face code on each
398 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
399 to which we can actually apply intern_face.
400 Call this function with input blocked. */
401
402static void
403dumpglyphs (f, left, top, gp, n, hl, just_foreground)
404 struct frame *f;
405 int left, top;
406 register GLYPH *gp; /* Points to first GLYPH. */
407 register int n; /* Number of glyphs to display. */
408 int hl;
409 int just_foreground;
410{
411 /* Holds characters to be displayed. */
412 char *buf = (char *) alloca (f->width * sizeof (*buf));
413 register char *cp; /* Steps through buf[]. */
414 register int tlen = GLYPH_TABLE_LENGTH;
415 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
416 Window window = FRAME_WIN32_WINDOW (f);
417 int orig_left = left;
418 HDC hdc;
419
420 hdc = my_get_dc (window);
421
422 while (n > 0)
423 {
424 /* Get the face-code of the next GLYPH. */
425 int cf, len;
426 int g = *gp;
427
428 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
429 cf = FAST_GLYPH_FACE (g);
430
431 /* Find the run of consecutive glyphs with the same face-code.
432 Extract their character codes into BUF. */
433 cp = buf;
434 while (n > 0)
435 {
436 g = *gp;
437 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
438 if (FAST_GLYPH_FACE (g) != cf)
439 break;
440
441 *cp++ = FAST_GLYPH_CHAR (g);
442 --n;
443 ++gp;
444 }
445
446 /* LEN gets the length of the run. */
447 len = cp - buf;
448
449 /* Now output this run of chars, with the font and pixel values
450 determined by the face code CF. */
451 {
452 struct face *face = FRAME_DEFAULT_FACE (f);
453 XFontStruct *font = FACE_FONT (face);
454 int stippled = 0;
455 COLORREF fg;
456 COLORREF bg;
457
458 /* HL = 3 means use a mouse face previously chosen. */
459 if (hl == 3)
460 cf = FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id;
461
462 /* First look at the face of the text itself. */
463 if (cf != 0)
464 {
465 /* It's possible for the display table to specify
466 a face code that is out of range. Use 0 in that case. */
467 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
468 || FRAME_COMPUTED_FACES (f) [cf] == 0)
469 cf = 0;
470
471 if (cf == 1)
472 face = FRAME_MODE_LINE_FACE (f);
473 else
474 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
475 font = FACE_FONT (face);
476 if (FACE_STIPPLE (face))
477 stippled = 1;
478 }
479
480 /* Then comes the distinction between modeline and normal text. */
481 else if (hl == 0)
482 ;
483 else if (hl == 1)
484 {
485 face = FRAME_MODE_LINE_FACE (f);
486 font = FACE_FONT (face);
487 if (FACE_STIPPLE (face))
488 stippled = 1;
489 }
490
491 fg = face->foreground;
492 bg = face->background;
493
494 /* Now override that if the cursor's on this character. */
495 if (hl == 2)
496 {
497 /* The cursor overrides stippling. */
498 stippled = 0;
499
500 if ((!face->font
501 || face->font == (XFontStruct *) FACE_DEFAULT
502 || face->font == f->output_data.win32->font)
503 && face->background == f->output_data.win32->background_pixel
504 && face->foreground == f->output_data.win32->foreground_pixel)
505 {
506 bg = f->output_data.win32->cursor_pixel;
507 fg = face->background;
508 }
509 /* Cursor on non-default face: must merge. */
510 else
511 {
512 bg = f->output_data.win32->cursor_pixel;
513 fg = face->background;
514 /* If the glyph would be invisible,
515 try a different foreground. */
516 if (fg == bg)
517 fg = face->foreground;
518 if (fg == bg)
519 fg = f->output_data.win32->cursor_foreground_pixel;
520 if (fg == bg)
521 fg = face->foreground;
522 /* Make sure the cursor is distinct from text in this face. */
523 if (bg == face->background
524 && fg == face->foreground)
525 {
526 bg = face->foreground;
527 fg = face->background;
528 }
529 }
530 }
531
532 if (font == (XFontStruct *) FACE_DEFAULT)
533 font = f->output_data.win32->font;
534
535 SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
536
537 SetTextColor (hdc, fg);
538 SetBkColor (hdc, bg);
539
540 SelectObject (hdc, font->hfont);
541
542 TextOut (hdc, left, top, buf, len);
543
544 if (!just_foreground)
545 {
546 /* Clear the rest of the line's height. */
547 if (f->output_data.win32->line_height != FONT_HEIGHT (font))
548 win32_fill_area (f, hdc, bg,
549 left,
550 top + FONT_HEIGHT (font),
551 FONT_WIDTH (font) * len,
552 f->output_data.win32->line_height - FONT_HEIGHT (font));
553 }
554
555 {
556 int underline_position = 1;
557
558 if (font->tm.tmDescent <= underline_position)
559 underline_position = font->tm.tmDescent - 1;
560
561 if (face->underline)
562 win32_fill_area (f, hdc, fg,
563 left, (top
564 + FONT_BASE (font)
565 + underline_position),
566 len * FONT_WIDTH (font), 1);
567 }
568
569 left += len * FONT_WIDTH (font);
570 }
571 }
572
573 ReleaseDC (window, hdc);
574}
575
576
577/* Output some text at the nominal frame cursor position.
578 Advance the cursor over the text.
579 Output LEN glyphs at START.
580
581 `highlight', set up by win32_reassert_line_highlight or win32_change_line_highlight,
582 controls the pixel values used for foreground and background. */
583
584static
585win32_write_glyphs (start, len)
586 register GLYPH *start;
587 int len;
588{
589 register int temp_length;
590 struct frame *f;
591
592 BLOCK_INPUT;
593
594 do_line_dance ();
595 f = updating_frame;
596 if (f == 0)
597 {
598 f = selected_frame;
599 /* If not within an update,
600 output at the frame's visible cursor. */
601 curs_x = f->cursor_x;
602 curs_y = f->cursor_y;
603 }
604
605 dumpglyphs (f,
606 CHAR_TO_PIXEL_COL (f, curs_x),
607 CHAR_TO_PIXEL_ROW (f, curs_y),
608 start, len, highlight, 0);
609
610 /* If we drew on top of the cursor, note that it is turned off. */
611 if (curs_y == f->phys_cursor_y
612 && curs_x <= f->phys_cursor_x
613 && curs_x + len > f->phys_cursor_x)
614 f->phys_cursor_x = -1;
615
616 if (updating_frame == 0)
617 {
618 f->cursor_x += len;
619 x_display_cursor (f, 1);
620 f->cursor_x -= len;
621 }
622 else
623 curs_x += len;
624
625 UNBLOCK_INPUT;
626}
627
628/* Clear to the end of the line.
629 Erase the current text line from the nominal cursor position (inclusive)
630 to column FIRST_UNUSED (exclusive). The idea is that everything
631 from FIRST_UNUSED onward is already erased. */
632
633static
634win32_clear_end_of_line (first_unused)
635 register int first_unused;
636{
637 struct frame *f = updating_frame;
638
639 if (f == 0)
640 abort ();
641
642 if (curs_y < 0 || curs_y >= f->height)
643 return 1;
644 if (first_unused <= 0)
645 return 1;
646
647 if (first_unused >= f->width)
648 first_unused = f->width;
649
650 BLOCK_INPUT;
651
652 do_line_dance ();
653
654 /* Notice if the cursor will be cleared by this operation. */
655 if (curs_y == f->phys_cursor_y
656 && curs_x <= f->phys_cursor_x
657 && f->phys_cursor_x < first_unused)
658 f->phys_cursor_x = -1;
659
660 win32_clear_area (f, NULL,
661 CHAR_TO_PIXEL_COL (f, curs_x),
662 CHAR_TO_PIXEL_ROW (f, curs_y),
663 FONT_WIDTH (f->output_data.win32->font) * (first_unused - curs_x),
664 f->output_data.win32->line_height);
665
666 UNBLOCK_INPUT;
667}
668
669static
670win32_clear_frame ()
671{
672 struct frame *f = updating_frame;
673
674 if (f == 0)
675 f = selected_frame;
676
677 f->phys_cursor_x = -1; /* Cursor not visible. */
678 curs_x = 0; /* Nominal cursor position is top left. */
679 curs_y = 0;
680
681 BLOCK_INPUT;
682
683 win32_clear_window (f);
684
685 /* We have to clear the scroll bars, too. If we have changed
686 colors or something like that, then they should be notified. */
687 x_scroll_bar_clear (f);
688
689 UNBLOCK_INPUT;
690}
691
692/* Make audible bell. */
693
694win32_ring_bell ()
695{
696 BLOCK_INPUT;
697
698 if (visible_bell)
699 FlashWindow (FRAME_WIN32_WINDOW (selected_frame), FALSE);
700 else
701 nt_ring_bell ();
702
703 UNBLOCK_INPUT;
704
705 return 1;
706}
707
708/* Insert and delete character.
709 These are not supposed to be used because we are supposed to turn
710 off the feature of using them. */
711
712static
713win32_insert_glyphs (start, len)
714 register char *start;
715 register int len;
716{
717 abort ();
718}
719
720static
721win32_delete_glyphs (n)
722 register int n;
723{
724 abort ();
725}
726
727/* Specify how many text lines, from the top of the window,
728 should be affected by insert-lines and delete-lines operations.
729 This, and those operations, are used only within an update
730 that is bounded by calls to win32_update_begin and win32_update_end. */
731
732static
733win32_set_terminal_window (n)
734 register int n;
735{
736 if (updating_frame == 0)
737 abort ();
738
739 if ((n <= 0) || (n > updating_frame->height))
740 flexlines = updating_frame->height;
741 else
742 flexlines = n;
743}
744
745/* These variables need not be per frame
746 because redisplay is done on a frame-by-frame basis
747 and the line dance for one frame is finished before
748 anything is done for another frame. */
749
750/* Array of line numbers from cached insert/delete operations.
751 line_dance[i] is the old position of the line that we want
752 to move to line i, or -1 if we want a blank line there. */
753static int *line_dance;
754
755/* Allocated length of that array. */
756static int line_dance_len;
757
758/* Flag indicating whether we've done any work. */
759static int line_dance_in_progress;
760
761/* Perform an insert-lines or delete-lines operation,
762 inserting N lines or deleting -N lines at vertical position VPOS. */
763win32_ins_del_lines (vpos, n)
764 int vpos, n;
765{
766 register int fence, i;
767
768 if (vpos >= flexlines)
769 return 1;
770
771 if (!line_dance_in_progress)
772 {
773 int ht = updating_frame->height;
774 if (ht > line_dance_len)
775 {
776 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
777 line_dance_len = ht;
778 }
779 for (i = 0; i < ht; ++i) line_dance[i] = i;
780 line_dance_in_progress = 1;
781 }
782 if (n >= 0)
783 {
784 if (n > flexlines - vpos)
785 n = flexlines - vpos;
786 fence = vpos + n;
787 for (i = flexlines; --i >= fence;)
788 line_dance[i] = line_dance[i-n];
789 for (i = fence; --i >= vpos;)
790 line_dance[i] = -1;
791 }
792 else
793 {
794 n = -n;
795 if (n > flexlines - vpos)
796 n = flexlines - vpos;
797 fence = flexlines - n;
798 for (i = vpos; i < fence; ++i)
799 line_dance[i] = line_dance[i + n];
800 for (i = fence; i < flexlines; ++i)
801 line_dance[i] = -1;
802 }
803}
804
805/* Here's where we actually move the pixels around.
806 Must be called with input blocked. */
807static void
808do_line_dance ()
809{
810 register int i, j, distance;
811 register struct frame *f;
812 int ht;
813 int intborder;
814 HDC hdc;
815
816 /* Must check this flag first. If it's not set, then not only is the
817 array uninitialized, but we might not even have a frame. */
818 if (!line_dance_in_progress)
819 return;
820
821 f = updating_frame;
822 if (f == 0)
823 abort ();
824
825 ht = f->height;
826 intborder = f->output_data.win32->internal_border_width;
827
828 x_display_cursor (updating_frame, 0);
829
830 hdc = my_get_dc (FRAME_WIN32_WINDOW (f));
831
832 for (i = 0; i < ht; ++i)
833 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
834 {
835 for (j = i; (j < ht && line_dance[j] != -1
836 && line_dance[j]-j == distance); ++j);
837 /* Copy [i,j) upward from [i+distance, j+distance) */
838 BitBlt (hdc,
839 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
840 f->width * FONT_WIDTH (f->output_data.win32->font),
841 (j-i) * f->output_data.win32->line_height,
842 hdc,
843 intborder, CHAR_TO_PIXEL_ROW (f, i),
844 SRCCOPY);
845 i = j-1;
846 }
847
848 for (i = ht; --i >=0; )
849 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
850 {
851 for (j = i; (--j >= 0 && line_dance[j] != -1
852 && line_dance[j]-j == distance););
853 /* Copy (j, i] downward from (j+distance, i+distance] */
854 BitBlt (hdc,
855 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
856 f->width * FONT_WIDTH (f->output_data.win32->font),
857 (i-j) * f->output_data.win32->line_height,
858 hdc,
859 intborder, CHAR_TO_PIXEL_ROW (f, j+1),
860 SRCCOPY);
861 i = j+1;
862 }
863
864 ReleaseDC (FRAME_WIN32_WINDOW (f), hdc);
865
866 for (i = 0; i < ht; ++i)
867 if (line_dance[i] == -1)
868 {
869 for (j = i; j < ht && line_dance[j] == -1; ++j);
870 /* Clear [i,j) */
871 win32_clear_area (f, NULL,
872 intborder,
873 CHAR_TO_PIXEL_ROW (f, i),
874 f->width * FONT_WIDTH (f->output_data.win32->font),
875 (j-i) * f->output_data.win32->line_height);
876 i = j-1;
877 }
878 line_dance_in_progress = 0;
879}
880
881/* Support routines for exposure events. */
882static void clear_cursor ();
883
884/* Output into a rectangle of a window (for frame F)
885 the characters in f->phys_lines that overlap that rectangle.
886 TOP and LEFT are the position of the upper left corner of the rectangle.
887 ROWS and COLS are the size of the rectangle.
888 Call this function with input blocked. */
889
890void
891dumprectangle (f, left, top, cols, rows)
892 struct frame *f;
893 register int left, top, cols, rows;
894{
895 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
896 int cursor_cleared = 0;
897 int bottom, right;
898 register int y;
899
900 if (FRAME_GARBAGED_P (f))
901 return;
902
903 /* Express rectangle as four edges, instead of position-and-size. */
904 bottom = top + rows;
905 right = left + cols;
906
907 /* Convert rectangle edges in pixels to edges in chars.
908 Round down for left and top, up for right and bottom. */
909 top = PIXEL_TO_CHAR_ROW (f, top);
910 left = PIXEL_TO_CHAR_COL (f, left);
911 bottom += (f->output_data.win32->line_height - 1);
912 right += (FONT_WIDTH (f->output_data.win32->font) - 1);
913 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
914 right = PIXEL_TO_CHAR_COL (f, right);
915
916 /* Clip the rectangle to what can be visible. */
917 if (left < 0)
918 left = 0;
919 if (top < 0)
920 top = 0;
921 if (right > f->width)
922 right = f->width;
923 if (bottom > f->height)
924 bottom = f->height;
925
926 /* Get size in chars of the rectangle. */
927 cols = right - left;
928 rows = bottom - top;
929
930 /* If rectangle has zero area, return. */
931 if (rows <= 0) return;
932 if (cols <= 0) return;
933
934 /* Turn off the cursor if it is in the rectangle.
935 We will turn it back on afterward. */
936 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
937 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
938 {
939 clear_cursor (f);
940 cursor_cleared = 1;
941 }
942
943 /* Display the text in the rectangle, one text line at a time. */
944
945 for (y = top; y < bottom; y++)
946 {
947 GLYPH *line = &active_frame->glyphs[y][left];
948
949 if (! active_frame->enable[y] || left > active_frame->used[y])
950 continue;
951
952 dumpglyphs (f,
953 CHAR_TO_PIXEL_COL (f, left),
954 CHAR_TO_PIXEL_ROW (f, y),
955 line, min (cols, active_frame->used[y] - left),
956 active_frame->highlight[y], 0);
957 }
958
959 /* Turn the cursor on if we turned it off. */
960
961 if (cursor_cleared)
962 x_display_cursor (f, 1);
963}
964
965static void
966frame_highlight (f)
967 struct frame *f;
968{
969 x_display_cursor (f, 1);
970}
971
972static void
973frame_unhighlight (f)
974 struct frame *f;
975{
976 x_display_cursor (f, 1);
977}
978
979static void win32_frame_rehighlight ();
980static void x_frame_rehighlight ();
981
982/* The focus has changed. Update the frames as necessary to reflect
983 the new situation. Note that we can't change the selected frame
984 here, because the Lisp code we are interrupting might become confused.
985 Each event gets marked with the frame in which it occurred, so the
986 Lisp code can tell when the switch took place by examining the events. */
987
988void
989x_new_focus_frame (dpyinfo, frame)
990 struct win32_display_info *dpyinfo;
991 struct frame *frame;
992{
993 struct frame *old_focus = dpyinfo->win32_focus_frame;
994 int events_enqueued = 0;
995
996 if (frame != dpyinfo->win32_focus_frame)
997 {
998 /* Set this before calling other routines, so that they see
999 the correct value of win32_focus_frame. */
1000 dpyinfo->win32_focus_frame = frame;
1001
1002 if (old_focus && old_focus->auto_lower)
1003 x_lower_frame (old_focus);
1004
1005 if (dpyinfo->win32_focus_frame && dpyinfo->win32_focus_frame->auto_raise)
1006 pending_autoraise_frame = dpyinfo->win32_focus_frame;
1007 else
1008 pending_autoraise_frame = 0;
1009 }
1010
1011 x_frame_rehighlight (dpyinfo);
1012}
1013
1014/* Handle an event saying the mouse has moved out of an Emacs frame. */
1015
1016void
1017x_mouse_leave (dpyinfo)
1018 struct win32_display_info *dpyinfo;
1019{
1020 x_new_focus_frame (dpyinfo, dpyinfo->win32_focus_event_frame);
1021}
1022
1023/* The focus has changed, or we have redirected a frame's focus to
1024 another frame (this happens when a frame uses a surrogate
1025 minibuffer frame). Shift the highlight as appropriate.
1026
1027 The FRAME argument doesn't necessarily have anything to do with which
1028 frame is being highlighted or unhighlighted; we only use it to find
1029 the appropriate display info. */
1030static void
1031win32_frame_rehighlight (frame)
1032 struct frame *frame;
1033{
1034 x_frame_rehighlight (FRAME_WIN32_DISPLAY_INFO (frame));
1035}
1036
1037static void
1038x_frame_rehighlight (dpyinfo)
1039 struct win32_display_info *dpyinfo;
1040{
1041 struct frame *old_highlight = dpyinfo->win32_highlight_frame;
1042
1043 if (dpyinfo->win32_focus_frame)
1044 {
1045 dpyinfo->win32_highlight_frame
1046 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame)))
1047 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame))
1048 : dpyinfo->win32_focus_frame);
1049 if (! FRAME_LIVE_P (dpyinfo->win32_highlight_frame))
1050 {
1051 FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame) = Qnil;
1052 dpyinfo->win32_highlight_frame = dpyinfo->win32_focus_frame;
1053 }
1054 }
1055 else
1056 dpyinfo->win32_highlight_frame = 0;
1057
1058 if (dpyinfo->win32_highlight_frame != old_highlight)
1059 {
1060 if (old_highlight)
1061 frame_unhighlight (old_highlight);
1062 if (dpyinfo->win32_highlight_frame)
1063 frame_highlight (dpyinfo->win32_highlight_frame);
1064 }
1065}
1066
1067/* Keyboard processing - modifier keys, etc. */
1068
1069/* Convert a keysym to its name. */
1070
1071char *
1072x_get_keysym_name (keysym)
1073 int keysym;
1074{
1075 /* Make static so we can always return it */
1076 static char value[100];
1077
1078 BLOCK_INPUT;
1079 GetKeyNameText(keysym, value, 100);
1080 UNBLOCK_INPUT;
1081
1082 return value;
1083}
1084
1085/* Mouse clicks and mouse movement. Rah. */
1086
1087/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1088 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1089 that the glyph at X, Y occupies, if BOUNDS != 0.
1090 If NOCLIP is nonzero, do not force the value into range. */
1091
1092void
1093pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1094 FRAME_PTR f;
1095 register int pix_x, pix_y;
1096 register int *x, *y;
1097 RECT *bounds;
1098 int noclip;
1099{
1100 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1101 even for negative values. */
1102 if (pix_x < 0)
1103 pix_x -= FONT_WIDTH ((f)->output_data.win32->font) - 1;
1104 if (pix_y < 0)
1105 pix_y -= (f)->output_data.win32->line_height - 1;
1106
1107 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1108 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1109
1110 if (bounds)
1111 {
1112 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
1113 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
1114 bounds->right = bounds->left + FONT_WIDTH (f->output_data.win32->font) - 1;
1115 bounds->bottom = bounds->top + f->output_data.win32->line_height - 1;
1116 }
1117
1118 if (!noclip)
1119 {
1120 if (pix_x < 0)
1121 pix_x = 0;
1122 else if (pix_x > f->width)
1123 pix_x = f->width;
1124
1125 if (pix_y < 0)
1126 pix_y = 0;
1127 else if (pix_y > f->height)
1128 pix_y = f->height;
1129 }
1130
1131 *x = pix_x;
1132 *y = pix_y;
1133}
1134
1135void
1136glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1137 FRAME_PTR f;
1138 register int x, y;
1139 register int *pix_x, *pix_y;
1140{
1141 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1142 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1143}
1144
1145BOOL
1146parse_button (message, pbutton, pup)
1147 int message;
1148 int * pbutton;
1149 int * pup;
1150{
1151 int button = 0;
1152 int up = 0;
1153
1154 switch (message)
1155 {
1156 case WM_LBUTTONDOWN:
1157 button = 0;
1158 up = 0;
1159 break;
1160 case WM_LBUTTONUP:
1161 button = 0;
1162 up = 1;
1163 break;
1164 case WM_MBUTTONDOWN:
1165 button = 1;
1166 up = 0;
1167 break;
1168 case WM_MBUTTONUP:
1169 button = 1;
1170 up = 1;
1171 break;
1172 case WM_RBUTTONDOWN:
1173 button = 2;
1174 up = 0;
1175 break;
1176 case WM_RBUTTONUP:
1177 button = 2;
1178 up = 1;
1179 break;
1180 default:
1181 return (FALSE);
1182 }
1183
1184 if (pup) *pup = up;
1185 if (pbutton) *pbutton = button;
1186
1187 return (TRUE);
1188}
1189
1190
1191/* Prepare a mouse-event in *RESULT for placement in the input queue.
1192
1193 If the event is a button press, then note that we have grabbed
1194 the mouse. */
1195
1196static void
1197construct_mouse_click (result, msg, f)
1198 struct input_event *result;
1199 Win32Msg *msg;
1200 struct frame *f;
1201{
1202 int button;
1203 int up;
1204
1205 parse_button (msg->msg.message, &button, &up);
1206
1207 /* Make the event type no_event; we'll change that when we decide
1208 otherwise. */
1209 result->kind = mouse_click;
1210 result->code = button;
1211 result->timestamp = msg->msg.time;
1212 result->modifiers = (msg->dwModifiers
1213 | (up
1214 ? up_modifier
1215 : down_modifier));
1216
1217 {
1218 int row, column;
1219
1220 XSETINT (result->x, LOWORD (msg->msg.lParam));
1221 XSETINT (result->y, HIWORD (msg->msg.lParam));
1222 XSETFRAME (result->frame_or_window, f);
1223 }
1224}
1225
1226
1227/* Function to report a mouse movement to the mainstream Emacs code.
1228 The input handler calls this.
1229
1230 We have received a mouse movement event, which is given in *event.
1231 If the mouse is over a different glyph than it was last time, tell
1232 the mainstream emacs code by setting mouse_moved. If not, ask for
1233 another motion event, so we can check again the next time it moves. */
1234
1235static void
1236note_mouse_movement (frame, msg)
1237 FRAME_PTR frame;
1238 MSG *msg;
1239{
1240 last_mouse_movement_time = msg->time;
1241
1242 if (msg->hwnd != FRAME_WIN32_WINDOW (frame))
1243 {
1244 frame->mouse_moved = 1;
1245 last_mouse_scroll_bar = Qnil;
1246
1247 note_mouse_highlight (frame, -1, -1);
1248 }
1249
1250 /* Has the mouse moved off the glyph it was on at the last sighting? */
1251 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
1252 || LOWORD (msg->lParam) > last_mouse_glyph.right
1253 || HIWORD (msg->lParam) < last_mouse_glyph.left
1254 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
1255 {
1256 frame->mouse_moved = 1;
1257 last_mouse_scroll_bar = Qnil;
1258
1259 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
1260 }
1261}
1262
1263/* This is used for debugging, to turn off note_mouse_highlight. */
1264static int disable_mouse_highlight;
1265
1266/* Take proper action when the mouse has moved to position X, Y on frame F
1267 as regards highlighting characters that have mouse-face properties.
1268 Also dehighlighting chars where the mouse was before.
1269 X and Y can be negative or out of range. */
1270
1271static void
1272note_mouse_highlight (f, x, y)
1273 FRAME_PTR f;
1274 int x, y;
1275{
1276 int row, column, portion;
1277 RECT new_glyph;
1278 Lisp_Object window;
1279 struct window *w;
1280
1281 if (disable_mouse_highlight)
1282 return;
1283
1284 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
1285 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
1286 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
1287
1288 if (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer)
1289 return;
1290
1291 if (gc_in_progress)
1292 {
1293 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
1294 return;
1295 }
1296
1297 /* Find out which glyph the mouse is on. */
1298 pixel_to_glyph_coords (f, x, y, &column, &row,
1299 &new_glyph, FRAME_WIN32_DISPLAY_INFO (f)->grabbed);
1300
1301 /* Which window is that in? */
1302 window = window_from_coordinates (f, column, row, &portion);
1303 w = XWINDOW (window);
1304
1305 /* If we were displaying active text in another window, clear that. */
1306 if (! EQ (window, FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window))
1307 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
1308
1309 /* Are we in a window whose display is up to date?
1310 And verify the buffer's text has not changed. */
1311 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
1312 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
1313 && EQ (w->window_end_valid, w->buffer)
1314 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
1315 {
1316 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1317 int i, pos;
1318
1319 /* Find which buffer position the mouse corresponds to. */
1320 for (i = column; i >= 0; i--)
1321 if (ptr[i] > 0)
1322 break;
1323 pos = ptr[i];
1324 /* Is it outside the displayed active region (if any)? */
1325 if (pos <= 0)
1326 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
1327 else if (! (EQ (window, FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window)
1328 && row >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
1329 && row <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
1330 && (row > FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
1331 || column >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col)
1332 && (row < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
1333 || column < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col
1334 || FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end)))
1335 {
1336 Lisp_Object mouse_face, overlay, position;
1337 Lisp_Object *overlay_vec;
1338 int len, noverlays, ignor1;
1339 struct buffer *obuf;
1340 int obegv, ozv;
1341
1342 /* If we get an out-of-range value, return now; avoid an error. */
1343 if (pos > BUF_Z (XBUFFER (w->buffer)))
1344 return;
1345
1346 /* Make the window's buffer temporarily current for
1347 overlays_at and compute_char_face. */
1348 obuf = current_buffer;
1349 current_buffer = XBUFFER (w->buffer);
1350 obegv = BEGV;
1351 ozv = ZV;
1352 BEGV = BEG;
1353 ZV = Z;
1354
1355 /* Yes. Clear the display of the old active region, if any. */
1356 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
1357
1358 /* Is this char mouse-active? */
1359 XSETINT (position, pos);
1360
1361 len = 10;
1362 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1363
1364 /* Put all the overlays we want in a vector in overlay_vec.
1365 Store the length in len. */
1366 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
1367 NULL, NULL);
1368 noverlays = sort_overlays (overlay_vec, noverlays, w);
1369
1370 /* Find the highest priority overlay that has a mouse-face prop. */
1371 overlay = Qnil;
1372 for (i = 0; i < noverlays; i++)
1373 {
1374 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1375 if (!NILP (mouse_face))
1376 {
1377 overlay = overlay_vec[i];
1378 break;
1379 }
1380 }
1381 free (overlay_vec);
1382 /* If no overlay applies, get a text property. */
1383 if (NILP (overlay))
1384 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
1385
1386 /* Handle the overlay case. */
1387 if (! NILP (overlay))
1388 {
1389 /* Find the range of text around this char that
1390 should be active. */
1391 Lisp_Object before, after;
1392 int ignore;
1393
1394 before = Foverlay_start (overlay);
1395 after = Foverlay_end (overlay);
1396 /* Record this as the current active region. */
1397 fast_find_position (window, before,
1398 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col,
1399 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row);
1400 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end
1401 = !fast_find_position (window, after,
1402 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col,
1403 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row);
1404 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = window;
1405 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id
1406 = compute_char_face (f, w, pos, 0, 0,
1407 &ignore, pos + 1, 1);
1408
1409 /* Display it as active. */
1410 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f), 1);
1411 }
1412 /* Handle the text property case. */
1413 else if (! NILP (mouse_face))
1414 {
1415 /* Find the range of text around this char that
1416 should be active. */
1417 Lisp_Object before, after, beginning, end;
1418 int ignore;
1419
1420 beginning = Fmarker_position (w->start);
1421 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1422 - XFASTINT (w->window_end_pos)));
1423 before
1424 = Fprevious_single_property_change (make_number (pos + 1),
1425 Qmouse_face,
1426 w->buffer, beginning);
1427 after
1428 = Fnext_single_property_change (position, Qmouse_face,
1429 w->buffer, end);
1430 /* Record this as the current active region. */
1431 fast_find_position (window, before,
1432 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col,
1433 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row);
1434 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end
1435 = !fast_find_position (window, after,
1436 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col,
1437 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row);
1438 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = window;
1439 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id
1440 = compute_char_face (f, w, pos, 0, 0,
1441 &ignore, pos + 1, 1);
1442
1443 /* Display it as active. */
1444 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f), 1);
1445 }
1446 BEGV = obegv;
1447 ZV = ozv;
1448 current_buffer = obuf;
1449 }
1450 }
1451}
1452
1453/* Find the row and column of position POS in window WINDOW.
1454 Store them in *COLUMNP and *ROWP.
1455 This assumes display in WINDOW is up to date.
1456 If POS is above start of WINDOW, return coords
1457 of start of first screen line.
1458 If POS is after end of WINDOW, return coords of end of last screen line.
1459
1460 Value is 1 if POS is in range, 0 if it was off screen. */
1461
1462static int
1463fast_find_position (window, pos, columnp, rowp)
1464 Lisp_Object window;
1465 int pos;
1466 int *columnp, *rowp;
1467{
1468 struct window *w = XWINDOW (window);
1469 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1470 int i;
1471 int row = 0;
1472 int left = w->left;
1473 int top = w->top;
1474 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
1475 int width = window_internal_width (w);
1476 int *charstarts;
1477 int lastcol;
1478 int maybe_next_line = 0;
1479
1480 /* Find the right row. */
1481 for (i = 0;
1482 i < height;
1483 i++)
1484 {
1485 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
1486 if (linestart > pos)
1487 break;
1488 /* If the position sought is the end of the buffer,
1489 don't include the blank lines at the bottom of the window. */
1490 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
1491 {
1492 maybe_next_line = 1;
1493 break;
1494 }
1495 if (linestart > 0)
1496 row = i;
1497 }
1498
1499 /* Find the right column with in it. */
1500 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
1501 lastcol = left;
1502 for (i = 0; i < width; i++)
1503 {
1504 if (charstarts[left + i] == pos)
1505 {
1506 *rowp = row + top;
1507 *columnp = i + left;
1508 return 1;
1509 }
1510 else if (charstarts[left + i] > pos)
1511 break;
1512 else if (charstarts[left + i] > 0)
1513 lastcol = left + i;
1514 }
1515
1516 /* If we're looking for the end of the buffer,
1517 and we didn't find it in the line we scanned,
1518 use the start of the following line. */
1519 if (maybe_next_line)
1520 {
1521 row++;
1522 i = 0;
1523 }
1524
1525 *rowp = row + top;
1526 *columnp = lastcol;
1527 return 0;
1528}
1529
1530/* Display the active region described by mouse_face_*
1531 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1532
1533static void
1534show_mouse_face (dpyinfo, hl)
1535 struct win32_display_info *dpyinfo;
1536 int hl;
1537{
1538 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1539 int width = window_internal_width (w);
1540 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1541 int i;
1542 int cursor_off = 0;
1543 int old_curs_x = curs_x;
1544 int old_curs_y = curs_y;
1545
1546 /* Set these variables temporarily
1547 so that if we have to turn the cursor off and on again
1548 we will put it back at the same place. */
1549 curs_x = f->phys_cursor_x;
1550 curs_y = f->phys_cursor_y;
1551
1552 for (i = FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row;
1553 i <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
1554 {
1555 int column = (i == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
1556 ? FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col
1557 : w->left);
1558 int endcolumn = (i == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
1559 ? FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col
1560 : w->left + width);
1561 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
1562
1563 /* If the cursor's in the text we are about to rewrite,
1564 turn the cursor off. */
1565 if (i == curs_y
1566 && curs_x >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col - 1
1567 && curs_x <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col)
1568 {
1569 x_display_cursor (f, 0);
1570 cursor_off = 1;
1571 }
1572
1573 dumpglyphs (f,
1574 CHAR_TO_PIXEL_COL (f, column),
1575 CHAR_TO_PIXEL_ROW (f, i),
1576 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
1577 endcolumn - column,
1578 /* Highlight with mouse face if hl > 0. */
1579 hl > 0 ? 3 : 0, 0);
1580 }
1581
1582 /* If we turned the cursor off, turn it back on. */
1583 if (cursor_off)
1584 x_display_cursor (f, 1);
1585
1586 curs_x = old_curs_x;
1587 curs_y = old_curs_y;
1588
1589 /* Change the mouse cursor according to the value of HL. */
1590 if (hl > 0)
1591 SetCursor (f->output_data.win32->cross_cursor);
1592 else
1593 SetCursor (f->output_data.win32->text_cursor);
1594}
1595
1596/* Clear out the mouse-highlighted active region.
1597 Redraw it unhighlighted first. */
1598
1599static void
1600clear_mouse_face (dpyinfo)
1601 struct win32_display_info *dpyinfo;
1602{
1603 if (! NILP (dpyinfo->mouse_face_window))
1604 show_mouse_face (dpyinfo, 0);
1605
1606 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1607 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1608 dpyinfo->mouse_face_window = Qnil;
1609}
1610
1611struct scroll_bar *x_window_to_scroll_bar ();
1612static void x_scroll_bar_report_motion ();
1613
1614/* Return the current position of the mouse.
1615 *fp should be a frame which indicates which display to ask about.
1616
1617 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1618 and *part to the frame, window, and scroll bar part that the mouse
1619 is over. Set *x and *y to the portion and whole of the mouse's
1620 position on the scroll bar.
1621
1622 If the mouse movement started elsewhere, set *fp to the frame the
1623 mouse is on, *bar_window to nil, and *x and *y to the character cell
1624 the mouse is over.
1625
1626 Set *time to the server timestamp for the time at which the mouse
1627 was at this position.
1628
1629 Don't store anything if we don't have a valid set of values to report.
1630
1631 This clears the mouse_moved flag, so we can wait for the next mouse
1632 movement. This also calls XQueryPointer, which will cause the
1633 server to give us another MotionNotify when the mouse moves
1634 again. */
1635
1636static void
1637win32_mouse_position (fp, insist, bar_window, part, x, y, time)
1638 FRAME_PTR *fp;
1639 int insist;
1640 Lisp_Object *bar_window;
1641 enum scroll_bar_part *part;
1642 Lisp_Object *x, *y;
1643 unsigned long *time;
1644{
1645 FRAME_PTR f1;
1646
1647 BLOCK_INPUT;
1648
1649 if (! NILP (last_mouse_scroll_bar))
1650 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
1651 else
1652 {
1653 POINT pt;
1654
1655 Lisp_Object frame, tail;
1656
1657 /* Clear the mouse-moved flag for every frame on this display. */
1658 FOR_EACH_FRAME (tail, frame)
1659 XFRAME (frame)->mouse_moved = 0;
1660
1661 last_mouse_scroll_bar = Qnil;
1662
1663 GetCursorPos (&pt);
1664
1665 /* Now we have a position on the root; find the innermost window
1666 containing the pointer. */
1667 {
1668 if (FRAME_WIN32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
1669 && FRAME_LIVE_P (last_mouse_frame))
1670 {
1671 f1 = last_mouse_frame;
1672 }
1673 else
1674 {
1675 /* Is win one of our frames? */
1676 f1 = x_window_to_frame (FRAME_WIN32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
1677 }
1678
1679 /* If not, is it one of our scroll bars? */
1680 if (! f1)
1681 {
1682 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
1683
1684 if (bar)
1685 {
1686 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1687 }
1688 }
1689
1690 if (f1 == 0 && insist)
1691 f1 = selected_frame;
1692
1693 if (f1)
1694 {
1695 int ignore1, ignore2;
1696
1697 ScreenToClient (FRAME_WIN32_WINDOW (f1), &pt);
1698
1699 /* Ok, we found a frame. Store all the values. */
1700
1701 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
1702 &last_mouse_glyph,
1703 FRAME_WIN32_DISPLAY_INFO (f1)->grabbed
1704 || insist);
1705
1706 *bar_window = Qnil;
1707 *part = 0;
1708 *fp = f1;
1709 XSETINT (*x, pt.x);
1710 XSETINT (*y, pt.y);
1711 *time = last_mouse_movement_time;
1712 }
1713 }
1714 }
1715
1716 UNBLOCK_INPUT;
1717}
1718
1719/* Scroll bar support. */
1720
1721/* Given an window ID, find the struct scroll_bar which manages it.
1722 This can be called in GC, so we have to make sure to strip off mark
1723 bits. */
1724struct scroll_bar *
1725x_window_to_scroll_bar (window_id)
1726 Window window_id;
1727{
1728 Lisp_Object tail, frame;
1729
1730 for (tail = Vframe_list;
1731 XGCTYPE (tail) == Lisp_Cons;
1732 tail = XCONS (tail)->cdr)
1733 {
1734 Lisp_Object frame, bar, condemned;
1735
1736 frame = XCONS (tail)->car;
1737 /* All elements of Vframe_list should be frames. */
1738 if (! GC_FRAMEP (frame))
1739 abort ();
1740
1741 /* Scan this frame's scroll bar list for a scroll bar with the
1742 right window ID. */
1743 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1744 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1745 /* This trick allows us to search both the ordinary and
1746 condemned scroll bar lists with one loop. */
1747 ! GC_NILP (bar) || (bar = condemned,
1748 condemned = Qnil,
1749 ! GC_NILP (bar));
1750 bar = XSCROLL_BAR (bar)->next)
1751 if (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar)) == window_id)
1752 return XSCROLL_BAR (bar);
1753 }
1754
1755 return 0;
1756}
1757
1758HWND
1759my_create_scrollbar (f, bar)
1760 struct frame * f;
1761 struct scroll_bar * bar;
1762{
1763 MSG msg;
1764
1765 PostThreadMessage (dwWinThreadId, WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
1766 (LPARAM) bar);
1767 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
1768
1769 return ((HWND) msg.wParam);
1770}
1771
1772void
1773my_destroy_window (f, hwnd)
1774 struct frame * f;
1775 HWND hwnd;
1776{
1777 SendMessage (FRAME_WIN32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
1778 (WPARAM) hwnd, 0);
1779}
1780
1781/* Open a new window to serve as a scroll bar, and return the
1782 scroll bar vector for it. */
1783static struct scroll_bar *
1784x_scroll_bar_create (window, top, left, width, height)
1785 struct window *window;
1786 int top, left, width, height;
1787{
1788 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
1789 struct scroll_bar *bar
1790 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1791 HWND hwnd;
1792
1793 BLOCK_INPUT;
1794
1795 XSETWINDOW (bar->window, window);
1796 XSETINT (bar->top, top);
1797 XSETINT (bar->left, left);
1798 XSETINT (bar->width, width);
1799 XSETINT (bar->height, height);
1800 XSETINT (bar->start, 0);
1801 XSETINT (bar->end, 0);
1802 bar->dragging = Qnil;
1803
1804 /* Requires geometry to be set before call to create the real window */
1805
1806 hwnd = my_create_scrollbar (f, bar);
1807
1808 SetScrollRange (hwnd, SB_CTL, 0, height, FALSE);
1809 SetScrollPos (hwnd, SB_CTL, 0, TRUE);
1810
1811 SET_SCROLL_BAR_WIN32_WINDOW (bar, hwnd);
1812
1813 /* Add bar to its frame's list of scroll bars. */
1814 bar->next = FRAME_SCROLL_BARS (f);
1815 bar->prev = Qnil;
1816 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
1817 if (! NILP (bar->next))
1818 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
1819
1820 UNBLOCK_INPUT;
1821
1822 return bar;
1823}
1824
1825/* Draw BAR's handle in the proper position.
1826 If the handle is already drawn from START to END, don't bother
1827 redrawing it, unless REBUILD is non-zero; in that case, always
1828 redraw it. (REBUILD is handy for drawing the handle after expose
1829 events.)
1830
1831 Normally, we want to constrain the start and end of the handle to
1832 fit inside its rectangle, but if the user is dragging the scroll bar
1833 handle, we want to let them drag it down all the way, so that the
1834 bar's top is as far down as it goes; otherwise, there's no way to
1835 move to the very end of the buffer. */
1836static void
1837x_scroll_bar_set_handle (bar, start, end, rebuild)
1838 struct scroll_bar *bar;
1839 int start, end;
1840 int rebuild;
1841{
1842 int dragging = ! NILP (bar->dragging);
1843 Window w = SCROLL_BAR_WIN32_WINDOW (bar);
1844 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1845
1846 /* If the display is already accurate, do nothing. */
1847 if (! rebuild
1848 && start == XINT (bar->start)
1849 && end == XINT (bar->end))
1850 return;
1851
1852 BLOCK_INPUT;
1853
1854 /* Store the adjusted setting in the scroll bar. */
1855 XSETINT (bar->start, start);
1856 XSETINT (bar->end, end);
1857
1858 /* If we are less than half of the page use start otherwise use end */
1859
1860 SetScrollPos (w, SB_CTL, ((start >> 1) < bar->height)?start:end, TRUE);
1861
1862 UNBLOCK_INPUT;
1863}
1864
1865/* Move a scroll bar around on the screen, to accommodate changing
1866 window configurations. */
1867static void
1868x_scroll_bar_move (bar, top, left, width, height)
1869 struct scroll_bar *bar;
1870 int top, left, width, height;
1871{
1872 Window w = SCROLL_BAR_WIN32_WINDOW (bar);
1873 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1874
1875 BLOCK_INPUT;
1876
1877 MoveWindow (w, left, top, width, height, TRUE);
1878 SetScrollRange (w, SB_CTL, 0, height, FALSE);
1879
1880 XSETINT (bar->left, left);
1881 XSETINT (bar->top, top);
1882 XSETINT (bar->width, width);
1883 XSETINT (bar->height, height);
1884
1885 UNBLOCK_INPUT;
1886}
1887
1888/* Destroy the window for BAR, and set its Emacs window's scroll bar
1889 to nil. */
1890static void
1891x_scroll_bar_remove (bar)
1892 struct scroll_bar *bar;
1893{
1894 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1895
1896 BLOCK_INPUT;
1897
1898 /* Destroy the window. */
1899 my_destroy_window (f, SCROLL_BAR_WIN32_WINDOW (bar));
1900
1901 /* Disassociate this scroll bar from its window. */
1902 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
1903
1904 UNBLOCK_INPUT;
1905}
1906
1907/* Set the handle of the vertical scroll bar for WINDOW to indicate
1908 that we are displaying PORTION characters out of a total of WHOLE
1909 characters, starting at POSITION. If WINDOW has no scroll bar,
1910 create one. */
1911static void
1912win32_set_vertical_scroll_bar (window, portion, whole, position)
1913 struct window *window;
1914 int portion, whole, position;
1915{
1916 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
1917 int top = XINT (window->top);
1918 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
1919 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
1920
1921 /* Where should this scroll bar be, pixelwise? */
1922 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
1923 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
1924 int pixel_width
1925 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
1926 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
1927 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
1928 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
1929
1930 struct scroll_bar *bar;
1931
1932 /* Does the scroll bar exist yet? */
1933 if (NILP (window->vertical_scroll_bar))
1934 bar = x_scroll_bar_create (window,
1935 pixel_top, pixel_left,
1936 pixel_width, pixel_height);
1937 else
1938 {
1939 /* It may just need to be moved and resized. */
1940 bar = XSCROLL_BAR (window->vertical_scroll_bar);
1941 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
1942 }
1943
1944 /* Set the scroll bar's current state, unless we're currently being
1945 dragged. */
1946 if (NILP (bar->dragging))
1947 {
1948 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
1949
1950 if (whole == 0)
1951 x_scroll_bar_set_handle (bar, 0, top_range, 0);
1952 else
1953 {
1954 int start = (int) (((double) position * top_range) / whole);
1955 int end = (int) (((double) (position + portion) * top_range) / whole);
1956
1957 x_scroll_bar_set_handle (bar, start, end, 0);
1958 }
1959 }
1960
1961 XSETVECTOR (window->vertical_scroll_bar, bar);
1962}
1963
1964
1965/* The following three hooks are used when we're doing a thorough
1966 redisplay of the frame. We don't explicitly know which scroll bars
1967 are going to be deleted, because keeping track of when windows go
1968 away is a real pain - "Can you say set-window-configuration, boys
1969 and girls?" Instead, we just assert at the beginning of redisplay
1970 that *all* scroll bars are to be removed, and then save a scroll bar
1971 from the fiery pit when we actually redisplay its window. */
1972
1973/* Arrange for all scroll bars on FRAME to be removed at the next call
1974 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
1975 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
1976static void
1977win32_condemn_scroll_bars (frame)
1978 FRAME_PTR frame;
1979{
1980 /* The condemned list should be empty at this point; if it's not,
1981 then the rest of Emacs isn't using the condemn/redeem/judge
1982 protocol correctly. */
1983 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
1984 abort ();
1985
1986 /* Move them all to the "condemned" list. */
1987 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
1988 FRAME_SCROLL_BARS (frame) = Qnil;
1989}
1990
1991/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
1992 Note that WINDOW isn't necessarily condemned at all. */
1993static void
1994win32_redeem_scroll_bar (window)
1995 struct window *window;
1996{
1997 struct scroll_bar *bar;
1998
1999 /* We can't redeem this window's scroll bar if it doesn't have one. */
2000 if (NILP (window->vertical_scroll_bar))
2001 abort ();
2002
2003 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2004
2005 /* Unlink it from the condemned list. */
2006 {
2007 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2008
2009 if (NILP (bar->prev))
2010 {
2011 /* If the prev pointer is nil, it must be the first in one of
2012 the lists. */
2013 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2014 /* It's not condemned. Everything's fine. */
2015 return;
2016 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2017 window->vertical_scroll_bar))
2018 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2019 else
2020 /* If its prev pointer is nil, it must be at the front of
2021 one or the other! */
2022 abort ();
2023 }
2024 else
2025 XSCROLL_BAR (bar->prev)->next = bar->next;
2026
2027 if (! NILP (bar->next))
2028 XSCROLL_BAR (bar->next)->prev = bar->prev;
2029
2030 bar->next = FRAME_SCROLL_BARS (f);
2031 bar->prev = Qnil;
2032 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2033 if (! NILP (bar->next))
2034 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2035 }
2036}
2037
2038/* Remove all scroll bars on FRAME that haven't been saved since the
2039 last call to `*condemn_scroll_bars_hook'. */
2040static void
2041win32_judge_scroll_bars (f)
2042 FRAME_PTR f;
2043{
2044 Lisp_Object bar, next;
2045
2046 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2047
2048 /* Clear out the condemned list now so we won't try to process any
2049 more events on the hapless scroll bars. */
2050 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2051
2052 for (; ! NILP (bar); bar = next)
2053 {
2054 struct scroll_bar *b = XSCROLL_BAR (bar);
2055
2056 x_scroll_bar_remove (b);
2057
2058 next = b->next;
2059 b->next = b->prev = Qnil;
2060 }
2061
2062 /* Now there should be no references to the condemned scroll bars,
2063 and they should get garbage-collected. */
2064}
2065
2066/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2067 is set to something other than no_event, it is enqueued.
2068
2069 This may be called from a signal handler, so we have to ignore GC
2070 mark bits. */
2071static void
2072x_scroll_bar_handle_click (bar, msg, emacs_event)
2073 struct scroll_bar *bar;
2074 Win32Msg *msg;
2075 struct input_event *emacs_event;
2076{
2077 if (! GC_WINDOWP (bar->window))
2078 abort ();
2079
2080 emacs_event->kind = scroll_bar_click;
2081 emacs_event->code = 0;
2082 emacs_event->modifiers = (msg->dwModifiers
2083 | ((LOWORD (msg->msg.wParam) == SB_ENDSCROLL)
2084 ? up_modifier
2085 : down_modifier));
2086 emacs_event->frame_or_window = bar->window;
2087 emacs_event->timestamp = msg->msg.time;
2088
2089 {
2090 int internal_height
2091 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2092 int top_range
2093 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2094 int y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
2095
2096 switch (LOWORD (msg->msg.wParam))
2097 {
2098 case SB_THUMBPOSITION:
2099 case SB_THUMBTRACK:
2100 emacs_event->part = scroll_bar_handle;
2101 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2102 y = HIWORD (msg->msg.wParam);
2103 break;
2104 case SB_LINEDOWN:
2105 emacs_event->part = scroll_bar_handle;
2106 if (y < top_range) y++;
2107 break;
2108 case SB_LINEUP:
2109 emacs_event->part = scroll_bar_handle;
2110 if (y) y--;
2111 break;
2112 case SB_PAGEUP:
2113 emacs_event->part = scroll_bar_above_handle;
2114 break;
2115 case SB_PAGEDOWN:
2116 emacs_event->part = scroll_bar_below_handle;
2117 break;
2118 case SB_TOP:
2119 emacs_event->part = scroll_bar_handle;
2120 y = 0;
2121 break;
2122 case SB_BOTTOM:
2123 emacs_event->part = scroll_bar_handle;
2124 y = top_range;
2125 break;
2126 case SB_ENDSCROLL:
2127 emacs_event->part = scroll_bar_handle;
2128 x_scroll_bar_set_handle (bar, y , y, 0);
2129 break;
2130 default:
2131 emacs_event->part = scroll_bar_handle;
2132 break;
2133 }
2134
2135 XSETINT (emacs_event->x, y);
2136 XSETINT (emacs_event->y, top_range);
2137 }
2138}
2139
2140/* Return information to the user about the current position of the mouse
2141 on the scroll bar. */
2142static void
2143x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
2144 FRAME_PTR *fp;
2145 Lisp_Object *bar_window;
2146 enum scroll_bar_part *part;
2147 Lisp_Object *x, *y;
2148 unsigned long *time;
2149{
2150 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2151 Window w = SCROLL_BAR_WIN32_WINDOW (bar);
2152 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2153 int pos;
2154
2155 BLOCK_INPUT;
2156
2157 *fp = f;
2158 *bar_window = bar->window;
2159
2160 pos = GetScrollPos (w, SB_CTL);
2161
2162 switch (LOWORD (last_mouse_scroll_bar_pos))
2163 {
2164 case SB_THUMBPOSITION:
2165 case SB_THUMBTRACK:
2166 *part = scroll_bar_handle;
2167 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2168 pos = HIWORD (last_mouse_scroll_bar_pos);
2169 break;
2170 case SB_LINEDOWN:
2171 *part = scroll_bar_handle;
2172 pos++;
2173 break;
2174 default:
2175 *part = scroll_bar_handle;
2176 break;
2177 }
2178
2179 XSETINT(*x, pos);
2180 XSETINT(*y, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)));
2181
2182 f->mouse_moved = 0;
2183 last_mouse_scroll_bar = Qnil;
2184
2185 *time = last_mouse_movement_time;
2186
2187 UNBLOCK_INPUT;
2188}
2189
2190/* The screen has been cleared so we may have changed foreground or
2191 background colors, and the scroll bars may need to be redrawn.
2192 Clear out the scroll bars, and ask for expose events, so we can
2193 redraw them. */
2194
2195x_scroll_bar_clear (f)
2196 FRAME_PTR f;
2197{
2198#if 0
2199 Lisp_Object bar;
2200
2201 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2202 bar = XSCROLL_BAR (bar)->next)
2203 UpdateWindow (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar)));
2204#endif
2205}
2206
2207
2208/* The main Win32 event-reading loop - w32_read_socket. */
2209
2210/* Timestamp of enter window event. This is only used by w32_read_socket,
2211 but we have to put it out here, since static variables within functions
2212 sometimes don't work. */
2213static Time enter_timestamp;
2214
2215/* Record the last 100 characters stored
2216 to help debug the loss-of-chars-during-GC problem. */
2217int temp_index;
2218short temp_buffer[100];
2219
2220/* Read events coming from the Win32 shell.
2221 This routine is called by the SIGIO handler.
2222 We return as soon as there are no more events to be read.
2223
2224 Events representing keys are stored in buffer BUFP,
2225 which can hold up to NUMCHARS characters.
2226 We return the number of characters stored into the buffer,
2227 thus pretending to be `read'.
2228
2229 WAITP is nonzero if we should block until input arrives.
2230 EXPECTED is nonzero if the caller knows input is available.
2231
2232 Some of these messages are reposted back to the message queue since the
2233 system calls the winproc directly in a context where we cannot return the
2234 data nor can we guarantee the state we are in. So if we dispatch them
2235 we will get into an infinite loop. To prevent this from ever happening we
2236 will set a variable to indicate we are in the read_socket call and indicate
2237 which message we are processing since the winproc gets called recursively with different
2238 messages by the system.
2239*/
2240
2241int
2242w32_read_socket (sd, bufp, numchars, waitp, expected)
2243 register int sd;
2244 register struct input_event *bufp;
2245 register int numchars;
2246 int waitp;
2247 int expected;
2248{
2249 int count = 0;
2250 int nbytes = 0;
2251 int items_pending; /* How many items are in the X queue. */
2252 Win32Msg msg;
2253 struct frame *f;
2254 int event_found = 0;
2255 int prefix;
2256 Lisp_Object part;
2257 struct win32_display_info *dpyinfo = &one_win32_display_info;
2258
2259 if (interrupt_input_blocked)
2260 {
2261 interrupt_input_pending = 1;
2262 return -1;
2263 }
2264
2265 interrupt_input_pending = 0;
2266 BLOCK_INPUT;
2267
2268 /* So people can tell when we have read the available input. */
2269 input_signal_count++;
2270
2271 if (numchars <= 0)
2272 abort (); /* Don't think this happens. */
2273
2274 while (get_next_msg (&msg, 0))
2275 {
2276 switch (msg.msg.message)
2277 {
2278 case WM_ERASEBKGND:
2279 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2280 if (f)
2281 {
2282 win32_clear_rect (f, NULL, &msg.rect);
2283 }
2284 break;
2285 case WM_PAINT:
2286 {
2287 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2288
2289 if (f)
2290 {
2291 if (f->async_visible == 0)
2292 {
2293 f->async_visible = 1;
2294 f->async_iconified = 0;
2295 SET_FRAME_GARBAGED (f);
2296 }
2297 else
2298 {
2299 dumprectangle (f,
2300 msg.rect.left,
2301 msg.rect.top,
2302 msg.rect.right-msg.rect.left+1,
2303 msg.rect.bottom-msg.rect.top+1);
2304
2305 }
2306 }
2307 }
2308
2309 break;
2310 case WM_KEYDOWN:
2311 case WM_SYSKEYDOWN:
2312 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2313
2314 if (f && !f->iconified)
2315 {
2316 if (temp_index == sizeof temp_buffer / sizeof (short))
2317 temp_index = 0;
2318 temp_buffer[temp_index++] = msg.msg.wParam;
2319 bufp->kind = non_ascii_keystroke;
2320 bufp->code = msg.msg.wParam;
2321 bufp->modifiers = msg.dwModifiers;
2322 XSETFRAME (bufp->frame_or_window, f);
2323 bufp->timestamp = msg.msg.time;
2324 bufp++;
2325 numchars--;
2326 count++;
2327 }
2328 break;
2329 case WM_SYSCHAR:
2330 case WM_CHAR:
2331 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2332
2333 if (f && !f->iconified)
2334 {
2335 if (numchars > 1)
2336 {
2337 if (temp_index == sizeof temp_buffer / sizeof (short))
2338 temp_index = 0;
2339 temp_buffer[temp_index++] = msg.msg.wParam;
2340 bufp->kind = ascii_keystroke;
2341 bufp->code = msg.msg.wParam;
2342 XSETFRAME (bufp->frame_or_window, f);
2343 bufp->modifiers = msg.dwModifiers;
2344 bufp->timestamp = msg.msg.time;
2345 bufp++;
2346 numchars--;
2347 count++;
2348 }
2349 else
2350 {
2351 abort ();
2352 }
2353 }
2354 break;
2355 case WM_MOUSEMOVE:
2356 if (dpyinfo->grabbed && last_mouse_frame
2357 && FRAME_LIVE_P (last_mouse_frame))
2358 f = last_mouse_frame;
2359 else
2360 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2361
2362 if (f)
2363 note_mouse_movement (f, &msg.msg);
2364 else
2365 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
2366
2367 break;
2368 case WM_LBUTTONDOWN:
2369 case WM_LBUTTONUP:
2370 case WM_MBUTTONDOWN:
2371 case WM_MBUTTONUP:
2372 case WM_RBUTTONDOWN:
2373 case WM_RBUTTONUP:
2374 {
2375 int button;
2376 int up;
2377
2378 if (dpyinfo->grabbed && last_mouse_frame
2379 && FRAME_LIVE_P (last_mouse_frame))
2380 f = last_mouse_frame;
2381 else
2382 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2383
2384 if (f)
2385 {
2386 if ((!dpyinfo->win32_focus_frame || f == dpyinfo->win32_focus_frame)
2387 && (numchars >= 1))
2388 {
2389 construct_mouse_click (bufp, &msg, f);
2390 bufp++;
2391 count++;
2392 numchars--;
2393 }
2394 }
2395
2396 parse_button (msg.msg.message, &button, &up);
2397
2398 if (up)
2399 {
2400 dpyinfo->grabbed &= ~ (1 << button);
2401 }
2402 else
2403 {
2404 dpyinfo->grabbed |= (1 << button);
2405 last_mouse_frame = f;
2406 }
2407 }
2408
2409 break;
2410 case WM_VSCROLL:
2411 {
2412 struct scroll_bar *bar = x_window_to_scroll_bar ((HWND)msg.msg.lParam);
2413
2414 if (bar && numchars >= 1)
2415 {
2416 x_scroll_bar_handle_click (bar, &msg, bufp);
2417 bufp++;
2418 count++;
2419 numchars--;
2420 }
2421 }
2422
2423 break;
2424 case WM_MOVE:
2425 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2426
2427 if (f && !f->async_iconified)
2428 {
2429 f->output_data.win32->left_pos = LOWORD (msg.msg.lParam);
2430 f->output_data.win32->top_pos = HIWORD (msg.msg.lParam);
2431 }
2432
2433 break;
2434 case WM_SIZE:
2435 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2436
2437 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
2438 {
2439 RECT rect;
2440 int rows;
2441 int columns;
2442 int width;
2443 int height;
2444
2445 GetClientRect(msg.msg.hwnd, &rect);
2446
2447 height = rect.bottom - rect.top + 1;
2448 width = rect.right - rect.left + 1;
2449
2450 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
2451 columns = PIXEL_TO_CHAR_WIDTH (f, width);
2452
2453 /* Even if the number of character rows and columns has
2454 not changed, the font size may have changed, so we need
2455 to check the pixel dimensions as well. */
2456
2457 if (columns != f->width
2458 || rows != f->height
2459 || width != f->output_data.win32->pixel_width
2460 || height != f->output_data.win32->pixel_height)
2461 {
2462 /* I had set this to 0, 0 - I am not sure why?? */
2463
2464 change_frame_size (f, rows, columns, 0, 1);
2465 SET_FRAME_GARBAGED (f);
2466
2467 f->output_data.win32->pixel_width = width;
2468 f->output_data.win32->pixel_height = height;
2469 f->output_data.win32->win_gravity = NorthWestGravity;
2470 }
2471 }
2472
2473 break;
2474 case WM_SETFOCUS:
2475 case WM_KILLFOCUS:
2476 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2477
2478 if (msg.msg.message == WM_SETFOCUS)
2479 {
2480 x_new_focus_frame (dpyinfo, f);
2481 }
2482 else if (f == dpyinfo->win32_focus_frame)
2483 x_new_focus_frame (dpyinfo, 0);
2484
2485 break;
2486 case WM_SYSCOMMAND:
2487 switch (msg.msg.wParam)
2488 {
2489 case SC_CLOSE:
2490 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2491
2492 if (f)
2493 {
2494 if (numchars == 0)
2495 abort ();
2496
2497 bufp->kind = delete_window_event;
2498 XSETFRAME (bufp->frame_or_window, f);
2499 bufp++;
2500 count++;
2501 numchars--;
2502 }
2503
2504 break;
2505 case SC_MINIMIZE:
2506 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2507
2508 if (f)
2509 {
2510 f->async_visible = 1;
2511 f->async_iconified = 1;
2512
2513 bufp->kind = iconify_event;
2514 XSETFRAME (bufp->frame_or_window, f);
2515 bufp++;
2516 count++;
2517 numchars--;
2518 }
2519
2520 break;
2521 case SC_MAXIMIZE:
2522 case SC_RESTORE:
2523 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2524
2525 if (f)
2526 {
2527 f->async_visible = 1;
2528 f->async_iconified = 0;
2529
2530 /* wait_reading_process_input will notice this and update
2531 the frame's display structures. */
2532 SET_FRAME_GARBAGED (f);
2533
2534 if (f->iconified)
2535 {
2536 bufp->kind = deiconify_event;
2537 XSETFRAME (bufp->frame_or_window, f);
2538 bufp++;
2539 count++;
2540 numchars--;
2541 }
2542 else
2543 /* Force a redisplay sooner or later
2544 to update the frame titles
2545 in case this is the second frame. */
2546 record_asynch_buffer_change ();
2547 }
2548
2549 break;
2550 }
2551
2552 break;
2553 case WM_CLOSE:
2554 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2555
2556 if (f)
2557 {
2558 if (numchars == 0)
2559 abort ();
2560
2561 bufp->kind = delete_window_event;
2562 XSETFRAME (bufp->frame_or_window, f);
2563 bufp++;
2564 count++;
2565 numchars--;
2566 }
2567
2568 break;
2569 case WM_COMMAND:
2570 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2571
2572 if (f)
2573 {
2574 if (msg.msg.lParam == 0)
2575 {
2576 /* Came from window menu */
2577
2578 extern Lisp_Object get_frame_menubar_event ();
2579 Lisp_Object event = get_frame_menubar_event (f, msg.msg.wParam);
2580 struct input_event buf;
2581 Lisp_Object frame;
2582
2583 XSETFRAME (frame, f);
2584 buf.kind = menu_bar_event;
2585
2586 /* Store initial menu bar event */
2587
2588 if (!NILP (event))
2589 {
2590 buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
2591 kbd_buffer_store_event (&buf);
2592 }
2593
2594 /* Enqueue the events */
2595
2596 while (!NILP (event))
2597 {
2598 buf.frame_or_window = Fcons (frame, XCONS (event)->car);
2599 kbd_buffer_store_event (&buf);
2600 event = XCONS (event)->cdr;
2601 }
2602 }
2603 else
2604 {
2605 /* Came from popup menu */
2606 }
2607 }
2608 break;
2609 }
2610 }
2611
2612 /* If the focus was just given to an autoraising frame,
2613 raise it now. */
2614 /* ??? This ought to be able to handle more than one such frame. */
2615 if (pending_autoraise_frame)
2616 {
2617 x_raise_frame (pending_autoraise_frame);
2618 pending_autoraise_frame = 0;
2619 }
2620
2621 UNBLOCK_INPUT;
2622 return count;
2623}
2624
2625/* Drawing the cursor. */
2626
2627
2628/* Draw a hollow box cursor. Don't change the inside of the box. */
2629
2630static void
2631x_draw_box (f)
2632 struct frame *f;
2633{
2634 RECT rect;
2635 HBRUSH hb;
2636 HDC hdc;
2637
2638 hdc = my_get_dc (FRAME_WIN32_WINDOW (f));
2639
2640 hb = CreateSolidBrush (f->output_data.win32->cursor_pixel);
2641
2642 rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
2643 rect.top = CHAR_TO_PIXEL_ROW (f, curs_y);
2644 rect.right = rect.left + FONT_WIDTH (f->output_data.win32->font) - 1;
2645 rect.bottom = rect.top + f->output_data.win32->line_height - 1;
2646
2647 /* rect.left++; */
2648 /* rect.top++; */
2649 rect.right--;
2650 rect.bottom--;
2651
2652 FrameRect (hdc, &rect, hb);
2653
2654 DeleteObject (hb);
2655
2656 ReleaseDC (FRAME_WIN32_WINDOW (f), hdc);
2657}
2658
2659/* Clear the cursor of frame F to background color,
2660 and mark the cursor as not shown.
2661 This is used when the text where the cursor is
2662 is about to be rewritten. */
2663
2664static void
2665clear_cursor (f)
2666 struct frame *f;
2667{
2668 if (! FRAME_VISIBLE_P (f)
2669 || f->phys_cursor_x < 0)
2670 return;
2671
2672 x_display_cursor (f, 0);
2673 f->phys_cursor_x = -1;
2674}
2675
2676/* Redraw the glyph at ROW, COLUMN on frame F, in the style
2677 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2678 glyph drawn. */
2679
2680static void
2681x_draw_single_glyph (f, row, column, glyph, highlight)
2682 struct frame *f;
2683 int row, column;
2684 GLYPH glyph;
2685 int highlight;
2686{
2687 dumpglyphs (f,
2688 CHAR_TO_PIXEL_COL (f, column),
2689 CHAR_TO_PIXEL_ROW (f, row),
2690 &glyph, 1, highlight, 0);
2691}
2692
2693static void
2694x_display_bar_cursor (f, on)
2695 struct frame *f;
2696 int on;
2697{
2698 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2699
2700 /* This is pointless on invisible frames, and dangerous on garbaged
2701 frames; in the latter case, the frame may be in the midst of
2702 changing its size, and curs_x and curs_y may be off the frame. */
2703 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
2704 return;
2705
2706 if (! on && f->phys_cursor_x < 0)
2707 return;
2708
2709 /* If we're not updating, then we want to use the current frame's
2710 cursor position, not our local idea of where the cursor ought to be. */
2711 if (f != updating_frame)
2712 {
2713 curs_x = FRAME_CURSOR_X (f);
2714 curs_y = FRAME_CURSOR_Y (f);
2715 }
2716
2717 /* If there is anything wrong with the current cursor state, remove it. */
2718 if (f->phys_cursor_x >= 0
2719 && (!on
2720 || f->phys_cursor_x != curs_x
2721 || f->phys_cursor_y != curs_y
2722 || f->output_data.win32->current_cursor != bar_cursor))
2723 {
2724 /* Erase the cursor by redrawing the character underneath it. */
2725 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2726 f->phys_cursor_glyph,
2727 current_glyphs->highlight[f->phys_cursor_y]);
2728 f->phys_cursor_x = -1;
2729 }
2730
2731 /* If we now need a cursor in the new place or in the new form, do it so. */
2732 if (on
2733 && (f->phys_cursor_x < 0
2734 || (f->output_data.win32->current_cursor != bar_cursor)))
2735 {
2736 f->phys_cursor_glyph
2737 = ((current_glyphs->enable[curs_y]
2738 && curs_x < current_glyphs->used[curs_y])
2739 ? current_glyphs->glyphs[curs_y][curs_x]
2740 : SPACEGLYPH);
2741 win32_fill_area (f, NULL, f->output_data.win32->cursor_pixel,
2742 CHAR_TO_PIXEL_COL (f, curs_x),
2743 CHAR_TO_PIXEL_ROW (f, curs_y),
2744 max (f->output_data.win32->cursor_width, 1),
2745 f->output_data.win32->line_height);
2746
2747 f->phys_cursor_x = curs_x;
2748 f->phys_cursor_y = curs_y;
2749
2750 f->output_data.win32->current_cursor = bar_cursor;
2751 }
2752}
2753
2754
2755/* Turn the displayed cursor of frame F on or off according to ON.
2756 If ON is nonzero, where to put the cursor is specified
2757 by F->cursor_x and F->cursor_y. */
2758
2759static void
2760x_display_box_cursor (f, on)
2761 struct frame *f;
2762 int on;
2763{
2764 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2765
2766 /* This is pointless on invisible frames, and dangerous on garbaged
2767 frames; in the latter case, the frame may be in the midst of
2768 changing its size, and curs_x and curs_y may be off the frame. */
2769 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
2770 return;
2771
2772 /* If cursor is off and we want it off, return quickly. */
2773 if (!on && f->phys_cursor_x < 0)
2774 return;
2775
2776 /* If we're not updating, then we want to use the current frame's
2777 cursor position, not our local idea of where the cursor ought to be. */
2778 if (f != updating_frame)
2779 {
2780 curs_x = FRAME_CURSOR_X (f);
2781 curs_y = FRAME_CURSOR_Y (f);
2782 }
2783
2784 /* If cursor is currently being shown and we don't want it to be
2785 or it is in the wrong place,
2786 or we want a hollow box and it's not so, (pout!)
2787 erase it. */
2788 if (f->phys_cursor_x >= 0
2789 && (!on
2790 || f->phys_cursor_x != curs_x
2791 || f->phys_cursor_y != curs_y
2792 || (f->output_data.win32->current_cursor != hollow_box_cursor
2793 && (f != FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame))))
2794 {
2795 int mouse_face_here = 0;
2796 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
2797
2798 /* If the cursor is in the mouse face area, redisplay that when
2799 we clear the cursor. */
2800 if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame
2801 &&
2802 (f->phys_cursor_y > FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
2803 || (f->phys_cursor_y == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
2804 && f->phys_cursor_x >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col))
2805 &&
2806 (f->phys_cursor_y < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
2807 || (f->phys_cursor_y == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
2808 && f->phys_cursor_x < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col))
2809 /* Don't redraw the cursor's spot in mouse face
2810 if it is at the end of a line (on a newline).
2811 The cursor appears there, but mouse highlighting does not. */
2812 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
2813 mouse_face_here = 1;
2814
2815 /* If the font is not as tall as a whole line,
2816 we must explicitly clear the line's whole height. */
2817 if (FONT_HEIGHT (f->output_data.win32->font) != f->output_data.win32->line_height)
2818 win32_clear_area (f, NULL,
2819 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
2820 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
2821 FONT_WIDTH (f->output_data.win32->font),
2822 f->output_data.win32->line_height);
2823 /* Erase the cursor by redrawing the character underneath it. */
2824 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2825 f->phys_cursor_glyph,
2826 (mouse_face_here
2827 ? 3
2828 : current_glyphs->highlight[f->phys_cursor_y]));
2829 f->phys_cursor_x = -1;
2830 }
2831
2832 /* If we want to show a cursor,
2833 or we want a box cursor and it's not so,
2834 write it in the right place. */
2835 if (on
2836 && (f->phys_cursor_x < 0
2837 || (f->output_data.win32->current_cursor != filled_box_cursor
2838 && f == FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame)))
2839 {
2840 f->phys_cursor_glyph
2841 = ((current_glyphs->enable[curs_y]
2842 && curs_x < current_glyphs->used[curs_y])
2843 ? current_glyphs->glyphs[curs_y][curs_x]
2844 : SPACEGLYPH);
2845 if (f != FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame)
2846 {
2847 x_draw_box (f);
2848 f->output_data.win32->current_cursor = hollow_box_cursor;
2849 }
2850 else
2851 {
2852 x_draw_single_glyph (f, curs_y, curs_x,
2853 f->phys_cursor_glyph, 2);
2854 f->output_data.win32->current_cursor = filled_box_cursor;
2855 }
2856
2857 f->phys_cursor_x = curs_x;
2858 f->phys_cursor_y = curs_y;
2859 }
2860}
2861
2862x_display_cursor (f, on)
2863 struct frame *f;
2864 int on;
2865{
2866 BLOCK_INPUT;
2867
2868 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
2869 x_display_box_cursor (f, on);
2870 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
2871 x_display_bar_cursor (f, on);
2872 else
2873 /* Those are the only two we have implemented! */
2874 abort ();
2875
2876 UNBLOCK_INPUT;
2877}
2878
2879/* Changing the font of the frame. */
2880
2881/* Give frame F the font named FONTNAME as its default font, and
2882 return the full name of that font. FONTNAME may be a wildcard
2883 pattern; in that case, we choose some font that fits the pattern.
2884 The return value shows which font we chose. */
2885
2886Lisp_Object
2887x_new_font (f, fontname)
2888 struct frame *f;
2889 register char *fontname;
2890{
2891 int already_loaded;
2892 int n_matching_fonts;
2893 XFontStruct *font_info;
2894 char new_font_name[101];
2895
2896 /* Get a font which matches this name */
2897 {
2898 LOGFONT lf;
2899
2900 if (!x_to_win32_font(fontname, &lf)
2901 || !win32_to_x_font(&lf, new_font_name, 100))
2902 {
2903 return Qnil;
2904 }
2905 }
2906
2907 /* See if we've already loaded a matching font. */
2908 already_loaded = -1;
2909
2910 {
2911 int i;
2912
2913 for (i = 0; i < FRAME_WIN32_DISPLAY_INFO (f)->n_fonts; i++)
2914 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
2915 {
2916 already_loaded = i;
2917 fontname = FRAME_WIN32_DISPLAY_INFO (f)->font_table[i].name;
2918 break;
2919 }
2920 }
2921
2922 /* If we have, just return it from the table. */
2923 if (already_loaded >= 0)
2924 f->output_data.win32->font = FRAME_WIN32_DISPLAY_INFO (f)->font_table[already_loaded].font;
2925 /* Otherwise, load the font and add it to the table. */
2926 else
2927 {
2928 XFontStruct *font;
2929 int n_fonts;
2930
2931 font = win32_load_font(FRAME_WIN32_DISPLAY_INFO (f), fontname);
2932
2933 if (! font)
2934 {
2935 return Qnil;
2936 }
2937
2938 /* Do we need to create the table? */
2939 if (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size == 0)
2940 {
2941 FRAME_WIN32_DISPLAY_INFO (f)->font_table_size = 16;
2942 FRAME_WIN32_DISPLAY_INFO (f)->font_table
2943 = (struct font_info *) xmalloc (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size
2944 * sizeof (struct font_info));
2945 }
2946 /* Do we need to grow the table? */
2947 else if (FRAME_WIN32_DISPLAY_INFO (f)->n_fonts
2948 >= FRAME_WIN32_DISPLAY_INFO (f)->font_table_size)
2949 {
2950 FRAME_WIN32_DISPLAY_INFO (f)->font_table_size *= 2;
2951 FRAME_WIN32_DISPLAY_INFO (f)->font_table
2952 = (struct font_info *) xrealloc (FRAME_WIN32_DISPLAY_INFO (f)->font_table,
2953 (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size
2954 * sizeof (struct font_info)));
2955 }
2956
2957 n_fonts = FRAME_WIN32_DISPLAY_INFO (f)->n_fonts;
2958 FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
2959 bcopy (fontname, FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
2960 f->output_data.win32->font = FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
2961 FRAME_WIN32_DISPLAY_INFO (f)->n_fonts++;
2962 }
2963
2964 /* Compute the scroll bar width in character columns. */
2965 if (f->scroll_bar_pixel_width > 0)
2966 {
2967 int wid = FONT_WIDTH (f->output_data.win32->font);
2968 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
2969 }
2970 else
2971 f->scroll_bar_cols = 2;
2972
2973 /* Now make the frame display the given font. */
2974 if (FRAME_WIN32_WINDOW (f) != 0)
2975 {
2976 frame_update_line_height (f);
2977 x_set_window_size (f, 0, f->width, f->height);
2978 }
2979 else
2980 /* If we are setting a new frame's font for the first time,
2981 there are no faces yet, so this font's height is the line height. */
2982 f->output_data.win32->line_height = FONT_HEIGHT (f->output_data.win32->font);
2983
2984 {
2985 Lisp_Object lispy_name;
2986
2987 lispy_name = build_string (fontname);
2988
2989 return lispy_name;
2990 }
2991}
2992
2993x_calc_absolute_position (f)
2994 struct frame *f;
2995{
2996 Window win, child;
2997 POINT pt;
2998 int flags = f->output_data.win32->size_hint_flags;
2999
3000 pt.x = pt.y = 0;
3001
3002 /* Find the position of the outside upper-left corner of
3003 the inner window, with respect to the outer window. */
3004 if (f->output_data.win32->parent_desc != FRAME_WIN32_DISPLAY_INFO (f)->root_window)
3005 {
3006 BLOCK_INPUT;
3007 MapWindowPoints (FRAME_WIN32_WINDOW (f),
3008 f->output_data.win32->parent_desc,
3009 &pt, 1);
3010 UNBLOCK_INPUT;
3011 }
3012
3013 {
3014 RECT rt;
3015 rt.left = rt.right = rt.top = rt.bottom = 0;
3016
3017 BLOCK_INPUT;
3018 AdjustWindowRect(&rt, f->output_data.win32->dwStyle,
3019 FRAME_EXTERNAL_MENU_BAR (f));
3020 UNBLOCK_INPUT;
3021
3022 pt.x += (rt.right - rt.left);
3023 pt.y += (rt.bottom - rt.top);
3024 }
3025
3026 /* Treat negative positions as relative to the leftmost bottommost
3027 position that fits on the screen. */
3028 if (flags & XNegative)
3029 f->output_data.win32->left_pos = (FRAME_WIN32_DISPLAY_INFO (f)->width
3030 - 2 * f->output_data.win32->border_width - pt.x
3031 - PIXEL_WIDTH (f)
3032 + f->output_data.win32->left_pos);
3033
3034 if (flags & YNegative)
3035 f->output_data.win32->top_pos = (FRAME_WIN32_DISPLAY_INFO (f)->height
3036 - 2 * f->output_data.win32->border_width - pt.y
3037 - PIXEL_HEIGHT (f)
3038 + f->output_data.win32->top_pos);
3039 /* The left_pos and top_pos
3040 are now relative to the top and left screen edges,
3041 so the flags should correspond. */
3042 f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
3043}
3044
3045/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3046 to really change the position, and 0 when calling from
3047 x_make_frame_visible (in that case, XOFF and YOFF are the current
3048 position values). It is -1 when calling from x_set_frame_parameters,
3049 which means, do adjust for borders but don't change the gravity. */
3050
3051x_set_offset (f, xoff, yoff, change_gravity)
3052 struct frame *f;
3053 register int xoff, yoff;
3054 int change_gravity;
3055{
3056 int modified_top, modified_left;
3057
3058 if (change_gravity > 0)
3059 {
3060 f->output_data.win32->top_pos = yoff;
3061 f->output_data.win32->left_pos = xoff;
3062 f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
3063 if (xoff < 0)
3064 f->output_data.win32->size_hint_flags |= XNegative;
3065 if (yoff < 0)
3066 f->output_data.win32->size_hint_flags |= YNegative;
3067 f->output_data.win32->win_gravity = NorthWestGravity;
3068 }
3069 x_calc_absolute_position (f);
3070
3071 BLOCK_INPUT;
3072 x_wm_set_size_hint (f, (long) 0, 0);
3073
3074 /* It is a mystery why we need to add the border_width here
3075 when the frame is already visible, but experiment says we do. */
3076 modified_left = f->output_data.win32->left_pos;
3077 modified_top = f->output_data.win32->top_pos;
3078 if (change_gravity != 0)
3079 {
3080 modified_left += f->output_data.win32->border_width;
3081 modified_top += f->output_data.win32->border_width;
3082 }
3083
3084 SetWindowPos (FRAME_WIN32_WINDOW (f),
3085 NULL,
3086 modified_left, modified_top,
3087 0,0,
3088 SWP_NOZORDER | SWP_NOSIZE);
3089 UNBLOCK_INPUT;
3090}
3091
3092/* Call this to change the size of frame F's x-window.
3093 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3094 for this size change and subsequent size changes.
3095 Otherwise we leave the window gravity unchanged. */
3096
3097x_set_window_size (f, change_gravity, cols, rows)
3098 struct frame *f;
3099 int change_gravity;
3100 int cols, rows;
3101{
3102 int pixelwidth, pixelheight;
3103
3104 BLOCK_INPUT;
3105
3106 check_frame_size (f, &rows, &cols);
3107 f->output_data.win32->vertical_scroll_bar_extra
3108 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3109 ? 0
3110 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3111 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3112 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
3113 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
3114 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
3115
3116 f->output_data.win32->win_gravity = NorthWestGravity;
3117 x_wm_set_size_hint (f, (long) 0, 0);
3118
3119 {
3120 RECT rect;
3121
3122 rect.left = rect.top = 0;
3123 rect.right = pixelwidth;
3124 rect.bottom = pixelheight;
3125
3126 AdjustWindowRect(&rect, f->output_data.win32->dwStyle,
3127 FRAME_EXTERNAL_MENU_BAR (f));
3128
3129 /* All windows have an extra pixel */
3130
3131 SetWindowPos (FRAME_WIN32_WINDOW (f),
3132 NULL,
3133 0, 0,
3134 rect.right - rect.left + 1,
3135 rect.bottom - rect.top + 1,
3136 SWP_NOZORDER | SWP_NOMOVE);
3137 }
3138
3139 /* Now, strictly speaking, we can't be sure that this is accurate,
3140 but the window manager will get around to dealing with the size
3141 change request eventually, and we'll hear how it went when the
3142 ConfigureNotify event gets here.
3143
3144 We could just not bother storing any of this information here,
3145 and let the ConfigureNotify event set everything up, but that
3146 might be kind of confusing to the lisp code, since size changes
3147 wouldn't be reported in the frame parameters until some random
3148 point in the future when the ConfigureNotify event arrives. */
3149 change_frame_size (f, rows, cols, 0, 0);
3150 PIXEL_WIDTH (f) = pixelwidth;
3151 PIXEL_HEIGHT (f) = pixelheight;
3152
3153 /* If cursor was outside the new size, mark it as off. */
3154 if (f->phys_cursor_y >= rows
3155 || f->phys_cursor_x >= cols)
3156 {
3157 f->phys_cursor_x = -1;
3158 f->phys_cursor_y = -1;
3159 }
3160
3161 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3162 receive in the ConfigureNotify event; if we get what we asked
3163 for, then the event won't cause the screen to become garbaged, so
3164 we have to make sure to do it here. */
3165 SET_FRAME_GARBAGED (f);
3166
3167 UNBLOCK_INPUT;
3168}
3169
3170/* Mouse warping. */
3171
3172void
3173x_set_mouse_position (f, x, y)
3174 struct frame *f;
3175 int x, y;
3176{
3177 int pix_x, pix_y;
3178
3179 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.win32->font) / 2;
3180 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.win32->line_height / 2;
3181
3182 if (pix_x < 0) pix_x = 0;
3183 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
3184
3185 if (pix_y < 0) pix_y = 0;
3186 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
3187
3188 BLOCK_INPUT;
3189
3190 SetCursorPos (pix_x, pix_y);
3191
3192 UNBLOCK_INPUT;
3193}
3194
3195/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
3196
3197void
3198x_set_mouse_pixel_position (f, pix_x, pix_y)
3199 struct frame *f;
3200 int pix_x, pix_y;
3201{
3202 BLOCK_INPUT;
3203
3204 SetCursorPos (pix_x, pix_y);
3205
3206 UNBLOCK_INPUT;
3207}
3208
3209/* focus shifting, raising and lowering. */
3210
3211x_focus_on_frame (f)
3212 struct frame *f;
3213{
3214}
3215
3216x_unfocus_frame (f)
3217 struct frame *f;
3218{
3219}
3220
3221/* Raise frame F. */
3222
3223x_raise_frame (f)
3224 struct frame *f;
3225{
3226 if (f->async_visible)
3227 {
3228 BLOCK_INPUT;
3229 SetWindowPos (FRAME_WIN32_WINDOW (f),
3230 HWND_TOP,
3231 0, 0, 0, 0,
3232 SWP_NOSIZE | SWP_NOMOVE);
3233 UNBLOCK_INPUT;
3234 }
3235}
3236
3237/* Lower frame F. */
3238
3239x_lower_frame (f)
3240 struct frame *f;
3241{
3242 if (f->async_visible)
3243 {
3244 BLOCK_INPUT;
3245 SetWindowPos (FRAME_WIN32_WINDOW (f),
3246 HWND_BOTTOM,
3247 0, 0, 0, 0,
3248 SWP_NOSIZE | SWP_NOMOVE);
3249 UNBLOCK_INPUT;
3250 }
3251}
3252
3253static void
3254win32_frame_raise_lower (f, raise)
3255 FRAME_PTR f;
3256 int raise;
3257{
3258 if (raise)
3259 x_raise_frame (f);
3260 else
3261 x_lower_frame (f);
3262}
3263
3264/* Change of visibility. */
3265
3266/* This tries to wait until the frame is really visible.
3267 However, if the window manager asks the user where to position
3268 the frame, this will return before the user finishes doing that.
3269 The frame will not actually be visible at that time,
3270 but it will become visible later when the window manager
3271 finishes with it. */
3272
3273x_make_frame_visible (f)
3274 struct frame *f;
3275{
3276 BLOCK_INPUT;
3277
3278 if (! FRAME_VISIBLE_P (f))
3279 {
3280 /* We test FRAME_GARBAGED_P here to make sure we don't
3281 call x_set_offset a second time
3282 if we get to x_make_frame_visible a second time
3283 before the window gets really visible. */
3284 if (! FRAME_ICONIFIED_P (f)
3285 && ! f->output_data.win32->asked_for_visible)
3286 x_set_offset (f, f->output_data.win32->left_pos, f->output_data.win32->top_pos, 0);
3287
3288 f->output_data.win32->asked_for_visible = 1;
3289
3290 ShowWindow (FRAME_WIN32_WINDOW (f), SW_SHOW);
3291 }
3292
3293 /* Synchronize to ensure Emacs knows the frame is visible
3294 before we do anything else. We do this loop with input not blocked
3295 so that incoming events are handled. */
3296 {
3297 Lisp_Object frame;
3298 int count = input_signal_count;
3299
3300 /* This must come after we set COUNT. */
3301 UNBLOCK_INPUT;
3302
3303 XSETFRAME (frame, f);
3304
3305 while (1)
3306 {
3307 /* Once we have handled input events,
3308 we should have received the MapNotify if one is coming.
3309 So if we have not got it yet, stop looping.
3310 Some window managers make their own decisions
3311 about visibility. */
3312 if (input_signal_count != count)
3313 break;
3314 /* Machines that do polling rather than SIGIO have been observed
3315 to go into a busy-wait here. So we'll fake an alarm signal
3316 to let the handler know that there's something to be read.
3317 We used to raise a real alarm, but it seems that the handler
3318 isn't always enabled here. This is probably a bug. */
3319 if (input_polling_used ())
3320 {
3321 /* It could be confusing if a real alarm arrives while processing
3322 the fake one. Turn it off and let the handler reset it. */
3323 alarm (0);
3324 input_poll_signal ();
3325 }
3326 /* Once we have handled input events,
3327 we should have received the MapNotify if one is coming.
3328 So if we have not got it yet, stop looping.
3329 Some window managers make their own decisions
3330 about visibility. */
3331 if (input_signal_count != count)
3332 break;
3333 }
3334 FRAME_SAMPLE_VISIBILITY (f);
3335 }
3336}
3337
3338/* Change from mapped state to withdrawn state. */
3339
3340/* Make the frame visible (mapped and not iconified). */
3341
3342x_make_frame_invisible (f)
3343 struct frame *f;
3344{
3345 Window window;
3346
3347 /* Don't keep the highlight on an invisible frame. */
3348 if (FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame == f)
3349 FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame = 0;
3350
3351 BLOCK_INPUT;
3352
3353 ShowWindow (FRAME_WIN32_WINDOW (f), SW_HIDE);
3354
3355 /* We can't distinguish this from iconification
3356 just by the event that we get from the server.
3357 So we can't win using the usual strategy of letting
3358 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3359 and synchronize with the server to make sure we agree. */
3360 f->visible = 0;
3361 FRAME_ICONIFIED_P (f) = 0;
3362 f->async_visible = 0;
3363 f->async_iconified = 0;
3364
3365 UNBLOCK_INPUT;
3366}
3367
3368/* Change window state from mapped to iconified. */
3369
3370void x_iconify_frame (f)
3371 struct frame *f;
3372{
3373 int result;
3374
3375 /* Don't keep the highlight on an invisible frame. */
3376 if (FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame == f)
3377 FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame = 0;
3378
3379 if (f->async_iconified)
3380 return;
3381
3382 BLOCK_INPUT;
3383
3384 ShowWindow (FRAME_WIN32_WINDOW (f), SW_SHOWMINIMIZED);
3385
3386 f->async_iconified = 1;
3387
3388 UNBLOCK_INPUT;
3389}
3390
3391/* Destroy the window of frame F. */
3392
3393x_destroy_window (f)
3394 struct frame *f;
3395{
3396 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
3397
3398 BLOCK_INPUT;
3399
3400 my_destroy_window (f, FRAME_WIN32_WINDOW (f));
3401 free_frame_menubar (f);
3402 free_frame_faces (f);
3403
3404 xfree (f->output_data.win32);
3405 f->output_data.win32 = 0;
3406 if (f == dpyinfo->win32_focus_frame)
3407 dpyinfo->win32_focus_frame = 0;
3408 if (f == dpyinfo->win32_focus_event_frame)
3409 dpyinfo->win32_focus_event_frame = 0;
3410 if (f == dpyinfo->win32_highlight_frame)
3411 dpyinfo->win32_highlight_frame = 0;
3412
3413 dpyinfo->reference_count--;
3414
3415 if (f == dpyinfo->mouse_face_mouse_frame)
3416 {
3417 dpyinfo->mouse_face_beg_row
3418 = dpyinfo->mouse_face_beg_col = -1;
3419 dpyinfo->mouse_face_end_row
3420 = dpyinfo->mouse_face_end_col = -1;
3421 dpyinfo->mouse_face_window = Qnil;
3422 }
3423
3424 UNBLOCK_INPUT;
3425}
3426
3427/* Setting window manager hints. */
3428
3429/* Set the normal size hints for the window manager, for frame F.
3430 FLAGS is the flags word to use--or 0 meaning preserve the flags
3431 that the window now has.
3432 If USER_POSITION is nonzero, we set the USPosition
3433 flag (this is useful when FLAGS is 0). */
3434
3435x_wm_set_size_hint (f, flags, user_position)
3436 struct frame *f;
3437 long flags;
3438 int user_position;
3439{
3440 Window window = FRAME_WIN32_WINDOW (f);
3441
3442 flexlines = f->height;
3443
3444 enter_crit ();
3445
3446 SetWindowLong (window, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.win32->font));
3447 SetWindowLong (window, WND_Y_UNITS_INDEX, f->output_data.win32->line_height);
3448
3449 leave_crit ();
3450}
3451
3452/* Window manager things */
3453x_wm_set_icon_position (f, icon_x, icon_y)
3454 struct frame *f;
3455 int icon_x, icon_y;
3456{
3457#if 0
3458 Window window = FRAME_WIN32_WINDOW (f);
3459
3460 f->display.x->wm_hints.flags |= IconPositionHint;
3461 f->display.x->wm_hints.icon_x = icon_x;
3462 f->display.x->wm_hints.icon_y = icon_y;
3463
3464 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
3465#endif
3466}
3467
3468
3469/* Initialization. */
3470
3471#ifdef USE_X_TOOLKIT
3472static XrmOptionDescRec emacs_options[] = {
3473 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
3474 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
3475
3476 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3477 XrmoptionSepArg, NULL},
3478 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
3479
3480 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3481 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3482 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3483 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
3484 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
3485 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
3486 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
3487};
3488#endif /* USE_X_TOOLKIT */
3489
3490static int win32_initialized = 0;
3491
3492struct win32_display_info *
3493win32_term_init (display_name, xrm_option, resource_name)
3494 Lisp_Object display_name;
3495 char *xrm_option;
3496 char *resource_name;
3497{
3498 Lisp_Object frame;
3499 char *defaultvalue;
3500 struct win32_display_info *dpyinfo;
3501 HDC hdc;
3502
3503 BLOCK_INPUT;
3504
3505 if (!win32_initialized)
3506 {
3507 win32_initialize ();
3508 win32_initialized = 1;
3509 }
3510
3511 {
3512 int argc = 0;
3513 char *argv[3];
3514
3515 argv[0] = "";
3516 argc = 1;
3517 if (xrm_option)
3518 {
3519 argv[argc++] = "-xrm";
3520 argv[argc++] = xrm_option;
3521 }
3522 }
3523
3524 dpyinfo = &one_win32_display_info;
3525
3526 /* Put this display on the chain. */
3527 dpyinfo->next = NULL;
3528
3529 /* Put it on win32_display_name_list as well, to keep them parallel. */
3530 win32_display_name_list = Fcons (Fcons (display_name, Qnil),
3531 win32_display_name_list);
3532 dpyinfo->name_list_element = XCONS (win32_display_name_list)->car;
3533
3534 dpyinfo->win32_id_name
3535 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
3536 + XSTRING (Vsystem_name)->size
3537 + 2);
3538 sprintf (dpyinfo->win32_id_name, "%s@%s",
3539 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
3540
3541#if 0
3542 xrdb = x_load_resources (dpyinfo->display, xrm_option,
3543 resource_name, EMACS_CLASS);
3544
3545 /* Put the rdb where we can find it in a way that works on
3546 all versions. */
3547 dpyinfo->xrdb = xrdb;
3548#endif
3549 hdc = my_get_dc (GetDesktopWindow ());
3550
3551 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
3552 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
3553 dpyinfo->root_window = GetDesktopWindow ();
3554 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
3555 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
3556 dpyinfo->height_in = GetDeviceCaps (hdc, LOGPIXELSX);
3557 dpyinfo->width_in = GetDeviceCaps (hdc, LOGPIXELSY);
3558 dpyinfo->grabbed = 0;
3559 dpyinfo->reference_count = 0;
3560 dpyinfo->n_fonts = 0;
3561 dpyinfo->font_table_size = 0;
3562 dpyinfo->bitmaps = 0;
3563 dpyinfo->bitmaps_size = 0;
3564 dpyinfo->bitmaps_last = 0;
3565 dpyinfo->mouse_face_mouse_frame = 0;
3566 dpyinfo->mouse_face_deferred_gc = 0;
3567 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
3568 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
3569 dpyinfo->mouse_face_face_id = 0;
3570 dpyinfo->mouse_face_window = Qnil;
3571 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
3572 dpyinfo->mouse_face_defer = 0;
3573 dpyinfo->win32_focus_frame = 0;
3574 dpyinfo->win32_focus_event_frame = 0;
3575 dpyinfo->win32_highlight_frame = 0;
3576
3577 ReleaseDC (GetDesktopWindow (), hdc);
3578
3579#ifndef F_SETOWN_BUG
3580#ifdef F_SETOWN
3581#ifdef F_SETOWN_SOCK_NEG
3582 /* stdin is a socket here */
3583 fcntl (connection, F_SETOWN, -getpid ());
3584#else /* ! defined (F_SETOWN_SOCK_NEG) */
3585 fcntl (connection, F_SETOWN, getpid ());
3586#endif /* ! defined (F_SETOWN_SOCK_NEG) */
3587#endif /* ! defined (F_SETOWN) */
3588#endif /* F_SETOWN_BUG */
3589
3590#ifdef SIGIO
3591 if (interrupt_input)
3592 init_sigio (connection);
3593#endif /* ! defined (SIGIO) */
3594
3595 UNBLOCK_INPUT;
3596
3597 return dpyinfo;
3598}
3599
3600/* Get rid of display DPYINFO, assuming all frames are already gone. */
3601
3602void
3603x_delete_display (dpyinfo)
3604 struct win32_display_info *dpyinfo;
3605{
3606 /* Discard this display from win32_display_name_list and win32_display_list.
3607 We can't use Fdelq because that can quit. */
3608 if (! NILP (win32_display_name_list)
3609 && EQ (XCONS (win32_display_name_list)->car, dpyinfo->name_list_element))
3610 win32_display_name_list = XCONS (win32_display_name_list)->cdr;
3611 else
3612 {
3613 Lisp_Object tail;
3614
3615 tail = win32_display_name_list;
3616 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
3617 {
3618 if (EQ (XCONS (XCONS (tail)->cdr)->car,
3619 dpyinfo->name_list_element))
3620 {
3621 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
3622 break;
3623 }
3624 tail = XCONS (tail)->cdr;
3625 }
3626 }
3627
3628 xfree (dpyinfo->font_table);
3629 xfree (dpyinfo->win32_id_name);
3630}
3631
3632/* Set up use of Win32. */
3633
3634DWORD win_msg_worker ();
3635
3636win32_initialize ()
3637{
3638 clear_frame_hook = win32_clear_frame;
3639 clear_end_of_line_hook = win32_clear_end_of_line;
3640 ins_del_lines_hook = win32_ins_del_lines;
3641 change_line_highlight_hook = win32_change_line_highlight;
3642 insert_glyphs_hook = win32_insert_glyphs;
3643 write_glyphs_hook = win32_write_glyphs;
3644 delete_glyphs_hook = win32_delete_glyphs;
3645 ring_bell_hook = win32_ring_bell;
3646 reset_terminal_modes_hook = win32_reset_terminal_modes;
3647 set_terminal_modes_hook = win32_set_terminal_modes;
3648 update_begin_hook = win32_update_begin;
3649 update_end_hook = win32_update_end;
3650 set_terminal_window_hook = win32_set_terminal_window;
3651 read_socket_hook = w32_read_socket;
3652 frame_up_to_date_hook = win32_frame_up_to_date;
3653 cursor_to_hook = win32_cursor_to;
3654 reassert_line_highlight_hook = win32_reassert_line_highlight;
3655 mouse_position_hook = win32_mouse_position;
3656 frame_rehighlight_hook = win32_frame_rehighlight;
3657 frame_raise_lower_hook = win32_frame_raise_lower;
3658 set_vertical_scroll_bar_hook = win32_set_vertical_scroll_bar;
3659 condemn_scroll_bars_hook = win32_condemn_scroll_bars;
3660 redeem_scroll_bar_hook = win32_redeem_scroll_bar;
3661 judge_scroll_bars_hook = win32_judge_scroll_bars;
3662
3663 scroll_region_ok = 1; /* we'll scroll partial frames */
3664 char_ins_del_ok = 0; /* just as fast to write the line */
3665 line_ins_del_ok = 1; /* we'll just blt 'em */
3666 fast_clear_end_of_line = 1; /* X does this well */
3667 memory_below_frame = 0; /* we don't remember what scrolls
3668 off the bottom */
3669 baud_rate = 19200;
3670
3671 /* Try to use interrupt input; if we can't, then start polling. */
3672 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3673
3674 /* Create the window thread - it will terminate itself or when the app terminates */
3675
3676 init_crit ();
3677
3678 dwMainThreadId = GetCurrentThreadId ();
3679 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3680 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
3681
3682 /* Wait for thread to start */
3683
3684 {
3685 MSG msg;
3686
3687 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
3688
3689 hWinThread = CreateThread (NULL, 0,
3690 (LPTHREAD_START_ROUTINE) win_msg_worker,
3691 0, 0, &dwWinThreadId);
3692
3693 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
3694 }
3695
3696 /* AttachThreadInput (dwWinThreadId, dwMainThreadId, TRUE); */
3697
3698}
3699
3700void
3701syms_of_win32term ()
3702{
3703 staticpro (&win32_display_name_list);
3704 win32_display_name_list = Qnil;
3705
3706 staticpro (&last_mouse_scroll_bar);
3707 last_mouse_scroll_bar = Qnil;
3708
3709 staticpro (&Qvendor_specific_keysyms);
3710 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
3711}
diff --git a/src/w32xfns.c b/src/w32xfns.c
new file mode 100644
index 00000000000..0fda8c87e6b
--- /dev/null
+++ b/src/w32xfns.c
@@ -0,0 +1,293 @@
1/* Functions taken directly from X sources
2 Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include <signal.h>
21#include <config.h>
22#include <stdio.h>
23#include "lisp.h"
24#include "blockinput.h"
25#include "w32term.h"
26#include "windowsx.h"
27
28#define myalloc(cb) GlobalAllocPtr (GPTR, cb)
29#define myfree(lp) GlobalFreePtr (lp)
30
31CRITICAL_SECTION critsect;
32extern HANDLE keyboard_handle;
33HANDLE hEvent = NULL;
34
35void
36init_crit ()
37{
38 InitializeCriticalSection (&critsect);
39 keyboard_handle = hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
40}
41
42void
43enter_crit ()
44{
45 EnterCriticalSection (&critsect);
46}
47
48void
49leave_crit ()
50{
51 LeaveCriticalSection (&critsect);
52}
53
54void
55delete_crit ()
56{
57 DeleteCriticalSection (&critsect);
58 if (hEvent)
59 {
60 CloseHandle (hEvent);
61 hEvent = NULL;
62 }
63}
64
65typedef struct int_msg
66{
67 Win32Msg w32msg;
68 struct int_msg *lpNext;
69} int_msg;
70
71int_msg *lpHead = NULL;
72int_msg *lpTail = NULL;
73int nQueue = 0;
74
75BOOL
76get_next_msg (lpmsg, bWait)
77 Win32Msg * lpmsg;
78 BOOL bWait;
79{
80 BOOL bRet = FALSE;
81
82 enter_crit ();
83
84 /* The while loop takes care of multiple sets */
85
86 while (!nQueue && bWait)
87 {
88 leave_crit ();
89 WaitForSingleObject (hEvent, INFINITE);
90 enter_crit ();
91 }
92
93 if (nQueue)
94 {
95 bcopy (&(lpHead->w32msg), lpmsg, sizeof (Win32Msg));
96
97 {
98 int_msg * lpCur = lpHead;
99
100 lpHead = lpHead->lpNext;
101
102 myfree (lpCur);
103 }
104
105 nQueue--;
106
107 bRet = TRUE;
108 }
109
110 leave_crit ();
111
112 return (bRet);
113}
114
115BOOL
116post_msg (lpmsg)
117 Win32Msg * lpmsg;
118{
119 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
120
121 if (!lpNew) return (FALSE);
122
123 bcopy (lpmsg, &(lpNew->w32msg), sizeof (Win32Msg));
124 lpNew->lpNext = NULL;
125
126 enter_crit ();
127
128 if (nQueue++)
129 {
130 lpTail->lpNext = lpNew;
131 }
132 else
133 {
134 lpHead = lpNew;
135 SetEvent (hEvent);
136 }
137
138 lpTail = lpNew;
139
140 leave_crit ();
141
142 return (TRUE);
143}
144
145/*
146 * XParseGeometry parses strings of the form
147 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
148 * width, height, xoffset, and yoffset are unsigned integers.
149 * Example: "=80x24+300-49"
150 * The equal sign is optional.
151 * It returns a bitmask that indicates which of the four values
152 * were actually found in the string. For each value found,
153 * the corresponding argument is updated; for each value
154 * not found, the corresponding argument is left unchanged.
155 */
156
157static int
158read_integer (string, NextString)
159 register char *string;
160 char **NextString;
161{
162 register int Result = 0;
163 int Sign = 1;
164
165 if (*string == '+')
166 string++;
167 else if (*string == '-')
168 {
169 string++;
170 Sign = -1;
171 }
172 for (; (*string >= '0') && (*string <= '9'); string++)
173 {
174 Result = (Result * 10) + (*string - '0');
175 }
176 *NextString = string;
177 if (Sign >= 0)
178 return (Result);
179 else
180 return (-Result);
181}
182
183int
184XParseGeometry (string, x, y, width, height)
185 char *string;
186 int *x, *y;
187 unsigned int *width, *height; /* RETURN */
188{
189 int mask = NoValue;
190 register char *strind;
191 unsigned int tempWidth, tempHeight;
192 int tempX, tempY;
193 char *nextCharacter;
194
195 if ((string == NULL) || (*string == '\0')) return (mask);
196 if (*string == '=')
197 string++; /* ignore possible '=' at beg of geometry spec */
198
199 strind = (char *)string;
200 if (*strind != '+' && *strind != '-' && *strind != 'x')
201 {
202 tempWidth = read_integer (strind, &nextCharacter);
203 if (strind == nextCharacter)
204 return (0);
205 strind = nextCharacter;
206 mask |= WidthValue;
207 }
208
209 if (*strind == 'x' || *strind == 'X')
210 {
211 strind++;
212 tempHeight = read_integer (strind, &nextCharacter);
213 if (strind == nextCharacter)
214 return (0);
215 strind = nextCharacter;
216 mask |= HeightValue;
217 }
218
219 if ((*strind == '+') || (*strind == '-'))
220 {
221 if (*strind == '-')
222 {
223 strind++;
224 tempX = -read_integer (strind, &nextCharacter);
225 if (strind == nextCharacter)
226 return (0);
227 strind = nextCharacter;
228 mask |= XNegative;
229
230 }
231 else
232 {
233 strind++;
234 tempX = read_integer (strind, &nextCharacter);
235 if (strind == nextCharacter)
236 return (0);
237 strind = nextCharacter;
238 }
239 mask |= XValue;
240 if ((*strind == '+') || (*strind == '-'))
241 {
242 if (*strind == '-')
243 {
244 strind++;
245 tempY = -read_integer (strind, &nextCharacter);
246 if (strind == nextCharacter)
247 return (0);
248 strind = nextCharacter;
249 mask |= YNegative;
250
251 }
252 else
253 {
254 strind++;
255 tempY = read_integer (strind, &nextCharacter);
256 if (strind == nextCharacter)
257 return (0);
258 strind = nextCharacter;
259 }
260 mask |= YValue;
261 }
262 }
263
264 /* If strind isn't at the end of the string the it's an invalid
265 geometry specification. */
266
267 if (*strind != '\0') return (0);
268
269 if (mask & XValue)
270 *x = tempX;
271 if (mask & YValue)
272 *y = tempY;
273 if (mask & WidthValue)
274 *width = tempWidth;
275 if (mask & HeightValue)
276 *height = tempHeight;
277 return (mask);
278}
279
280/* The semantics of the use of using_x_p is really using_a_window_system. */
281int
282using_x_p (void)
283{
284 return 1;
285}
286
287/* x_sync is a no-op on Win32. */
288void
289x_sync (f)
290 void *f;
291{
292}
293