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.
5 This file is part of XEmacs.
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
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
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. */
22 /* Synched up with: Not synched with FSF. */
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.
37 #include "console-msw.h"
38 #include "glyphs-msw.h"
43 #include "redisplay.h"
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)
50 #define MSWINDOWS_FRAME_EXSTYLE WS_EX_OVERLAPPEDWINDOW
51 #define MSWINDOWS_POPUP_EXSTYLE WS_EX_PALETTEWINDOW
53 /* Default popup left top corner offset from the same
54 corner of the parent frame, in pixel */
55 #define POPUP_OFFSET 30
57 /* Default popup size, in characters */
58 #define POPUP_WIDTH 30
59 #define POPUP_HEIGHT 10
61 /* Default regular frame size, in characters */
62 #define DEFAULT_FRAME_WIDTH 80
63 #define DEFAULT_FRAME_HEIGHT 35
66 #define ADJR_MENUFLAG TRUE
68 #define ADJR_MENUFLAG FALSE
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;
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;
80 /*---------------------------------------------------------------------*/
81 /*----- DISPLAY FRAME -----*/
82 /*---------------------------------------------------------------------*/
85 mswindows_init_frame_1 (struct frame *f, Lisp_Object props)
87 Lisp_Object initially_unmapped;
88 Lisp_Object name, height, width, popup, top, left;
89 Lisp_Object frame_obj = Qnil;
91 XEMACS_RECT_WH rect_default;
93 HWND hwnd, hwnd_parent;
95 /* Pick up relevant properties */
96 initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
97 name = Fplist_get (props, Qname, Qnil);
99 popup = Fplist_get (props, Qpopup, Qnil);
101 popup = Fselected_frame (Qnil);
103 left = Fplist_get (props, Qleft, Qnil);
107 top = Fplist_get (props, Qtop, Qnil);
111 width = Fplist_get (props, Qwidth, Qnil);
115 height = Fplist_get (props, Qheight, Qnil);
119 f->frame_data = xnew_and_zero (struct mswindows_frame);
120 FRAME_MSWINDOWS_TARGET_RECT (f) = xnew_and_zero (XEMACS_RECT_WH);
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 :
126 FRAME_MSWINDOWS_TARGET_RECT (f)->height = NILP (height) ? -1 :
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;
139 FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) =
140 make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
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 */
148 FRAME_HEIGHT (f) = 0;
149 FRAME_PIXWIDTH (f) = 0;
150 FRAME_PIXHEIGHT (f) = 0;
154 style = MSWINDOWS_FRAME_STYLE;
155 exstyle = MSWINDOWS_FRAME_EXSTYLE;
158 rect_default.left = rect_default.top = CW_USEDEFAULT;
159 rect_default.width = rect_default.height = CW_USEDEFAULT;
163 style = MSWINDOWS_POPUP_STYLE;
164 exstyle = MSWINDOWS_POPUP_EXSTYLE;
166 CHECK_MSWINDOWS_FRAME (popup);
167 hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
168 assert (IsWindow (hwnd_parent));
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);
181 AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
183 XSETFRAME (frame_obj, f);
185 Vmswindows_frame_being_created = frame_obj;
187 hwnd = CreateWindowEx (exstyle,
189 STRINGP(f->name) ? XSTRING_DATA(f->name) :
191 (const Extbyte*)XSTRING_DATA(name) :
192 (const Extbyte*)XEMACS_CLASS),
194 rect_default.left, rect_default.top,
195 rect_default.width, rect_default.height,
196 hwnd_parent, NULL, NULL, NULL);
198 Vmswindows_frame_being_created = Qnil;
201 error ("System call to create frame failed");
203 FRAME_MSWINDOWS_HANDLE(f) = hwnd;
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);
211 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
213 if (NILP (Vmswindows_use_system_frame_size_defaults))
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
219 XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH,
220 DEFAULT_FRAME_HEIGHT };
221 mswindows_size_frame_internal (f, &dest);
225 /* Called after frame's properties are set */
227 mswindows_init_frame_3 (struct frame *f)
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);
241 mswindows_after_init_frame (struct frame *f, int first_on_device,
242 int first_on_console)
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
251 if (first_on_console)
256 mswindows_mark_frame (struct frame *f)
258 mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
260 mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
262 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f));
266 mswindows_focus_on_frame (struct frame *f)
268 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
272 mswindows_delete_frame (struct frame *f)
276 ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
277 DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
278 xfree (f->frame_data);
284 mswindows_set_frame_size (struct frame *f, int width, int height)
287 rect.left = rect.top = 0;
289 rect.bottom = height;
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));
296 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
297 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
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);
305 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
307 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
309 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
313 mswindows_make_frame_visible (struct frame *f)
315 if (!FRAME_VISIBLE_P(f))
316 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
318 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOW);
324 mswindows_make_frame_invisible (struct frame *f)
326 if (!FRAME_VISIBLE_P(f))
329 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
334 mswindows_frame_totally_visible_p (struct frame *f)
336 RECT rc_me, rc_other, rc_temp;
337 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
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);
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))
351 /* Then see if any window above us obscures us */
352 while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
353 if (IsWindowVisible (hwnd))
355 GetWindowRect (hwnd, &rc_other);
356 if (IntersectRect(&rc_temp, &rc_me, &rc_other))
364 mswindows_frame_visible_p (struct frame *f)
366 return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
367 && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
372 mswindows_iconify_frame (struct frame *f)
374 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
380 mswindows_frame_iconified_p (struct frame *f)
382 return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
386 mswindows_set_frame_icon (struct frame *f)
388 if (IMAGE_INSTANCEP (f->icon)
389 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
391 if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
393 mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon),
397 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON,
398 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
403 mswindows_set_frame_pointer (struct frame *f)
405 if (IMAGE_INSTANCEP (f->pointer)
406 && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
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
413 SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
418 mswindows_set_mouse_position (struct window *w, int x, int y)
420 struct frame *f = XFRAME (w->frame);
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);
430 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
437 /* What's under cursor? */
438 hwnd = WindowFromPoint (pt);
442 /* Get grandest parent of the window */
445 while ((hwnd_parent = GetParent (hwnd)) != NULL)
449 /* Make sure it belongs to us */
450 if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
453 /* And that the window is an XEmacs frame */
455 char class_name [sizeof(XEMACS_CLASS) + 1];
456 if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
457 || strcmp (class_name, XEMACS_CLASS) != 0)
462 ScreenToClient (hwnd, &pt);
463 VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
470 mswindows_raise_frame (struct frame *f)
472 BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
476 mswindows_lower_frame (struct frame *f)
478 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
479 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
483 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title)
485 unsigned int new_checksum = hash_string (title, strlen (title));
486 if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
488 FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
489 SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
494 mswindows_frame_property (struct frame *f, Lisp_Object property)
496 if (EQ (Qleft, property) || EQ (Qtop, property))
499 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
500 return make_int (EQ (Qtop, property) ? rc.top : rc.left);
506 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
508 return EQ (property, Qleft)
509 || EQ (property, Qtop);
510 /* #### frame-x.c has also this. Why?
511 || STRINGP (property);
516 mswindows_frame_properties (struct frame *f)
518 Lisp_Object props = Qnil;
520 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
522 props = cons3 (Qtop, make_int (rc.top), props);
523 props = cons3 (Qleft, make_int (rc.left), props);
529 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
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;
539 /* Extract the properties from plist */
540 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
542 Lisp_Object prop = Fcar (tail);
543 Lisp_Object val = Fcar (Fcdr (tail));
547 /* Kludge to handle the font property. */
548 if (EQ (prop, Qfont))
550 /* If the value is not a string we silently ignore it. */
553 Lisp_Object frm, font_spec;
556 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
558 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
559 update_frame_face_values (f);
562 else if (EQ (prop, Qwidth))
566 width_specified_p = TRUE;
568 else if (EQ (prop, Qheight))
572 height_specified_p = TRUE;
574 else if (EQ (prop, Qleft))
578 x_specified_p = TRUE;
580 else if (EQ (prop, Qtop))
584 y_specified_p = TRUE;
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.
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.
600 if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
601 && (width_specified_p || height_specified_p
602 || x_specified_p || y_specified_p))
604 XEMACS_RECT_WH dest = { x, y, width, height };
606 mswindows_size_frame_internal (f, &dest);
610 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
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);
619 pixel_width = FRAME_PIXWIDTH (f);
620 if (dest->height < 0)
621 pixel_height = FRAME_PIXHEIGHT (f);
623 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
625 dest->left = rect.left;
627 dest->top = rect.top;
629 rect.left = rect.top = 0;
630 rect.right = pixel_width;
631 rect.bottom = pixel_height;
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));
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
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)
647 pixel_width = ws_rect.right - ws_rect.left;
650 if (pixel_height > ws_rect.bottom - ws_rect.top)
652 pixel_height = ws_rect.bottom - ws_rect.top;
656 /* adjust position so window is in workspace */
657 if (dest->left + pixel_width > ws_rect.right)
659 dest->left = ws_rect.right - pixel_width;
662 if (dest->left < ws_rect.left)
664 dest->left = ws_rect.left;
668 if (dest->top + pixel_height > ws_rect.bottom)
670 dest->top = ws_rect.bottom - pixel_height;
673 if (dest->top < ws_rect.top)
675 dest->top = ws_rect.top;
679 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f))
680 || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
681 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
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));
691 mswindows_get_frame_parent (struct frame *f)
693 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
694 hwnd = GetParent (hwnd);
698 VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
699 assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
707 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
712 mswindows_frame_size_fixed_p (struct frame *f)
714 /* Frame size cannot change if the frame is maximized */
715 return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
718 /*---------------------------------------------------------------------*/
719 /*----- PRINTER FRAME -----*/
720 /*---------------------------------------------------------------------*/
723 msprinter_start_page (struct frame *f)
725 if (!FRAME_MSPRINTER_PAGE_STARTED (f))
727 FRAME_MSPRINTER_PAGE_STARTED (f) = 1;
728 StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
733 error_frame_unsizable (struct frame *f)
736 XSETFRAME (frame, f);
737 signal_simple_error ("Cannot resize frame (margins)"
738 " after print job has started.", frame);
742 maybe_error_if_job_active (struct frame *f)
744 if (FRAME_MSPRINTER_JOB_STARTED (f))
745 error_frame_unsizable (f);
749 msprinter_init_frame_1 (struct frame *f, Lisp_Object props)
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.");
757 f->frame_data = xnew_and_zero (struct msprinter_frame);
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;
765 /* Negative for "uinspecified" */
766 FRAME_MSPRINTER_CHARWIDTH(f) = -1;
767 FRAME_MSPRINTER_CHARHEIGHT(f) = -1;
769 /* nil is for "system default" for these properties. */
770 FRAME_MSPRINTER_ORIENTATION(f) = Qnil;
771 FRAME_MSPRINTER_DUPLEX(f) = Qnil;
775 msprinter_init_frame_3 (struct frame *f)
778 struct device *device = XDEVICE (FRAME_DEVICE (f));
780 int frame_left, frame_top, frame_width, frame_height;
782 /* Change printer parameters */
784 DEVMODE* devmode = msprinter_get_devmode_copy (device);
785 devmode->dmFields = 0;
787 if (!NILP (FRAME_MSPRINTER_ORIENTATION(f)))
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;
798 if (!NILP (FRAME_MSPRINTER_DUPLEX(f)))
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;
811 assert (!FRAME_MSPRINTER_PAGE_STARTED (f));
812 msprinter_apply_devmode (device, devmode);
815 /* DC might be recreated in msprinter_apply_devmode,
816 so do not initialize until now */
817 hdc = DEVICE_MSPRINTER_HDC (device);
819 /* Compute geometry properties */
820 frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
821 FRAME_MSPRINTER_LEFT_MARGIN(f), 1440)
822 - GetDeviceCaps (hdc, PHYSICALOFFSETX));
824 if (FRAME_MSPRINTER_CHARWIDTH(f) > 0)
826 char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH(f), 0,
828 FRAME_MSPRINTER_RIGHT_MARGIN(f) =
829 MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH)
830 - (frame_left + frame_width), 1440,
831 GetDeviceCaps (hdc, LOGPIXELSX));
834 frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH)
836 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
837 FRAME_MSPRINTER_RIGHT_MARGIN(f), 1440));
839 frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
840 FRAME_MSPRINTER_TOP_MARGIN(f), 1440)
841 - GetDeviceCaps (hdc, PHYSICALOFFSETY));
843 if (FRAME_MSPRINTER_CHARHEIGHT(f) > 0)
845 char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT(f),
846 NULL, &frame_height);
848 FRAME_MSPRINTER_BOTTOM_MARGIN(f) =
849 MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT)
850 - (frame_top + frame_height), 1440,
851 GetDeviceCaps (hdc, LOGPIXELSY));
854 frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT)
856 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
857 FRAME_MSPRINTER_BOTTOM_MARGIN(f), 1440));
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.");
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.");
869 /* Apply XEmacs frame geometry and layout windows */
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);
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);
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;
892 if (StartDoc (hdc, &di) <= 0)
893 error ("Cannot start print job");
895 /* Finish frame setup */
896 FRAME_MSPRINTER_JOB_STARTED (f) = 1;
897 FRAME_VISIBLE_P(f) = 0;
901 msprinter_mark_frame (struct frame *f)
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));
912 msprinter_delete_frame (struct frame *f)
916 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
917 if (FRAME_MSPRINTER_PAGE_STARTED (f))
919 if (FRAME_MSPRINTER_JOB_STARTED (f))
921 xfree (f->frame_data);
928 msprinter_frame_property (struct frame *f, Lisp_Object property)
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);
947 msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property)
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));
955 msprinter_frame_properties (struct frame *f)
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);
972 msprinter_set_frame_properties (struct frame *f, Lisp_Object plist)
976 /* Extract the properties from plist */
977 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
979 Lisp_Object prop = Fcar (tail);
980 Lisp_Object val = Fcar (Fcdr (tail));
984 if (EQ (prop, Qwidth))
986 maybe_error_if_job_active (f);
990 FRAME_MSPRINTER_CHARWIDTH(f) = XINT (val);
993 if (EQ (prop, Qheight))
995 maybe_error_if_job_active (f);
999 FRAME_MSPRINTER_CHARHEIGHT(f) = XINT (val);
1002 else if (EQ (prop, Qleft_margin))
1004 maybe_error_if_job_active (f);
1006 FRAME_MSPRINTER_LEFT_MARGIN(f) = XINT (val);
1008 else if (EQ (prop, Qtop_margin))
1010 maybe_error_if_job_active (f);
1012 FRAME_MSPRINTER_TOP_MARGIN(f) = XINT (val);
1014 else if (EQ (prop, Qright_margin))
1016 maybe_error_if_job_active (f);
1018 FRAME_MSPRINTER_RIGHT_MARGIN(f) = XINT (val);
1020 else if (EQ (prop, Qbottom_margin))
1022 maybe_error_if_job_active (f);
1024 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = XINT (val);
1026 else if (EQ (prop, Qorientation))
1028 maybe_error_if_job_active (f);
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;
1037 else if (EQ (prop, Qduplex))
1039 maybe_error_if_job_active (f);
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;
1054 msprinter_set_frame_size (struct frame *f, int width, int height)
1056 /* We're absolutely unsizeable */
1057 error_frame_unsizable (f);
1061 msprinter_eject_page (struct frame *f)
1063 /* #### Should we eject empty pages? */
1064 if (FRAME_MSPRINTER_PAGE_STARTED (f))
1066 FRAME_MSPRINTER_PAGE_STARTED (f) = 0;
1067 EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
1073 console_type_create_frame_mswindows (void)
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);
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);
1121 syms_of_frame_mswindows (void)
1126 reinit_vars_of_frame_mswindows (void)
1128 /* Needn't staticpro -- see comment above. */
1129 Vmswindows_frame_being_created = Qnil;
1133 vars_of_frame_mswindows (void)
1135 reinit_vars_of_frame_mswindows ();
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.
1142 Vmswindows_use_system_frame_size_defaults = Qnil;
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'.
1149 Note: In many cases, properties of a frame are available as specifiers
1150 instead of through the frame-properties mechanism.
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):
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
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
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
1177 See also `default-frame-plist', which specifies properties which apply
1178 to all frames, not just mswindows frames.
1180 Vdefault_mswindows_frame_plist = Qnil;
1182 mswindows_console_methods->device_specific_frame_props =
1183 &Vdefault_mswindows_frame_plist;
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'.
1190 Note: In many cases, properties of a frame are available as specifiers
1191 instead of through the frame-properties mechanism.
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):
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).
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:
1213 (setq default-frame-plist '(height 55 'width 80)
1214 default-msprinter-frame-plist '(height nil 'width nil))
1217 orientation Printer page orientation. Can be 'nil,
1218 indicating system default, 'portrait
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.
1227 See also `default-frame-plist', which specifies properties which apply
1228 to all frames, not just mswindows frames.
1230 Vdefault_msprinter_frame_plist = Qnil;
1232 msprinter_console_methods->device_specific_frame_props =
1233 &Vdefault_msprinter_frame_plist;