ff640f2e4591049ffe27f90842ed6eaf41b05749
[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 Vdefault_msprinter_frame_plist;
74 Lisp_Object Vmswindows_use_system_frame_size_defaults;
75
76 /* This does not need to be GC protected, as it holds a
77    frame Lisp_Object already protected by Fmake_frame */
78 Lisp_Object Vmswindows_frame_being_created;
79
80 /*---------------------------------------------------------------------*/
81 /*-----                    DISPLAY FRAME                          -----*/
82 /*---------------------------------------------------------------------*/
83
84 static void
85 mswindows_init_frame_1 (struct frame *f, Lisp_Object props)
86 {
87   Lisp_Object initially_unmapped;
88   Lisp_Object name, height, width, popup, top, left;
89   Lisp_Object frame_obj = Qnil;
90   RECT rect;
91   XEMACS_RECT_WH rect_default;
92   DWORD style, exstyle;
93   HWND hwnd, hwnd_parent;
94
95   /* Pick up relevant properties */
96   initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
97   name = Fplist_get (props, Qname, Qnil);
98   
99   popup = Fplist_get (props, Qpopup, Qnil);
100   if (EQ (popup, Qt))
101     popup = Fselected_frame (Qnil);
102
103   left = Fplist_get (props, Qleft, Qnil);
104   if (!NILP (left))
105     CHECK_INT (left);
106
107   top = Fplist_get (props, Qtop, Qnil);
108   if (!NILP (top))
109     CHECK_INT (top);
110
111   width = Fplist_get (props, Qwidth, Qnil);
112   if (!NILP (width))
113     CHECK_INT (width);
114
115   height = Fplist_get (props, Qheight, Qnil);
116   if (!NILP (height))
117     CHECK_INT (height);
118
119   f->frame_data = xnew_and_zero (struct mswindows_frame);
120   FRAME_MSWINDOWS_TARGET_RECT (f) = xnew_and_zero (XEMACS_RECT_WH);
121
122   FRAME_MSWINDOWS_TARGET_RECT (f)->left = NILP (left) ? -1 : abs (XINT (left));
123   FRAME_MSWINDOWS_TARGET_RECT (f)->top = NILP (top) ? -1 : abs (XINT (top));
124   FRAME_MSWINDOWS_TARGET_RECT (f)->width = NILP (width) ? -1 : 
125     abs (XINT (width));
126   FRAME_MSWINDOWS_TARGET_RECT (f)->height = NILP (height) ? -1 : 
127     abs (XINT (height));
128       
129   /* Misc frame stuff */
130   FRAME_MSWINDOWS_DATA(f)->button2_need_lbutton = 0;
131   FRAME_MSWINDOWS_DATA(f)->button2_need_rbutton = 0;
132   FRAME_MSWINDOWS_DATA(f)->button2_is_down = 0;
133   FRAME_MSWINDOWS_DATA(f)->ignore_next_lbutton_up = 0;
134   FRAME_MSWINDOWS_DATA(f)->ignore_next_rbutton_up = 0;
135   FRAME_MSWINDOWS_DATA(f)->sizing = 0;
136   FRAME_MSWINDOWS_MENU_HASH_TABLE(f) = Qnil;
137 #ifdef HAVE_TOOLBARS
138   FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) = 
139     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
140 #endif
141   /* hashtable of instantiated glyphs on the frame. */
142   FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f) = 
143     make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
144   /* Will initialize these in WM_SIZE handler. We cannot do it now,
145      because we do not know what is CW_USEDEFAULT height and width */
146   FRAME_WIDTH (f) = 0;
147   FRAME_HEIGHT (f) = 0;
148   FRAME_PIXWIDTH (f) = 0;
149   FRAME_PIXHEIGHT (f) = 0;
150
151   if (NILP (popup))
152     {
153       style = MSWINDOWS_FRAME_STYLE;
154       exstyle = MSWINDOWS_FRAME_EXSTYLE;
155       hwnd_parent = NULL;
156
157       rect_default.left = rect_default.top = CW_USEDEFAULT;
158       rect_default.width = rect_default.height = CW_USEDEFAULT;
159     }
160   else
161     {
162       style = MSWINDOWS_POPUP_STYLE;
163       exstyle = MSWINDOWS_POPUP_EXSTYLE;
164
165       CHECK_MSWINDOWS_FRAME (popup);
166       hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
167       assert (IsWindow (hwnd_parent));
168
169       /* We cannot use CW_USEDEFAULT when creating a popup window.
170          So by default, we offset the new popup 30 pixels right
171          and down from its parent, and give it size of 30x10 characters.
172          These dimensions look adequate on both high and low res monitors */
173       GetWindowRect (hwnd_parent, &rect);
174       rect_default.left = rect.left + POPUP_OFFSET;
175       rect_default.top = rect.top + POPUP_OFFSET;
176       char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
177                                &rect_default.width, &rect_default.height);
178     }
179
180   AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
181
182   XSETFRAME (frame_obj, f);
183
184   Vmswindows_frame_being_created = frame_obj;
185
186   hwnd = CreateWindowEx (exstyle,
187                          XEMACS_CLASS,
188                          STRINGP(f->name) ? XSTRING_DATA(f->name) :
189                          (STRINGP(name) ? 
190                           (const Extbyte*)XSTRING_DATA(name) : 
191                           (const Extbyte*)XEMACS_CLASS),
192                          style,
193                          rect_default.left, rect_default.top,
194                          rect_default.width, rect_default.height,
195                          hwnd_parent, NULL, NULL, NULL);
196
197   Vmswindows_frame_being_created = Qnil;
198
199   if (hwnd == NULL)
200     error ("System call to create frame failed");
201                            
202   FRAME_MSWINDOWS_HANDLE(f) = hwnd;
203
204   SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
205   FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
206   FRAME_MSWINDOWS_CDC(f) = CreateCompatibleDC (FRAME_MSWINDOWS_CDC(f));
207   SetTextAlign (FRAME_MSWINDOWS_DC(f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
208 }
209
210 static void
211 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
212 {
213   if (NILP (Vmswindows_use_system_frame_size_defaults))
214     {
215       /* I don't think anything can set the frame size before this
216          since we don't have X resources. This may change if we look
217          at the registry. Even so these values can get overridden
218          later.*/
219       XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH, 
220                               DEFAULT_FRAME_HEIGHT };
221       mswindows_size_frame_internal (f, &dest);
222     }
223 }
224
225 /* Called after frame's properties are set */
226 static void
227 mswindows_init_frame_3 (struct frame *f)
228 {
229   /* Don't do this earlier or we get a WM_PAINT before the frame is ready.
230    * The SW_x parameter in the first call that an app makes to ShowWindow is
231    * ignored, and the parameter specified in the caller's STARTUPINFO is 
232    * substituted instead. That parameter is SW_HIDE if we were started by
233    * runemacs, so call this twice. #### runemacs is evil */
234   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
235   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
236   SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
237   DragAcceptFiles (FRAME_MSWINDOWS_HANDLE(f), TRUE);
238 }
239
240 static void
241 mswindows_after_init_frame (struct frame *f, int first_on_device,
242                             int first_on_console)
243 {
244   /* Windows, unlike X, is very synchronous. After the initial
245      frame is created, it will never be displayed, except for 
246      hollow border, unless we start pumping messages. Load progress
247      messages show in the bottom of the hollow frame, which is ugly.
248      We redisplay the initial frame here, so modeline and root window
249      background show.
250   */
251   if (first_on_console)
252     redisplay ();
253 }
254
255 static void
256 mswindows_mark_frame (struct frame *f)
257 {
258   mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
259 #ifdef HAVE_TOOLBARS
260   mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
261 #endif
262   mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f));
263 }
264
265 static void
266 mswindows_focus_on_frame (struct frame *f)
267 {
268   SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
269 }
270
271 static void
272 mswindows_delete_frame (struct frame *f)
273 {
274   if (f->frame_data)
275     {
276       DeleteDC(FRAME_MSWINDOWS_CDC(f));
277       ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
278       DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
279       xfree (f->frame_data);
280     }
281   f->frame_data = 0;
282 }
283
284 static void
285 mswindows_set_frame_size (struct frame *f, int width, int height)
286 {
287   RECT rect;
288   rect.left = rect.top = 0;
289   rect.right = width;
290   rect.bottom = height;
291
292   AdjustWindowRectEx (&rect,
293                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
294                       GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
295                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
296
297   if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
298     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
299
300   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
301                 0, 0, rect.right-rect.left, rect.bottom-rect.top,
302                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
303 }
304
305 static void
306 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
307 {
308   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
309                 xoff, yoff, 0, 0,
310                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
311 }
312
313 static void
314 mswindows_make_frame_visible (struct frame *f) 
315 {
316   if (!FRAME_VISIBLE_P(f))
317     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
318   else
319     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOW);
320   f->visible = 1;
321   f->iconified = 0;
322 }
323
324 static void
325 mswindows_make_frame_invisible (struct frame *f) 
326 {
327   if (!FRAME_VISIBLE_P(f))
328     return;
329
330   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
331   f->visible = 0;
332 }
333
334 static int
335 mswindows_frame_totally_visible_p (struct frame *f)
336 {
337   RECT rc_me, rc_other, rc_temp;
338   HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
339
340   /* We test against not a whole window rectangle, only against its
341      client part. So, if non-client are is covered and client area is
342      not, we return true. */
343   GetClientRect (hwnd, &rc_me);
344   MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2);
345
346   /* First see if we're off the desktop */
347   GetWindowRect (GetDesktopWindow(), &rc_other);
348   UnionRect(&rc_temp, &rc_me, &rc_other);
349   if (!EqualRect (&rc_temp, &rc_other))
350     return 0;
351   
352   /* Then see if any window above us obscures us */
353   while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
354     if (IsWindowVisible (hwnd))
355       {
356         GetWindowRect (hwnd, &rc_other);
357         if (IntersectRect(&rc_temp, &rc_me, &rc_other))
358           return 0;
359       }
360
361   return 1;
362 }
363
364 static int
365 mswindows_frame_visible_p (struct frame *f)
366 {
367   return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
368     && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
369 }
370
371
372 static void
373 mswindows_iconify_frame (struct frame *f)
374 {
375   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
376   f->visible = 0;
377   f->iconified = 1;
378 }
379
380 static int
381 mswindows_frame_iconified_p (struct frame *f)
382 {
383   return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
384 }
385
386 static void
387 mswindows_set_frame_icon (struct frame *f)
388 {
389   if (IMAGE_INSTANCEP (f->icon)
390       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
391     {
392       if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
393         {
394           mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon), 
395                                                     FALSE);
396         }
397       
398       SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON, 
399                     (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
400     }
401 }
402
403 static void
404 mswindows_set_frame_pointer (struct frame *f)
405 {
406   if (IMAGE_INSTANCEP (f->pointer)
407       && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
408     {
409       SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR,
410                     (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
411       /* we only have to do this because GC doesn't cause a mouse
412          event and doesn't give time to event processing even if it
413          did. */
414       SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
415     }
416 }
417
418 static void
419 mswindows_set_mouse_position (struct window *w, int x, int y)
420 {
421   struct frame *f = XFRAME (w->frame);
422   POINT pt;
423
424   pt.x = w->pixel_left + x;
425   pt.y = w->pixel_top  + y;
426   ClientToScreen (FRAME_MSWINDOWS_HANDLE(f), &pt);
427   SetCursorPos (pt.x, pt.y);
428 }
429
430 static int
431 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
432 {
433   POINT pt;
434   HWND hwnd;
435
436   GetCursorPos (&pt);
437
438   /* What's under cursor? */
439   hwnd = WindowFromPoint (pt);
440   if (hwnd == NULL)
441     return 0;
442
443   /* Get grandest parent of the window */
444   {
445     HWND hwnd_parent;
446     while ((hwnd_parent = GetParent (hwnd)) != NULL)
447       hwnd = hwnd_parent;
448   }
449
450   /* Make sure it belongs to us */
451   if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
452     return 0;
453
454   /* And that the window is an XEmacs frame */
455   {
456     char class_name [sizeof(XEMACS_CLASS) + 1];
457     if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
458         || strcmp (class_name, XEMACS_CLASS) != 0)
459       return 0;
460   }
461
462   /* Yippie! */
463   ScreenToClient (hwnd, &pt);
464   VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
465   *x = pt.x;
466   *y = pt.y;
467   return 1;
468 }
469
470 static void
471 mswindows_raise_frame (struct frame *f)
472 {
473   BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
474 }
475
476 static void
477 mswindows_lower_frame (struct frame *f)
478 {
479   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
480                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
481 }
482
483 static void
484 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title) 
485 {
486   unsigned int new_checksum = hash_string (title, strlen (title));
487   if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
488     {
489       FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
490       SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
491     }
492 }
493
494 static Lisp_Object
495 mswindows_frame_property (struct frame *f, Lisp_Object property)
496 {
497   if (EQ (Qleft, property) || EQ (Qtop, property))
498     {
499       RECT rc;
500       GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
501       return make_int (EQ (Qtop,  property) ? rc.top : rc.left);
502     }
503   return Qunbound;
504 }
505
506 static int
507 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
508 {
509   return EQ (property, Qleft)
510     || EQ (property, Qtop);
511   /* #### frame-x.c has also this. Why?
512     || STRINGP (property);
513   */
514 }
515
516 static Lisp_Object
517 mswindows_frame_properties (struct frame *f)
518 {
519   Lisp_Object props = Qnil;
520   RECT rc;
521   GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
522
523   props = cons3 (Qtop,  make_int (rc.top), props);
524   props = cons3 (Qleft, make_int (rc.left), props);
525
526   return props;
527 }
528
529 static void
530 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
531 {
532   int x=-1, y=-1;
533   int width = -1, height = -1;
534   BOOL width_specified_p = FALSE;
535   BOOL height_specified_p = FALSE;
536   BOOL x_specified_p = FALSE;
537   BOOL y_specified_p = FALSE;
538   Lisp_Object tail;
539
540   /* Extract the properties from plist */
541   for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
542     {
543       Lisp_Object prop = Fcar (tail);
544       Lisp_Object val = Fcar (Fcdr (tail));
545
546       if (SYMBOLP (prop))
547         {
548           /* Kludge to handle the font property. */
549           if (EQ (prop, Qfont))
550             {
551               /* If the value is not a string we silently ignore it. */
552               if (STRINGP (val))
553                 {
554                   Lisp_Object frm, font_spec;
555                   
556                   XSETFRAME (frm, f);
557                   font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
558
559                   Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
560                   update_frame_face_values (f);
561                 }
562             }
563           else if (EQ (prop, Qwidth))
564             {
565               CHECK_INT (val);
566               width = XINT (val);
567               width_specified_p = TRUE;
568             }
569           else if (EQ (prop, Qheight))
570             {
571               CHECK_INT (val);
572               height = XINT (val);
573               height_specified_p = TRUE;
574             }
575           else if (EQ (prop, Qleft))
576             {
577               CHECK_INT (val);
578               x = XINT (val);
579               x_specified_p = TRUE;
580             }
581           else if (EQ (prop, Qtop))
582             {
583               CHECK_INT (val);
584               y = XINT (val);
585               y_specified_p = TRUE;
586             }
587         }
588     }
589
590   /* Now we've extracted the properties, apply them.
591      Do not apply geometric properties during frame creation. This
592      is excessive anyways, and this loses becuase WM_SIZE has not
593      been sent yet, so frame width and height fields are not initialized.
594      
595      unfortunately WM_SIZE loses as well since the resize is only
596      applied once and the first time WM_SIZE is applied not everything
597      is initialised in the frame (toolbars for instance). enabling
598      this always makes no visible difference and fixes a whole host of
599      bugs (and is more consistent with X) so I am going to reenable it.
600      --andyp */
601   if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
602        && (width_specified_p || height_specified_p
603            || x_specified_p || y_specified_p))
604     {
605       XEMACS_RECT_WH dest = { x, y, width, height };
606
607       mswindows_size_frame_internal (f, &dest);
608     }
609 }
610
611 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
612 {
613   RECT rect;
614   int pixel_width, pixel_height;
615   int size_p = (dest->width >=0 || dest->height >=0);
616   int move_p = (dest->top >=0 || dest->left >=0);
617   struct device* d = XDEVICE (FRAME_DEVICE (f));
618   char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height);
619   
620   if (dest->width < 0)
621     pixel_width = FRAME_PIXWIDTH (f);
622   if (dest->height < 0)
623     pixel_height = FRAME_PIXHEIGHT (f);
624
625   GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
626   if (dest->left < 0)
627     dest->left = rect.left;
628   if (dest->top < 0)
629     dest->top = rect.top;
630   
631   rect.left = rect.top = 0;
632   rect.right = pixel_width;
633   rect.bottom = pixel_height;
634
635   AdjustWindowRectEx (&rect,
636                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
637                       GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
638                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
639
640   /* resize and move the window so that it fits on the screen. This is
641   not restrictive since this will happen later anyway in WM_SIZE.  We
642   have to do this after adjusting the rect to account for menubar
643   etc. */
644   pixel_width = rect.right - rect.left;
645   pixel_height = rect.bottom - rect.top;
646   if (pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
647     {
648       pixel_width = DEVICE_MSWINDOWS_HORZRES(d);
649       size_p=1;
650     }
651   if (pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
652     {
653       pixel_height = DEVICE_MSWINDOWS_VERTRES(d);
654       size_p=1;
655     }
656
657   /* adjust position so window is on screen */
658   if (dest->left + pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
659     {
660       dest->left = DEVICE_MSWINDOWS_HORZRES(d) - pixel_width;
661       move_p=1;
662     }
663   if (dest->top + pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
664     {
665       dest->top = DEVICE_MSWINDOWS_VERTRES(d) - pixel_height;
666       move_p=1;
667     }
668
669   if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) 
670       || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
671     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
672
673   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
674                 dest->left, dest->top, pixel_width, pixel_height,
675                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
676                 | (size_p ? 0 : SWP_NOSIZE)
677                 | (move_p ? 0 : SWP_NOMOVE));
678 }
679
680 static Lisp_Object
681 mswindows_get_frame_parent (struct frame *f)
682 {
683   HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
684   hwnd = GetParent (hwnd);
685   if (hwnd)
686     {
687       Lisp_Object parent;
688       VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
689       assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
690       return parent;
691     }
692   else
693     return Qnil;
694 }
695
696 static void
697 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
698 {
699 }
700
701 static int
702 mswindows_frame_size_fixed_p (struct frame *f)
703 {
704   /* Frame size cannot change if the frame is maximized */
705   return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
706 }
707
708 /*---------------------------------------------------------------------*/
709 /*-----                    PRINTER FRAME                          -----*/
710 /*---------------------------------------------------------------------*/
711
712 void
713 msprinter_start_page (struct frame *f)
714 {
715   if (!FRAME_MSPRINTER_PAGE_STARTED (f))
716     {
717       FRAME_MSPRINTER_PAGE_STARTED (f) = 1;
718       StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
719     }
720 }
721
722 static void
723 error_frame_unsizable (struct frame *f)
724 {
725   Lisp_Object frame;
726   XSETFRAME (frame, f);
727   signal_simple_error ("Cannot resize frame (margins)"
728                        " after print job has started.", frame);
729 }
730
731 static void
732 maybe_error_if_job_active (struct frame *f)
733 {
734   if (FRAME_MSPRINTER_JOB_STARTED (f))
735     error_frame_unsizable (f);
736 }
737
738 static void
739 msprinter_init_frame_1 (struct frame *f, Lisp_Object props)
740 {
741   /* Make sure this is the only frame on device. Windows printer can
742      handle only one job at a time. */
743   if (!NILP (DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f)))))
744     error ("Only one frame (print job) at a time is allowed on "
745            "this printer device.");
746
747   f->frame_data = xnew_and_zero (struct msprinter_frame);
748
749   /* Default margin size is 1" = 1440 twips */
750   FRAME_MSPRINTER_TOP_MARGIN(f) = 1440;
751   FRAME_MSPRINTER_BOTTOM_MARGIN(f) = 1440;
752   FRAME_MSPRINTER_LEFT_MARGIN(f) = 1440;
753   FRAME_MSPRINTER_RIGHT_MARGIN(f) = 1440;
754
755   /* Negative for "uinspecified" */
756   FRAME_MSPRINTER_CHARWIDTH(f) = -1;
757   FRAME_MSPRINTER_CHARHEIGHT(f) = -1;
758
759   /* nil is for "system default" for these properties. */
760   FRAME_MSPRINTER_ORIENTATION(f) = Qnil;
761   FRAME_MSPRINTER_DUPLEX(f) = Qnil;
762 }
763
764 static void
765 msprinter_init_frame_3 (struct frame *f)
766 {
767   DOCINFO di;
768   struct device *device = XDEVICE (FRAME_DEVICE (f));
769   HDC hdc = DEVICE_MSPRINTER_HDC (device);
770   int frame_left, frame_top, frame_width, frame_height;
771
772   /* Change printer parameters */
773   {
774     DEVMODE* devmode = msprinter_get_devmode_copy (device);
775     devmode->dmFields = 0;
776
777     if (!NILP (FRAME_MSPRINTER_ORIENTATION(f)))
778       {
779         devmode->dmFields = DM_ORIENTATION;
780         if (EQ (FRAME_MSPRINTER_ORIENTATION(f), Qportrait))
781           devmode->dmOrientation = DMORIENT_PORTRAIT;
782         else if (EQ (FRAME_MSPRINTER_ORIENTATION(f), Qlandscape))
783           devmode->dmOrientation = DMORIENT_LANDSCAPE;
784         else
785           abort();
786       }
787
788     if (!NILP (FRAME_MSPRINTER_DUPLEX(f)))
789       {
790         devmode->dmFields = DM_DUPLEX;
791         if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qnone))
792           devmode->dmDuplex = DMDUP_SIMPLEX;
793         if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qvertical))
794           devmode->dmDuplex = DMDUP_VERTICAL;
795         if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qhorizontal))
796           devmode->dmDuplex = DMDUP_HORIZONTAL;
797         else
798           abort();
799       }
800
801     msprinter_apply_devmode (device, devmode);
802   }
803
804   /* Compute geometry properties */
805   frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
806                         FRAME_MSPRINTER_LEFT_MARGIN(f), 1440)
807                 - GetDeviceCaps (hdc, PHYSICALOFFSETX));
808   
809   if (FRAME_MSPRINTER_CHARWIDTH(f) > 0)
810     {
811       char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH(f), 0,
812                                &frame_width, NULL);
813       FRAME_MSPRINTER_RIGHT_MARGIN(f) = 
814         MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH)
815                 - (frame_left + frame_width), 1440,
816                 GetDeviceCaps (hdc, LOGPIXELSX));
817     }           
818   else
819     frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH)
820                    - frame_left
821                    - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
822                              FRAME_MSPRINTER_RIGHT_MARGIN(f), 1440));
823
824   frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
825                        FRAME_MSPRINTER_TOP_MARGIN(f), 1440)
826                - GetDeviceCaps (hdc, PHYSICALOFFSETY));
827
828   if (FRAME_MSPRINTER_CHARHEIGHT(f) > 0)
829     {
830       char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT(f),
831                                NULL, &frame_height);
832
833       FRAME_MSPRINTER_BOTTOM_MARGIN(f) = 
834         MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT)
835                 - (frame_top + frame_height), 1440,
836                 GetDeviceCaps (hdc, LOGPIXELSY));
837     }           
838   else
839     frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT)
840                     - frame_top
841                     - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
842                               FRAME_MSPRINTER_BOTTOM_MARGIN(f), 1440));
843
844   /* Geometry sanity checks */
845   if (!frame_pixsize_valid_p (f, frame_width, frame_height))
846     error ("Area inside print margins has shrunk to naught.");
847
848   if (frame_left < 0
849       || frame_top < 0
850       || frame_left + frame_width > GetDeviceCaps (hdc, HORZRES)
851       || frame_top + frame_height > GetDeviceCaps (hdc, VERTRES))
852     error ("Print area is ouside of the printer's hardware printable area.");
853
854   /* Apply XEmacs frame geometry and layout windows */
855   {
856     int rows, columns;
857     FRAME_PIXWIDTH(f) = frame_width;
858     FRAME_PIXHEIGHT(f) = frame_height;
859     pixel_to_char_size (f, frame_width, frame_height, &columns, &rows);
860     change_frame_size (f, rows, columns, 0);
861   }
862
863   /* Apply DC geometry */
864   SetTextAlign (hdc, TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
865   SetViewportOrgEx (hdc, frame_left, frame_top, NULL);
866   SetWindowOrgEx (hdc, 0, 0, NULL);
867
868   /* Start print job */
869   di.cbSize = sizeof (di);
870   di.lpszDocName = (STRINGP(f->name)
871                     ? (char*) XSTRING_DATA(f->name)
872                     : "XEmacs print document");
873   di.lpszOutput = NULL;
874   di.lpszDatatype = NULL;
875   di.fwType = 0;
876
877   if (StartDoc (hdc, &di) <= 0)
878     error ("Cannot start print job");
879
880   /* Finish frame setup */
881   FRAME_MSPRINTER_CDC(f) = CreateCompatibleDC (hdc);
882   FRAME_MSPRINTER_JOB_STARTED (f) = 1;
883   FRAME_VISIBLE_P(f) = 0;
884 }
885
886 static void
887 msprinter_mark_frame (struct frame *f)
888 {
889   /* NOTE: These need not be marked as long as we allow only c-defined
890      symbols for their values.  Although, marking these is safer than
891      expensive.  [I know a proof to the theorem postulating that a
892      gator is longer than greener. Ask me. -- kkm] */
893   mark_object (FRAME_MSPRINTER_ORIENTATION (f));
894   mark_object (FRAME_MSPRINTER_DUPLEX (f));
895 }
896
897 static void
898 msprinter_delete_frame (struct frame *f)
899 {
900   if (f->frame_data)
901     {
902       HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
903       if (FRAME_MSPRINTER_PAGE_STARTED (f))
904         EndPage (hdc);
905       if (FRAME_MSPRINTER_JOB_STARTED (f))
906         EndDoc (hdc);
907       if (FRAME_MSPRINTER_CDC(f))
908         DeleteDC (FRAME_MSPRINTER_CDC(f));
909       xfree (f->frame_data);
910     }
911
912   f->frame_data = 0;
913 }
914
915 static Lisp_Object
916 msprinter_frame_property (struct frame *f, Lisp_Object property)
917 {
918   if (EQ (Qleft_margin, property))
919     return make_int (FRAME_MSPRINTER_LEFT_MARGIN(f));
920   else if (EQ (Qtop_margin, property))
921     return make_int (FRAME_MSPRINTER_TOP_MARGIN(f));
922   if (EQ (Qright_margin, property))
923     return make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f));
924   else if (EQ (Qbottom_margin, property))
925     return make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f));
926   else if (EQ (Qorientation, property))
927     return FRAME_MSPRINTER_ORIENTATION(f);
928   else if (EQ (Qduplex, property))
929     return FRAME_MSPRINTER_DUPLEX(f);
930   else
931     return Qunbound;
932 }
933
934 static int
935 msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property)
936 {
937   return (EQ (Qleft_margin, property) || EQ (Qtop_margin, property) ||
938           EQ (Qright_margin, property) || EQ (Qbottom_margin, property) ||
939           EQ (Qorientation, property) || EQ (Qduplex, property));
940 }
941
942 static Lisp_Object
943 msprinter_frame_properties (struct frame *f)
944 {
945   Lisp_Object props = Qnil;
946   props = cons3 (Qorientation, FRAME_MSPRINTER_ORIENTATION(f), props);
947   props = cons3 (Qduplex, FRAME_MSPRINTER_DUPLEX(f), props);
948   props = cons3 (Qbottom_margin,
949                  make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f)), props);
950   props = cons3 (Qright_margin,
951                  make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f)), props);
952   props = cons3 (Qtop_margin,
953                  make_int (FRAME_MSPRINTER_TOP_MARGIN(f)), props);
954   props = cons3 (Qleft_margin,
955                  make_int (FRAME_MSPRINTER_LEFT_MARGIN(f)), props);
956   return props;
957 }
958
959 static void
960 msprinter_set_frame_properties (struct frame *f, Lisp_Object plist)
961 {
962   Lisp_Object tail;
963
964   /* Extract the properties from plist */
965   for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
966     {
967       Lisp_Object prop = Fcar (tail);
968       Lisp_Object val = Fcar (Fcdr (tail));
969
970       if (SYMBOLP (prop))
971         {
972           if (EQ (prop, Qwidth))
973             {
974               maybe_error_if_job_active (f);
975               if (!NILP (val))
976                 {
977                   CHECK_NATNUM (val);
978                   FRAME_MSPRINTER_CHARWIDTH(f) = XINT (val);
979                 }
980             }
981           if (EQ (prop, Qheight))
982             {
983               maybe_error_if_job_active (f);
984               if (!NILP (val))
985                 {
986                   CHECK_NATNUM (val);
987                   FRAME_MSPRINTER_CHARHEIGHT(f) = XINT (val);
988                 }
989             }
990           else if (EQ (prop, Qleft_margin))
991             {
992               maybe_error_if_job_active (f);
993               CHECK_NATNUM (val);
994               FRAME_MSPRINTER_LEFT_MARGIN(f) = XINT (val);
995             }
996           else if (EQ (prop, Qtop_margin))
997             {
998               maybe_error_if_job_active (f);
999               CHECK_NATNUM (val);
1000               FRAME_MSPRINTER_TOP_MARGIN(f) = XINT (val);
1001             }
1002           else if (EQ (prop, Qright_margin))
1003             {
1004               maybe_error_if_job_active (f);
1005               CHECK_NATNUM (val);
1006               FRAME_MSPRINTER_RIGHT_MARGIN(f) = XINT (val);
1007             }
1008           else if (EQ (prop, Qbottom_margin))
1009             {
1010               maybe_error_if_job_active (f);
1011               CHECK_NATNUM (val);
1012               FRAME_MSPRINTER_BOTTOM_MARGIN(f) = XINT (val);
1013             }
1014           else if (EQ (prop, Qorientation))
1015             {
1016               maybe_error_if_job_active (f);
1017               CHECK_SYMBOL (val);
1018               if (!NILP(val) &&
1019                   !EQ (val, Qportrait) &&
1020                   !EQ (val, Qlandscape))
1021                 signal_simple_error ("Page orientation can only be "
1022                                      "'portrait or 'landscape", val);
1023               FRAME_MSPRINTER_ORIENTATION(f) = val;
1024             }
1025           else if (EQ (prop, Qduplex))
1026             {
1027               maybe_error_if_job_active (f);
1028               CHECK_SYMBOL (val);
1029               if (!NILP(val) &&
1030                   !EQ (val, Qnone) &&
1031                   !EQ (val, Qvertical) &&
1032                   !EQ (val, Qhorizontal))
1033                 signal_simple_error ("Duplex can only be 'none, "
1034                                      "'vertical or 'horizontal", val);
1035               FRAME_MSPRINTER_DUPLEX(f) = val;
1036             }
1037         }
1038     }
1039 }
1040
1041 static void
1042 msprinter_set_frame_size (struct frame *f, int width, int height)
1043 {
1044   /* We're absolutely unsizeable */
1045   error_frame_unsizable (f);
1046 }
1047
1048 static void
1049 msprinter_eject_page (struct frame *f)
1050 {
1051   /* #### Should we eject empty pages? */
1052   if (FRAME_MSPRINTER_PAGE_STARTED (f))
1053     {
1054       FRAME_MSPRINTER_PAGE_STARTED (f) = 0;
1055       EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
1056     }
1057 }
1058
1059 \f
1060 void
1061 console_type_create_frame_mswindows (void)
1062 {
1063   /* Display frames */
1064   CONSOLE_HAS_METHOD (mswindows, init_frame_1);
1065   CONSOLE_HAS_METHOD (mswindows, init_frame_2); 
1066   CONSOLE_HAS_METHOD (mswindows, init_frame_3);
1067   CONSOLE_HAS_METHOD (mswindows, after_init_frame);
1068   CONSOLE_HAS_METHOD (mswindows, mark_frame);
1069   CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
1070   CONSOLE_HAS_METHOD (mswindows, delete_frame);
1071   CONSOLE_HAS_METHOD (mswindows, get_mouse_position);
1072   CONSOLE_HAS_METHOD (mswindows, set_mouse_position);
1073   CONSOLE_HAS_METHOD (mswindows, raise_frame);
1074   CONSOLE_HAS_METHOD (mswindows, lower_frame);
1075   CONSOLE_HAS_METHOD (mswindows, make_frame_visible);
1076   CONSOLE_HAS_METHOD (mswindows, make_frame_invisible);
1077   CONSOLE_HAS_METHOD (mswindows, iconify_frame);
1078   CONSOLE_HAS_METHOD (mswindows, set_frame_size);
1079   CONSOLE_HAS_METHOD (mswindows, set_frame_position);
1080   CONSOLE_HAS_METHOD (mswindows, frame_property);
1081   CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p);
1082   CONSOLE_HAS_METHOD (mswindows, frame_properties);
1083   CONSOLE_HAS_METHOD (mswindows, set_frame_properties);
1084   CONSOLE_HAS_METHOD (mswindows, set_title_from_bufbyte);
1085 /*  CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_bufbyte); */
1086   CONSOLE_HAS_METHOD (mswindows, frame_visible_p);
1087   CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p);
1088   CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
1089   CONSOLE_HAS_METHOD (mswindows, set_frame_pointer); 
1090   CONSOLE_HAS_METHOD (mswindows, set_frame_icon); 
1091   CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
1092   CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
1093   CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p);
1094
1095   /* Printer frames, aka print jobs */
1096   CONSOLE_HAS_METHOD (msprinter, init_frame_1);
1097   CONSOLE_HAS_METHOD (msprinter, init_frame_3);
1098   CONSOLE_HAS_METHOD (msprinter, mark_frame);
1099   CONSOLE_HAS_METHOD (msprinter, delete_frame);
1100   CONSOLE_HAS_METHOD (msprinter, frame_property);
1101   CONSOLE_HAS_METHOD (msprinter, internal_frame_property_p);
1102   CONSOLE_HAS_METHOD (msprinter, frame_properties);
1103   CONSOLE_HAS_METHOD (msprinter, set_frame_properties);
1104   CONSOLE_HAS_METHOD (msprinter, set_frame_size);
1105   CONSOLE_HAS_METHOD (msprinter, eject_page);
1106 }
1107
1108 void
1109 syms_of_frame_mswindows (void)
1110 {
1111 }
1112
1113 void
1114 reinit_vars_of_frame_mswindows (void)
1115 {
1116   /* Needn't staticpro -- see comment above.  */
1117   Vmswindows_frame_being_created = Qnil;
1118 }
1119
1120 void
1121 vars_of_frame_mswindows (void)
1122 {
1123   reinit_vars_of_frame_mswindows ();
1124
1125   DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /*
1126 Controls whether to use system or XEmacs defaults for frame size.
1127 If nil then reasonable defaults are used for intial frame sizes. If t
1128 then the system will choose default sizes for the frame.
1129 */ );
1130   Vmswindows_use_system_frame_size_defaults = Qnil;
1131   
1132   DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
1133 Plist of default frame-creation properties for mswindows frames.
1134 These override what is specified in `default-frame-plist', but are
1135 overridden by the arguments to the particular call to `make-frame'.
1136
1137 Note: In many cases, properties of a frame are available as specifiers
1138 instead of through the frame-properties mechanism.
1139
1140 Here is a list of recognized frame properties, other than those
1141 documented in `set-frame-properties' (they can be queried and
1142 set at any time, except as otherwise noted):
1143
1144   initially-unmapped            If non-nil, the frame will not be visible
1145                                 when it is created.  In this case, you
1146                                 need to call `make-frame-visible' to make
1147                                 the frame appear.
1148   popup                         If non-nil, it should be a frame, and this
1149                                 frame will be created as a "popup" frame
1150                                 whose parent is the given frame.  This
1151                                 will make the window manager treat the
1152                                 frame as a dialog box, which may entail
1153                                 doing different things (e.g. not asking
1154                                 for positioning, and not iconifying
1155                                 separate from its parent).
1156   top                           Y position (in pixels) of the upper-left
1157                                 outermost corner of the frame (i.e. the
1158                                 upper-left of the window-manager
1159                                 decorations).
1160   left                          X position (in pixels) of the upper-left
1161                                 outermost corner of the frame (i.e. the
1162                                 upper-left of the window-manager
1163                                 decorations).
1164
1165 See also `default-frame-plist', which specifies properties which apply
1166 to all frames, not just mswindows frames.
1167 */ );
1168   Vdefault_mswindows_frame_plist = Qnil;
1169
1170   mswindows_console_methods->device_specific_frame_props =
1171     &Vdefault_mswindows_frame_plist;
1172
1173   DEFVAR_LISP ("default-msprinter-frame-plist", &Vdefault_msprinter_frame_plist /*
1174 Plist of default frame-creation properties for msprinter print job frames.
1175 These override what is specified in `default-frame-plist', but are
1176 overridden by the arguments to the particular call to `make-frame'.
1177
1178 Note: In many cases, properties of a frame are available as specifiers
1179 instead of through the frame-properties mechanism.
1180
1181 Here is a list of recognized frame properties, other than those
1182 documented in `set-frame-properties' (they can be queried and
1183 set at any time, except as otherwise noted):
1184
1185   left-margin                   Margin of the page, in twips. Twip is a
1186   top-margin                    typographical unit of measurement,
1187   right-margin                  equal to 1/1440 of an inch, or 1/20 of a
1188   bottom-margin                 point, and roughly equal to 7/400 of a
1189                                 millimeter. If not specifified, each margin
1190                                 defaults to one inch (25.4 mm).
1191
1192      MARGINS NOTE. right-margin and bottom-margin are overridden by
1193        the height and width properties. If you want to specify size
1194        of the printable area in character, as with the rest of XEmacs,
1195        use these properties. If height and/or width are nil, then
1196        corresponding margin setting is taken into account. If you
1197        specify height and/or width in `default-frame-plist', but still
1198        want to specify right/bottom margins, set height/width in this
1199        plist to nil, as in this example:
1200
1201           (setq default-frame-plist '(height 55 'width 80)
1202                 default-msprinter-frame-plist '(height nil 'width nil))
1203
1204
1205   orientation                   Printer page orientation. Can be 'nil,
1206                                 indicating system default, 'portrait
1207                                 or 'landscape.
1208
1209   duplex                        Duplex printing mode, subject to printer
1210                                 support. Can be 'nil for the device default,
1211                                 'none for simplex printing, 'vertical or
1212                                 'horizontal for duplex page bound along
1213                                 the corresponding page direction.
1214
1215 See also `default-frame-plist', which specifies properties which apply
1216 to all frames, not just mswindows frames.
1217 */ );
1218   Vdefault_msprinter_frame_plist = Qnil;
1219
1220   msprinter_console_methods->device_specific_frame_props =
1221     &Vdefault_msprinter_frame_plist;
1222 }