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