XEmacs 21.2.7
[chise/xemacs-chise.git.1] / src / frame-msw.c
1 /* Functions for the mswindows window system.
2    Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3    Copyright (C) 1995, 1996 Ben Wing.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Not synched with FSF. */
23
24 /* Authorship:
25
26    Ultimately based on FSF.
27    Substantially rewritten for XEmacs by Ben Wing.
28    Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
29    Graphics features added and frame resizing fiddled with by Andy Piper.
30  */
31
32 #include <config.h>
33 #include "lisp.h"
34
35 #include "buffer.h"
36 #include "elhash.h"
37 #include "console-msw.h"
38 #include "glyphs-msw.h"
39 #include "elhash.h"
40 #include "events.h"
41 #include "faces.h"
42 #include "frame.h"
43 #include "redisplay.h"
44 #include "window.h"
45
46 #define MSWINDOWS_FRAME_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW)
47 #define MSWINDOWS_POPUP_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP \
48                                | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX)
49
50 #define MSWINDOWS_FRAME_EXSTYLE WS_EX_OVERLAPPEDWINDOW
51 #define MSWINDOWS_POPUP_EXSTYLE WS_EX_PALETTEWINDOW
52
53 /* Default popup left top corner offset from the same
54    corner of the parent frame, in pixel */
55 #define POPUP_OFFSET 30
56
57 /* Default popup size, in characters */
58 #define POPUP_WIDTH 30
59 #define POPUP_HEIGHT 10
60
61 /* Default popup size, in characters */
62 #define DEFAULT_FRAME_WIDTH 80
63 #define DEFAULT_FRAME_HEIGHT 35
64
65 #ifdef HAVE_MENUBARS
66 #define ADJR_MENUFLAG TRUE
67 #else
68 #define ADJR_MENUFLAG FALSE
69 #endif
70
71 /* Default properties to use when creating frames.  */
72 Lisp_Object Vdefault_mswindows_frame_plist;
73 Lisp_Object Vmswindows_use_system_frame_size_defaults;
74
75 /* This does not need to be GC protected, as it holds a
76    frame Lisp_Object already protected by Fmake_frame */
77 Lisp_Object Vmswindows_frame_being_created;
78
79 static void
80 mswindows_init_frame_1 (struct frame *f, Lisp_Object props)
81 {
82   Lisp_Object initially_unmapped;
83   Lisp_Object name, height, width, popup, top, left;
84   Lisp_Object frame_obj = Qnil;
85   RECT rect;
86   XEMACS_RECT_WH rect_default;
87   DWORD style, exstyle;
88   HWND hwnd, hwnd_parent;
89
90   /* Pick up relevant properties */
91   initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
92   name = Fplist_get (props, Qname, Qnil);
93   
94   popup = Fplist_get (props, Qpopup, Qnil);
95   if (EQ (popup, Qt))
96     popup = Fselected_frame (Qnil);
97
98   left = Fplist_get (props, Qleft, Qnil);
99   if (!NILP (left))
100     CHECK_INT (left);
101
102   top = Fplist_get (props, Qtop, Qnil);
103   if (!NILP (top))
104     CHECK_INT (top);
105
106   width = Fplist_get (props, Qwidth, Qnil);
107   if (!NILP (width))
108     CHECK_INT (width);
109
110   height = Fplist_get (props, Qheight, Qnil);
111   if (!NILP (height))
112     CHECK_INT (height);
113
114   f->frame_data = xnew_and_zero (struct mswindows_frame);
115   FRAME_MSWINDOWS_TARGET_RECT (f) = xnew_and_zero (XEMACS_RECT_WH);
116
117   FRAME_MSWINDOWS_TARGET_RECT (f)->left = NILP (left) ? -1 : abs (XINT (left));
118   FRAME_MSWINDOWS_TARGET_RECT (f)->top = NILP (top) ? -1 : abs (XINT (top));
119   FRAME_MSWINDOWS_TARGET_RECT (f)->width = NILP (width) ? -1 : 
120     abs (XINT (width));
121   FRAME_MSWINDOWS_TARGET_RECT (f)->height = NILP (height) ? -1 : 
122     abs (XINT (height));
123       
124   /* Misc frame stuff */
125   FRAME_MSWINDOWS_DATA(f)->button2_need_lbutton = 0;
126   FRAME_MSWINDOWS_DATA(f)->button2_need_rbutton = 0;
127   FRAME_MSWINDOWS_DATA(f)->button2_is_down = 0;
128   FRAME_MSWINDOWS_DATA(f)->ignore_next_lbutton_up = 0;
129   FRAME_MSWINDOWS_DATA(f)->ignore_next_rbutton_up = 0;
130   FRAME_MSWINDOWS_DATA(f)->sizing = 0;
131   FRAME_MSWINDOWS_MENU_HASH_TABLE(f) = Qnil;
132 #ifdef HAVE_TOOLBARS
133   FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) = 
134     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
135 #endif
136   /* hashtable of instantiated glyphs on the frame. */
137   FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f) = 
138     make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
139   /* Will initialize these in WM_SIZE handler. We cannot do it now,
140      because we do not know what is CW_USEDEFAULT height and width */
141   FRAME_WIDTH (f) = 0;
142   FRAME_HEIGHT (f) = 0;
143   FRAME_PIXWIDTH (f) = 0;
144   FRAME_PIXHEIGHT (f) = 0;
145
146   if (NILP (popup))
147     {
148       style = MSWINDOWS_FRAME_STYLE;
149       exstyle = MSWINDOWS_FRAME_EXSTYLE;
150       hwnd_parent = NULL;
151
152       rect_default.left = rect_default.top = CW_USEDEFAULT;
153       rect_default.width = rect_default.height = CW_USEDEFAULT;
154     }
155   else
156     {
157       style = MSWINDOWS_POPUP_STYLE;
158       exstyle = MSWINDOWS_POPUP_EXSTYLE;
159
160       CHECK_MSWINDOWS_FRAME (popup);
161       hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
162       assert (IsWindow (hwnd_parent));
163
164       /* We cannot use CW_USEDEFAULT when creating a popup window.
165          So by default, we offset the new popup 30 pixels right
166          and down from its parent, and give it size of 30x10 characters.
167          These dimensions look adequate on both high and low res monitors */
168       GetWindowRect (hwnd_parent, &rect);
169       rect_default.left = rect.left + POPUP_OFFSET;
170       rect_default.top = rect.top + POPUP_OFFSET;
171       char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
172                                &rect_default.width, &rect_default.height);
173     }
174
175   AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
176
177   XSETFRAME (frame_obj, f);
178
179   Vmswindows_frame_being_created = frame_obj;
180
181   hwnd = CreateWindowEx (exstyle,
182                          XEMACS_CLASS,
183                          STRINGP(f->name) ? XSTRING_DATA(f->name) :
184                          (STRINGP(name) ? XSTRING_DATA(name) : XEMACS_CLASS),
185                          style,
186                          rect_default.left, rect_default.top,
187                          rect_default.width, rect_default.height,
188                          hwnd_parent, NULL, NULL, NULL);
189
190   Vmswindows_frame_being_created = Qnil;
191
192   if (hwnd == NULL)
193     error ("System call to create frame failed");
194                            
195   FRAME_MSWINDOWS_HANDLE(f) = hwnd;
196
197   SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
198   FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
199   FRAME_MSWINDOWS_CDC(f) = CreateCompatibleDC (FRAME_MSWINDOWS_CDC(f));
200   SetTextAlign (FRAME_MSWINDOWS_DC(f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
201 }
202
203 static void
204 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
205 {
206   if (NILP (Vmswindows_use_system_frame_size_defaults))
207     {
208       /* I don't think anything can set the frame size before this
209          since we don't have X resources. This may change if we look
210          at the registry. Even so these values can get overridden
211          later.*/
212       XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH, 
213                               DEFAULT_FRAME_HEIGHT };
214       mswindows_size_frame_internal (f, &dest);
215     }
216 }
217
218 /* Called after frame's properties are set */
219 static void
220 mswindows_init_frame_3 (struct frame *f)
221 {
222   /* Don't do this earlier or we get a WM_PAINT before the frame is ready.
223    * The SW_x parameter in the first call that an app makes to ShowWindow is
224    * ignored, and the parameter specified in the caller's STARTUPINFO is 
225    * substituted instead. That parameter is SW_HIDE if we were started by
226    * runemacs, so call this twice. #### runemacs is evil */
227   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
228   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
229   SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
230   DragAcceptFiles (FRAME_MSWINDOWS_HANDLE(f), TRUE);
231 }
232
233 static void
234 mswindows_after_init_frame (struct frame *f, int first_on_device,
235                             int first_on_console)
236 {
237   /* Windows, unlike X, is very synchronous. After the initial
238      frame is created, it will never be displayed, except for 
239      hollow border, unless we start pumping messages. Load progress
240      messages show in the bottom of the hollow frame, which is ugly.
241      We redisplay the initial frame here, so modeline and root window
242      background show.
243   */
244   if (first_on_console)
245     redisplay ();
246 }
247
248 static void
249 mswindows_mark_frame (struct frame *f, void (*markobj) (Lisp_Object))
250 {
251   markobj (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
252 #ifdef HAVE_TOOLBARS
253   markobj (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
254 #endif
255   markobj (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f));
256 }
257
258 static void
259 mswindows_focus_on_frame (struct frame *f)
260 {
261   SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
262 }
263
264 static void
265 mswindows_delete_frame (struct frame *f)
266 {
267   if (f->frame_data)
268     {
269       DeleteDC(FRAME_MSWINDOWS_CDC(f));
270       ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
271       DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
272       xfree (f->frame_data);
273     }
274   f->frame_data = 0;
275 }
276
277 static void
278 mswindows_set_frame_size (struct frame *f, int width, int height)
279 {
280   RECT rect;
281   rect.left = rect.top = 0;
282   rect.right = width;
283   rect.bottom = height;
284
285   AdjustWindowRectEx (&rect,
286                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
287                       GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
288                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
289
290   if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
291     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
292
293   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
294                 0, 0, rect.right-rect.left, rect.bottom-rect.top,
295                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
296 }
297
298 static void
299 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
300 {
301   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
302                 xoff, yoff, 0, 0,
303                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
304 }
305
306 static void
307 mswindows_make_frame_visible (struct frame *f) 
308 {
309   if (f->iconified)
310     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
311   else
312     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
313   f->visible = 1;
314   f->iconified = 0;
315 }
316
317 static void
318 mswindows_make_frame_invisible (struct frame *f) 
319 {
320   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
321   f->visible = -1;
322 }
323
324 static int
325 mswindows_frame_totally_visible_p (struct frame *f)
326 {
327   RECT rc_me, rc_other, rc_temp;
328   HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
329
330   /* We test against not a whole window rectangle, only against its
331      client part. So, if non-client are is covered and client area is
332      not, we return true. */
333   GetClientRect (hwnd, &rc_me);
334   MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2);
335
336   /* First see if we're off the desktop */
337   GetWindowRect (GetDesktopWindow(), &rc_other);
338   UnionRect(&rc_temp, &rc_me, &rc_other);
339   if (!EqualRect (&rc_temp, &rc_other))
340     return 0;
341   
342   /* Then see if any window above us obscures us */
343   while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
344     if (IsWindowVisible (hwnd))
345       {
346         GetWindowRect (hwnd, &rc_other);
347         if (IntersectRect(&rc_temp, &rc_me, &rc_other))
348           return 0;
349       }
350
351   return 1;
352 }
353
354 static int
355 mswindows_frame_visible_p (struct frame *f)
356 {
357   return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
358     && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
359 }
360
361
362 static void
363 mswindows_iconify_frame (struct frame *f)
364 {
365   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
366   f->visible = 0;
367   f->iconified = 1;
368 }
369
370 static int
371 mswindows_frame_iconified_p (struct frame *f)
372 {
373   return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
374 }
375
376 static void
377 mswindows_set_frame_icon (struct frame *f)
378 {
379   if (IMAGE_INSTANCEP (f->icon)
380       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
381     {
382       if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
383         {
384           mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon), 
385                                                     FALSE);
386         }
387       
388       SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON, 
389                     (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
390     }
391 }
392
393 static void
394 mswindows_set_frame_pointer (struct frame *f)
395 {
396   if (IMAGE_INSTANCEP (f->pointer)
397       && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
398     {
399       SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR,
400                     (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
401       /* we only have to do this because GC doesn't cause a mouse
402          event and doesn't give time to event processing even if it
403          did. */
404       SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
405     }
406 }
407
408 static void
409 mswindows_set_mouse_position (struct window *w, int x, int y)
410 {
411   struct frame *f = XFRAME (w->frame);
412   POINT pt;
413
414   pt.x = w->pixel_left + x;
415   pt.y = w->pixel_top  + y;
416   ClientToScreen (FRAME_MSWINDOWS_HANDLE(f), &pt);
417   SetCursorPos (pt.x, pt.y);
418 }
419
420 static int
421 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
422 {
423   POINT pt;
424   HWND hwnd;
425
426   GetCursorPos (&pt);
427
428   /* What's under cursor? */
429   hwnd = WindowFromPoint (pt);
430   if (hwnd == NULL)
431     return 0;
432
433   /* Get grandest parent of the window */
434   {
435     HWND hwnd_parent;
436     while ((hwnd_parent = GetParent (hwnd)) != NULL)
437       hwnd = hwnd_parent;
438   }
439
440   /* Make sure it belongs to us */
441   if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
442     return 0;
443
444   /* And that the window is an XEmacs frame */
445   {
446     char class_name [sizeof(XEMACS_CLASS) + 1];
447     if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
448         || strcmp (class_name, XEMACS_CLASS) != 0)
449       return 0;
450   }
451
452   /* Yippie! */
453   ScreenToClient (hwnd, &pt);
454   VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
455   *x = pt.x;
456   *y = pt.y;
457   return 1;
458 }
459
460 static void
461 mswindows_raise_frame (struct frame *f)
462 {
463   BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
464   /* XXX Should we do SetWindowForeground too ? */
465 }
466
467 static void
468 mswindows_lower_frame (struct frame *f)
469 {
470   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
471                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
472 }
473
474 static void
475 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title) 
476 {
477   unsigned int new_checksum = hash_string (title, strlen (title));
478   if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
479     {
480       FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
481       SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
482     }
483 }
484
485 static Lisp_Object
486 mswindows_frame_property (struct frame *f, Lisp_Object property)
487 {
488   if (EQ (Qleft, property) || EQ (Qtop, property))
489     {
490       RECT rc;
491       GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
492       return make_int (EQ (Qtop,  property) ? rc.top : rc.left);
493     }
494   return Qunbound;
495 }
496
497 static int
498 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
499 {
500   return EQ (property, Qleft)
501     || EQ (property, Qtop);
502   /* #### frame-x.c has also this. Why?
503     || STRINGP (property);
504   */
505 }
506
507 static Lisp_Object
508 mswindows_frame_properties (struct frame *f)
509 {
510   Lisp_Object props = Qnil;
511   RECT rc;
512   GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
513
514   props = cons3 (Qtop,  make_int (rc.top), props);
515   props = cons3 (Qleft, make_int (rc.left), props);
516
517   return props;
518 }
519
520 static void
521 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
522 {
523   int x=-1, y=-1;
524   int width = -1, height = -1;
525   BOOL width_specified_p = FALSE;
526   BOOL height_specified_p = FALSE;
527   BOOL x_specified_p = FALSE;
528   BOOL y_specified_p = FALSE;
529   Lisp_Object tail;
530
531   /* Extract the properties from plist */
532   for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
533     {
534       Lisp_Object prop = Fcar (tail);
535       Lisp_Object val = Fcar (Fcdr (tail));
536
537       if (SYMBOLP (prop))
538         {
539           /* Kludge to handle the font property. */
540           if (EQ (prop, Qfont))
541             {
542               /* If the value is not a string we silently ignore it. */
543               if (STRINGP (val))
544                 {
545                   Lisp_Object frm, font_spec;
546                   
547                   XSETFRAME (frm, f);
548                   font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
549
550                   Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
551                   update_frame_face_values (f);
552                 }
553             }
554           else if (EQ (prop, Qwidth))
555             {
556               CHECK_INT (val);
557               width = XINT (val);
558               width_specified_p = TRUE;
559             }
560           else if (EQ (prop, Qheight))
561             {
562               CHECK_INT (val);
563               height = XINT (val);
564               height_specified_p = TRUE;
565             }
566           else if (EQ (prop, Qleft))
567             {
568               CHECK_INT (val);
569               x = XINT (val);
570               x_specified_p = TRUE;
571             }
572           else if (EQ (prop, Qtop))
573             {
574               CHECK_INT (val);
575               y = XINT (val);
576               y_specified_p = TRUE;
577             }
578         }
579     }
580
581   /* Now we've extracted the properties, apply them.
582      Do not apply geometric properties during frame creation. This
583      is excessive anyways, and this loses becuase WM_SIZE has not
584      been sent yet, so frame width and height fields are not initialized.
585      
586      unfortunately WM_SIZE loses as well since the resize is only
587      applied once and the first time WM_SIZE is applied not everything
588      is initialised in the frame (toolbars for instance). enabling
589      this always makes no visible difference and fixes a whole host of
590      bugs (and is more consistent with X) so I am going to reenable it.
591      --andyp */
592   if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
593        && (width_specified_p || height_specified_p || x_specified_p || y_specified_p))
594     {
595       XEMACS_RECT_WH dest = { x, y, width, height };
596
597       mswindows_size_frame_internal (f, &dest);
598     }
599 }
600
601 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
602 {
603   RECT rect;
604   int pixel_width, pixel_height;
605   int size_p = (dest->width >=0 || dest->height >=0);
606   int move_p = (dest->top >=0 || dest->left >=0);
607   struct device* d = XDEVICE (FRAME_DEVICE (f));
608   char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height);
609   
610   if (dest->width < 0)
611     pixel_width = FRAME_PIXWIDTH (f);
612   if (dest->height < 0)
613     pixel_height = FRAME_PIXHEIGHT (f);
614
615   GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
616   if (dest->left < 0)
617     dest->left = rect.left;
618   if (dest->top < 0)
619     dest->top = rect.top;
620   
621   rect.left = rect.top = 0;
622   rect.right = pixel_width;
623   rect.bottom = pixel_height;
624
625   AdjustWindowRectEx (&rect,
626                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
627                       GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
628                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
629
630   /* resize and move the window so that it fits on the screen. This is
631   not restrictive since this will happen later anyway in WM_SIZE.  We
632   have to do this after adjusting the rect to account for menubar
633   etc. */
634   pixel_width = rect.right - rect.left;
635   pixel_height = rect.bottom - rect.top;
636   if (pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
637     {
638       pixel_width = DEVICE_MSWINDOWS_HORZRES(d);
639       size_p=1;
640     }
641   if (pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
642     {
643       pixel_height = DEVICE_MSWINDOWS_VERTRES(d);
644       size_p=1;
645     }
646
647   /* adjust position so window is on screen */
648   if (dest->left + pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
649     {
650       dest->left = DEVICE_MSWINDOWS_HORZRES(d) - pixel_width;
651       move_p=1;
652     }
653   if (dest->top + pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
654     {
655       dest->top = DEVICE_MSWINDOWS_VERTRES(d) - pixel_height;
656       move_p=1;
657     }
658
659   if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) 
660       || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
661     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
662
663   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
664                 dest->left, dest->top, pixel_width, pixel_height,
665                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
666                 | (size_p ? 0 : SWP_NOSIZE)
667                 | (move_p ? 0 : SWP_NOMOVE));
668 }
669
670 static Lisp_Object
671 mswindows_get_frame_parent (struct frame *f)
672 {
673   HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
674   hwnd = GetParent (hwnd);
675   if (hwnd)
676     {
677       Lisp_Object parent;
678       VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
679       assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
680       return parent;
681     }
682   else
683     return Qnil;
684 }
685
686 static void
687 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
688 {
689 }
690
691 static int
692 mswindows_frame_size_fixed_p (struct frame *f)
693 {
694   /* Frame size cannot change if the frame is maximized */
695   return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
696 }
697
698 void
699 console_type_create_frame_mswindows (void)
700 {
701   /* frame methods */
702   CONSOLE_HAS_METHOD (mswindows, init_frame_1);
703   CONSOLE_HAS_METHOD (mswindows, init_frame_2); 
704   CONSOLE_HAS_METHOD (mswindows, init_frame_3);
705   CONSOLE_HAS_METHOD (mswindows, after_init_frame);
706   CONSOLE_HAS_METHOD (mswindows, mark_frame);
707   CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
708   CONSOLE_HAS_METHOD (mswindows, delete_frame);
709   CONSOLE_HAS_METHOD (mswindows, get_mouse_position);
710   CONSOLE_HAS_METHOD (mswindows, set_mouse_position);
711   CONSOLE_HAS_METHOD (mswindows, raise_frame);
712   CONSOLE_HAS_METHOD (mswindows, lower_frame);
713   CONSOLE_HAS_METHOD (mswindows, make_frame_visible);
714   CONSOLE_HAS_METHOD (mswindows, make_frame_invisible);
715   CONSOLE_HAS_METHOD (mswindows, iconify_frame);
716   CONSOLE_HAS_METHOD (mswindows, set_frame_size);
717   CONSOLE_HAS_METHOD (mswindows, set_frame_position);
718   CONSOLE_HAS_METHOD (mswindows, frame_property);
719   CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p);
720   CONSOLE_HAS_METHOD (mswindows, frame_properties);
721   CONSOLE_HAS_METHOD (mswindows, set_frame_properties);
722   CONSOLE_HAS_METHOD (mswindows, set_title_from_bufbyte);
723 /*  CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_bufbyte); */
724   CONSOLE_HAS_METHOD (mswindows, frame_visible_p);
725   CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p);
726   CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
727   CONSOLE_HAS_METHOD (mswindows, set_frame_pointer); 
728   CONSOLE_HAS_METHOD (mswindows, set_frame_icon); 
729   CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
730   CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
731   CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p);
732 }
733
734 void
735 syms_of_frame_mswindows (void)
736 {
737 }
738
739 void
740 vars_of_frame_mswindows (void)
741 {
742   /* Needn't staticpro -- see comment above.  */
743   Vmswindows_frame_being_created = Qnil;
744
745   DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /*
746 Controls whether to use system or XEmacs defaults for frame size.
747 If nil then reasonable defaults are used for intial frame sizes. If t
748 then the system will choose default sizes for the frame.
749 */ );
750   Vmswindows_use_system_frame_size_defaults = Qnil;
751   
752   DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
753 Plist of default frame-creation properties for mswindows frames.
754 These override what is specified in `default-frame-plist', but are
755 overridden by the arguments to the particular call to `make-frame'.
756
757 Note: In many cases, properties of a frame are available as specifiers
758 instead of through the frame-properties mechanism.
759
760 Here is a list of recognized frame properties, other than those
761 documented in `set-frame-properties' (they can be queried and
762 set at any time, except as otherwise noted):
763
764   initially-unmapped            If non-nil, the frame will not be visible
765                                 when it is created.  In this case, you
766                                 need to call `make-frame-visible' to make
767                                 the frame appear.
768   popup                         If non-nil, it should be a frame, and this
769                                 frame will be created as a "popup" frame
770                                 whose parent is the given frame.  This
771                                 will make the window manager treat the
772                                 frame as a dialog box, which may entail
773                                 doing different things (e.g. not asking
774                                 for positioning, and not iconifying
775                                 separate from its parent).
776   top                           Y position (in pixels) of the upper-left
777                                 outermost corner of the frame (i.e. the
778                                 upper-left of the window-manager
779                                 decorations).
780   left                          X position (in pixels) of the upper-left
781                                 outermost corner of the frame (i.e. the
782                                 upper-left of the window-manager
783                                 decorations).
784
785 See also `default-frame-plist', which specifies properties which apply
786 to all frames, not just mswindows frames.
787 */ );
788   Vdefault_mswindows_frame_plist = Qnil;
789
790   mswindows_console_methods->device_specific_frame_props =
791     &Vdefault_mswindows_frame_plist;
792 }