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