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_MENU_HASH_TABLE(f) = Qnil;
132 FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) =
133 make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
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 */
145 FRAME_HEIGHT (f) = 0;
146 FRAME_PIXWIDTH (f) = 0;
147 FRAME_PIXHEIGHT (f) = 0;
151 style = MSWINDOWS_FRAME_STYLE;
152 exstyle = MSWINDOWS_FRAME_EXSTYLE;
155 rect_default.left = rect_default.top = CW_USEDEFAULT;
156 rect_default.width = rect_default.height = CW_USEDEFAULT;
160 style = MSWINDOWS_POPUP_STYLE;
161 exstyle = MSWINDOWS_POPUP_EXSTYLE;
163 CHECK_MSWINDOWS_FRAME (popup);
164 hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
165 assert (IsWindow (hwnd_parent));
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);
178 AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
180 XSETFRAME (frame_obj, f);
182 Vmswindows_frame_being_created = frame_obj;
184 hwnd = CreateWindowEx (exstyle,
186 STRINGP(f->name) ? XSTRING_DATA(f->name) :
188 (const Extbyte*)XSTRING_DATA(name) :
189 (const Extbyte*)XEMACS_CLASS),
191 rect_default.left, rect_default.top,
192 rect_default.width, rect_default.height,
193 hwnd_parent, NULL, NULL, NULL);
195 Vmswindows_frame_being_created = Qnil;
198 error ("System call to create frame failed");
200 FRAME_MSWINDOWS_HANDLE(f) = hwnd;
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);
208 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
210 if (NILP (Vmswindows_use_system_frame_size_defaults))
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
216 XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH,
217 DEFAULT_FRAME_HEIGHT };
218 mswindows_size_frame_internal (f, &dest);
222 /* Called after frame's properties are set */
224 mswindows_init_frame_3 (struct frame *f)
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);
238 mswindows_after_init_frame (struct frame *f, int first_on_device,
239 int first_on_console)
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
248 if (first_on_console)
253 mswindows_mark_frame (struct frame *f)
255 mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
257 mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
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));
265 mswindows_focus_on_frame (struct frame *f)
267 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
271 mswindows_delete_frame (struct frame *f)
275 ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
276 DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
277 xfree (f->frame_data);
283 mswindows_set_frame_size (struct frame *f, int width, int height)
286 rect.left = rect.top = 0;
288 rect.bottom = height;
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));
295 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
296 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
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);
304 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
306 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
308 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
312 mswindows_make_frame_visible (struct frame *f)
314 if (!FRAME_VISIBLE_P(f))
315 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
317 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOW);
323 mswindows_make_frame_invisible (struct frame *f)
325 if (!FRAME_VISIBLE_P(f))
328 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
333 mswindows_frame_totally_visible_p (struct frame *f)
335 RECT rc_me, rc_other, rc_temp;
336 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
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);
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))
350 /* Then see if any window above us obscures us */
351 while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
352 if (IsWindowVisible (hwnd))
354 GetWindowRect (hwnd, &rc_other);
355 if (IntersectRect(&rc_temp, &rc_me, &rc_other))
363 mswindows_frame_visible_p (struct frame *f)
365 return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
366 && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
371 mswindows_iconify_frame (struct frame *f)
373 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
379 mswindows_frame_iconified_p (struct frame *f)
381 return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
385 mswindows_set_frame_icon (struct frame *f)
387 if (IMAGE_INSTANCEP (f->icon)
388 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
390 if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
392 mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon),
396 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON,
397 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
402 mswindows_set_frame_pointer (struct frame *f)
404 if (IMAGE_INSTANCEP (f->pointer)
405 && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
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
412 SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
417 mswindows_set_mouse_position (struct window *w, int x, int y)
419 struct frame *f = XFRAME (w->frame);
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);
429 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
436 /* What's under cursor? */
437 hwnd = WindowFromPoint (pt);
441 /* Get grandest parent of the window */
444 while ((hwnd_parent = GetParent (hwnd)) != NULL)
448 /* Make sure it belongs to us */
449 if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
452 /* And that the window is an XEmacs frame */
454 char class_name [sizeof(XEMACS_CLASS) + 1];
455 if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
456 || strcmp (class_name, XEMACS_CLASS) != 0)
461 ScreenToClient (hwnd, &pt);
462 VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
469 mswindows_raise_frame (struct frame *f)
471 BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
475 mswindows_lower_frame (struct frame *f)
477 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
478 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
482 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title)
484 unsigned int new_checksum = hash_string (title, strlen (title));
485 if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
487 FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
488 SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
493 mswindows_frame_property (struct frame *f, Lisp_Object property)
495 if (EQ (Qleft, property) || EQ (Qtop, property))
498 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
499 return make_int (EQ (Qtop, property) ? rc.top : rc.left);
505 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
507 return EQ (property, Qleft)
508 || EQ (property, Qtop);
509 /* #### frame-x.c has also this. Why?
510 || STRINGP (property);
515 mswindows_frame_properties (struct frame *f)
517 Lisp_Object props = Qnil;
519 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
521 props = cons3 (Qtop, make_int (rc.top), props);
522 props = cons3 (Qleft, make_int (rc.left), props);
528 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
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;
538 /* Extract the properties from plist */
539 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
541 Lisp_Object prop = Fcar (tail);
542 Lisp_Object val = Fcar (Fcdr (tail));
546 /* Kludge to handle the font property. */
547 if (EQ (prop, Qfont))
549 /* If the value is not a string we silently ignore it. */
552 Lisp_Object frm, font_spec;
555 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
557 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
558 update_frame_face_values (f);
561 else if (EQ (prop, Qwidth))
565 width_specified_p = TRUE;
567 else if (EQ (prop, Qheight))
571 height_specified_p = TRUE;
573 else if (EQ (prop, Qleft))
577 x_specified_p = TRUE;
579 else if (EQ (prop, Qtop))
583 y_specified_p = TRUE;
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.
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.
599 if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
600 && (width_specified_p || height_specified_p
601 || x_specified_p || y_specified_p))
603 XEMACS_RECT_WH dest = { x, y, width, height };
605 mswindows_size_frame_internal (f, &dest);
609 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
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);
618 pixel_width = FRAME_PIXWIDTH (f);
619 if (dest->height < 0)
620 pixel_height = FRAME_PIXHEIGHT (f);
622 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
624 dest->left = rect.left;
626 dest->top = rect.top;
628 rect.left = rect.top = 0;
629 rect.right = pixel_width;
630 rect.bottom = pixel_height;
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));
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
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)
646 pixel_width = ws_rect.right - ws_rect.left;
649 if (pixel_height > ws_rect.bottom - ws_rect.top)
651 pixel_height = ws_rect.bottom - ws_rect.top;
655 /* adjust position so window is in workspace */
656 if (dest->left + pixel_width > ws_rect.right)
658 dest->left = ws_rect.right - pixel_width;
661 if (dest->left < ws_rect.left)
663 dest->left = ws_rect.left;
667 if (dest->top + pixel_height > ws_rect.bottom)
669 dest->top = ws_rect.bottom - pixel_height;
672 if (dest->top < ws_rect.top)
674 dest->top = ws_rect.top;
678 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f))
679 || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
680 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
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));
690 mswindows_get_frame_parent (struct frame *f)
692 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
693 hwnd = GetParent (hwnd);
697 VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
698 assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
706 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
711 mswindows_frame_size_fixed_p (struct frame *f)
713 /* Frame size cannot change if the frame is maximized */
714 return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
717 /*---------------------------------------------------------------------*/
718 /*----- PRINTER FRAME -----*/
719 /*---------------------------------------------------------------------*/
722 msprinter_start_page (struct frame *f)
724 if (!FRAME_MSPRINTER_PAGE_STARTED (f))
726 FRAME_MSPRINTER_PAGE_STARTED (f) = 1;
727 StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
732 error_frame_unsizable (struct frame *f)
735 XSETFRAME (frame, f);
736 signal_simple_error ("Cannot resize frame (margins)"
737 " after print job has started.", frame);
741 maybe_error_if_job_active (struct frame *f)
743 if (FRAME_MSPRINTER_JOB_STARTED (f))
744 error_frame_unsizable (f);
748 msprinter_init_frame_1 (struct frame *f, Lisp_Object props)
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.");
756 f->frame_data = xnew_and_zero (struct msprinter_frame);
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;
764 /* Negative for "uinspecified" */
765 FRAME_MSPRINTER_CHARWIDTH(f) = -1;
766 FRAME_MSPRINTER_CHARHEIGHT(f) = -1;
768 /* nil is for "system default" for these properties. */
769 FRAME_MSPRINTER_ORIENTATION(f) = Qnil;
770 FRAME_MSPRINTER_DUPLEX(f) = Qnil;
774 msprinter_init_frame_3 (struct frame *f)
777 struct device *device = XDEVICE (FRAME_DEVICE (f));
779 int frame_left, frame_top, frame_width, frame_height;
781 /* Change printer parameters */
783 DEVMODE* devmode = msprinter_get_devmode_copy (device);
784 devmode->dmFields = 0;
786 if (!NILP (FRAME_MSPRINTER_ORIENTATION(f)))
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;
797 if (!NILP (FRAME_MSPRINTER_DUPLEX(f)))
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;
810 assert (!FRAME_MSPRINTER_PAGE_STARTED (f));
811 msprinter_apply_devmode (device, devmode);
814 /* DC might be recreated in msprinter_apply_devmode,
815 so do not initialize until now */
816 hdc = DEVICE_MSPRINTER_HDC (device);
818 /* Compute geometry properties */
819 frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
820 FRAME_MSPRINTER_LEFT_MARGIN(f), 1440)
821 - GetDeviceCaps (hdc, PHYSICALOFFSETX));
823 if (FRAME_MSPRINTER_CHARWIDTH(f) > 0)
825 char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH(f), 0,
827 FRAME_MSPRINTER_RIGHT_MARGIN(f) =
828 MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH)
829 - (frame_left + frame_width), 1440,
830 GetDeviceCaps (hdc, LOGPIXELSX));
833 frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH)
835 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
836 FRAME_MSPRINTER_RIGHT_MARGIN(f), 1440));
838 frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
839 FRAME_MSPRINTER_TOP_MARGIN(f), 1440)
840 - GetDeviceCaps (hdc, PHYSICALOFFSETY));
842 if (FRAME_MSPRINTER_CHARHEIGHT(f) > 0)
844 char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT(f),
845 NULL, &frame_height);
847 FRAME_MSPRINTER_BOTTOM_MARGIN(f) =
848 MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT)
849 - (frame_top + frame_height), 1440,
850 GetDeviceCaps (hdc, LOGPIXELSY));
853 frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT)
855 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
856 FRAME_MSPRINTER_BOTTOM_MARGIN(f), 1440));
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.");
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.");
868 /* Apply XEmacs frame geometry and layout windows */
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);
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);
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;
891 if (StartDoc (hdc, &di) <= 0)
892 error ("Cannot start print job");
894 /* Finish frame setup */
895 FRAME_MSPRINTER_JOB_STARTED (f) = 1;
896 FRAME_VISIBLE_P(f) = 0;
900 msprinter_mark_frame (struct frame *f)
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));
911 msprinter_delete_frame (struct frame *f)
915 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
916 if (FRAME_MSPRINTER_PAGE_STARTED (f))
918 if (FRAME_MSPRINTER_JOB_STARTED (f))
920 xfree (f->frame_data);
927 msprinter_frame_property (struct frame *f, Lisp_Object property)
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);
946 msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property)
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));
954 msprinter_frame_properties (struct frame *f)
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);
971 msprinter_set_frame_properties (struct frame *f, Lisp_Object plist)
975 /* Extract the properties from plist */
976 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
978 Lisp_Object prop = Fcar (tail);
979 Lisp_Object val = Fcar (Fcdr (tail));
983 if (EQ (prop, Qwidth))
985 maybe_error_if_job_active (f);
989 FRAME_MSPRINTER_CHARWIDTH(f) = XINT (val);
992 if (EQ (prop, Qheight))
994 maybe_error_if_job_active (f);
998 FRAME_MSPRINTER_CHARHEIGHT(f) = XINT (val);
1001 else if (EQ (prop, Qleft_margin))
1003 maybe_error_if_job_active (f);
1005 FRAME_MSPRINTER_LEFT_MARGIN(f) = XINT (val);
1007 else if (EQ (prop, Qtop_margin))
1009 maybe_error_if_job_active (f);
1011 FRAME_MSPRINTER_TOP_MARGIN(f) = XINT (val);
1013 else if (EQ (prop, Qright_margin))
1015 maybe_error_if_job_active (f);
1017 FRAME_MSPRINTER_RIGHT_MARGIN(f) = XINT (val);
1019 else if (EQ (prop, Qbottom_margin))
1021 maybe_error_if_job_active (f);
1023 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = XINT (val);
1025 else if (EQ (prop, Qorientation))
1027 maybe_error_if_job_active (f);
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;
1036 else if (EQ (prop, Qduplex))
1038 maybe_error_if_job_active (f);
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;
1053 msprinter_set_frame_size (struct frame *f, int width, int height)
1055 /* We're absolutely unsizeable */
1056 error_frame_unsizable (f);
1060 msprinter_eject_page (struct frame *f)
1062 /* #### Should we eject empty pages? */
1063 if (FRAME_MSPRINTER_PAGE_STARTED (f))
1065 FRAME_MSPRINTER_PAGE_STARTED (f) = 0;
1066 EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
1072 console_type_create_frame_mswindows (void)
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);
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);
1120 syms_of_frame_mswindows (void)
1125 reinit_vars_of_frame_mswindows (void)
1127 /* Needn't staticpro -- see comment above. */
1128 Vmswindows_frame_being_created = Qnil;
1132 vars_of_frame_mswindows (void)
1134 reinit_vars_of_frame_mswindows ();
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.
1141 Vmswindows_use_system_frame_size_defaults = Qnil;
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'.
1148 Note: In many cases, properties of a frame are available as specifiers
1149 instead of through the frame-properties mechanism.
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):
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
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
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
1176 See also `default-frame-plist', which specifies properties which apply
1177 to all frames, not just mswindows frames.
1179 Vdefault_mswindows_frame_plist = Qnil;
1181 mswindows_console_methods->device_specific_frame_props =
1182 &Vdefault_mswindows_frame_plist;
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'.
1189 Note: In many cases, properties of a frame are available as specifiers
1190 instead of through the frame-properties mechanism.
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):
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).
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:
1212 (setq default-frame-plist '(height 55 'width 80)
1213 default-msprinter-frame-plist '(height nil 'width nil))
1216 orientation Printer page orientation. Can be 'nil,
1217 indicating system default, 'portrait
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.
1226 See also `default-frame-plist', which specifies properties which apply
1227 to all frames, not just mswindows frames.
1229 Vdefault_msprinter_frame_plist = Qnil;
1231 msprinter_console_methods->device_specific_frame_props =
1232 &Vdefault_msprinter_frame_plist;