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