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