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