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 popup 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_MENU_HASH_TABLE(f) = Qnil;
138 FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) =
139 make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
141 /* hashtable of instantiated glyphs on the frame. */
142 FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f) =
143 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
144 /* Will initialize these in WM_SIZE handler. We cannot do it now,
145 because we do not know what is CW_USEDEFAULT height and width */
147 FRAME_HEIGHT (f) = 0;
148 FRAME_PIXWIDTH (f) = 0;
149 FRAME_PIXHEIGHT (f) = 0;
153 style = MSWINDOWS_FRAME_STYLE;
154 exstyle = MSWINDOWS_FRAME_EXSTYLE;
157 rect_default.left = rect_default.top = CW_USEDEFAULT;
158 rect_default.width = rect_default.height = CW_USEDEFAULT;
162 style = MSWINDOWS_POPUP_STYLE;
163 exstyle = MSWINDOWS_POPUP_EXSTYLE;
165 CHECK_MSWINDOWS_FRAME (popup);
166 hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
167 assert (IsWindow (hwnd_parent));
169 /* We cannot use CW_USEDEFAULT when creating a popup window.
170 So by default, we offset the new popup 30 pixels right
171 and down from its parent, and give it size of 30x10 characters.
172 These dimensions look adequate on both high and low res monitors */
173 GetWindowRect (hwnd_parent, &rect);
174 rect_default.left = rect.left + POPUP_OFFSET;
175 rect_default.top = rect.top + POPUP_OFFSET;
176 char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
177 &rect_default.width, &rect_default.height);
180 AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
182 XSETFRAME (frame_obj, f);
184 Vmswindows_frame_being_created = frame_obj;
186 hwnd = CreateWindowEx (exstyle,
188 STRINGP(f->name) ? XSTRING_DATA(f->name) :
190 (const Extbyte*)XSTRING_DATA(name) :
191 (const Extbyte*)XEMACS_CLASS),
193 rect_default.left, rect_default.top,
194 rect_default.width, rect_default.height,
195 hwnd_parent, NULL, NULL, NULL);
197 Vmswindows_frame_being_created = Qnil;
200 error ("System call to create frame failed");
202 FRAME_MSWINDOWS_HANDLE(f) = hwnd;
204 SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
205 FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
206 FRAME_MSWINDOWS_CDC(f) = CreateCompatibleDC (FRAME_MSWINDOWS_CDC(f));
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 DeleteDC(FRAME_MSWINDOWS_CDC(f));
277 ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
278 DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
279 xfree (f->frame_data);
285 mswindows_set_frame_size (struct frame *f, int width, int height)
288 rect.left = rect.top = 0;
290 rect.bottom = height;
292 AdjustWindowRectEx (&rect,
293 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
294 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
295 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
297 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
298 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
300 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
301 0, 0, rect.right-rect.left, rect.bottom-rect.top,
302 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
306 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
308 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
310 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
314 mswindows_make_frame_visible (struct frame *f)
316 if (!FRAME_VISIBLE_P(f))
317 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
319 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOW);
325 mswindows_make_frame_invisible (struct frame *f)
327 if (!FRAME_VISIBLE_P(f))
330 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
335 mswindows_frame_totally_visible_p (struct frame *f)
337 RECT rc_me, rc_other, rc_temp;
338 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
340 /* We test against not a whole window rectangle, only against its
341 client part. So, if non-client are is covered and client area is
342 not, we return true. */
343 GetClientRect (hwnd, &rc_me);
344 MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2);
346 /* First see if we're off the desktop */
347 GetWindowRect (GetDesktopWindow(), &rc_other);
348 UnionRect(&rc_temp, &rc_me, &rc_other);
349 if (!EqualRect (&rc_temp, &rc_other))
352 /* Then see if any window above us obscures us */
353 while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
354 if (IsWindowVisible (hwnd))
356 GetWindowRect (hwnd, &rc_other);
357 if (IntersectRect(&rc_temp, &rc_me, &rc_other))
365 mswindows_frame_visible_p (struct frame *f)
367 return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
368 && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
373 mswindows_iconify_frame (struct frame *f)
375 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
381 mswindows_frame_iconified_p (struct frame *f)
383 return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
387 mswindows_set_frame_icon (struct frame *f)
389 if (IMAGE_INSTANCEP (f->icon)
390 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
392 if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
394 mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon),
398 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON,
399 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
404 mswindows_set_frame_pointer (struct frame *f)
406 if (IMAGE_INSTANCEP (f->pointer)
407 && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
409 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR,
410 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
411 /* we only have to do this because GC doesn't cause a mouse
412 event and doesn't give time to event processing even if it
414 SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
419 mswindows_set_mouse_position (struct window *w, int x, int y)
421 struct frame *f = XFRAME (w->frame);
424 pt.x = w->pixel_left + x;
425 pt.y = w->pixel_top + y;
426 ClientToScreen (FRAME_MSWINDOWS_HANDLE(f), &pt);
427 SetCursorPos (pt.x, pt.y);
431 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
438 /* What's under cursor? */
439 hwnd = WindowFromPoint (pt);
443 /* Get grandest parent of the window */
446 while ((hwnd_parent = GetParent (hwnd)) != NULL)
450 /* Make sure it belongs to us */
451 if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
454 /* And that the window is an XEmacs frame */
456 char class_name [sizeof(XEMACS_CLASS) + 1];
457 if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
458 || strcmp (class_name, XEMACS_CLASS) != 0)
463 ScreenToClient (hwnd, &pt);
464 VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
471 mswindows_raise_frame (struct frame *f)
473 BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
477 mswindows_lower_frame (struct frame *f)
479 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
480 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
484 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title)
486 unsigned int new_checksum = hash_string (title, strlen (title));
487 if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
489 FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
490 SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
495 mswindows_frame_property (struct frame *f, Lisp_Object property)
497 if (EQ (Qleft, property) || EQ (Qtop, property))
500 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
501 return make_int (EQ (Qtop, property) ? rc.top : rc.left);
507 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
509 return EQ (property, Qleft)
510 || EQ (property, Qtop);
511 /* #### frame-x.c has also this. Why?
512 || STRINGP (property);
517 mswindows_frame_properties (struct frame *f)
519 Lisp_Object props = Qnil;
521 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
523 props = cons3 (Qtop, make_int (rc.top), props);
524 props = cons3 (Qleft, make_int (rc.left), props);
530 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
533 int width = -1, height = -1;
534 BOOL width_specified_p = FALSE;
535 BOOL height_specified_p = FALSE;
536 BOOL x_specified_p = FALSE;
537 BOOL y_specified_p = FALSE;
540 /* Extract the properties from plist */
541 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
543 Lisp_Object prop = Fcar (tail);
544 Lisp_Object val = Fcar (Fcdr (tail));
548 /* Kludge to handle the font property. */
549 if (EQ (prop, Qfont))
551 /* If the value is not a string we silently ignore it. */
554 Lisp_Object frm, font_spec;
557 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
559 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
560 update_frame_face_values (f);
563 else if (EQ (prop, Qwidth))
567 width_specified_p = TRUE;
569 else if (EQ (prop, Qheight))
573 height_specified_p = TRUE;
575 else if (EQ (prop, Qleft))
579 x_specified_p = TRUE;
581 else if (EQ (prop, Qtop))
585 y_specified_p = TRUE;
590 /* Now we've extracted the properties, apply them.
591 Do not apply geometric properties during frame creation. This
592 is excessive anyways, and this loses becuase WM_SIZE has not
593 been sent yet, so frame width and height fields are not initialized.
595 unfortunately WM_SIZE loses as well since the resize is only
596 applied once and the first time WM_SIZE is applied not everything
597 is initialised in the frame (toolbars for instance). enabling
598 this always makes no visible difference and fixes a whole host of
599 bugs (and is more consistent with X) so I am going to reenable it.
601 if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
602 && (width_specified_p || height_specified_p
603 || x_specified_p || y_specified_p))
605 XEMACS_RECT_WH dest = { x, y, width, height };
607 mswindows_size_frame_internal (f, &dest);
611 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
614 int pixel_width, pixel_height;
615 int size_p = (dest->width >=0 || dest->height >=0);
616 int move_p = (dest->top >=0 || dest->left >=0);
617 struct device* d = XDEVICE (FRAME_DEVICE (f));
618 char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height);
621 pixel_width = FRAME_PIXWIDTH (f);
622 if (dest->height < 0)
623 pixel_height = FRAME_PIXHEIGHT (f);
625 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
627 dest->left = rect.left;
629 dest->top = rect.top;
631 rect.left = rect.top = 0;
632 rect.right = pixel_width;
633 rect.bottom = pixel_height;
635 AdjustWindowRectEx (&rect,
636 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
637 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
638 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
640 /* resize and move the window so that it fits on the screen. This is
641 not restrictive since this will happen later anyway in WM_SIZE. We
642 have to do this after adjusting the rect to account for menubar
644 pixel_width = rect.right - rect.left;
645 pixel_height = rect.bottom - rect.top;
646 if (pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
648 pixel_width = DEVICE_MSWINDOWS_HORZRES(d);
651 if (pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
653 pixel_height = DEVICE_MSWINDOWS_VERTRES(d);
657 /* adjust position so window is on screen */
658 if (dest->left + pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
660 dest->left = DEVICE_MSWINDOWS_HORZRES(d) - pixel_width;
663 if (dest->top + pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
665 dest->top = DEVICE_MSWINDOWS_VERTRES(d) - pixel_height;
669 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f))
670 || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
671 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
673 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
674 dest->left, dest->top, pixel_width, pixel_height,
675 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
676 | (size_p ? 0 : SWP_NOSIZE)
677 | (move_p ? 0 : SWP_NOMOVE));
681 mswindows_get_frame_parent (struct frame *f)
683 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
684 hwnd = GetParent (hwnd);
688 VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
689 assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
697 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
702 mswindows_frame_size_fixed_p (struct frame *f)
704 /* Frame size cannot change if the frame is maximized */
705 return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
708 /*---------------------------------------------------------------------*/
709 /*----- PRINTER FRAME -----*/
710 /*---------------------------------------------------------------------*/
713 msprinter_start_page (struct frame *f)
715 if (!FRAME_MSPRINTER_PAGE_STARTED (f))
717 FRAME_MSPRINTER_PAGE_STARTED (f) = 1;
718 StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
723 error_frame_unsizable (struct frame *f)
726 XSETFRAME (frame, f);
727 signal_simple_error ("Cannot resize frame (margins)"
728 " after print job has started.", frame);
732 maybe_error_if_job_active (struct frame *f)
734 if (FRAME_MSPRINTER_JOB_STARTED (f))
735 error_frame_unsizable (f);
739 msprinter_init_frame_1 (struct frame *f, Lisp_Object props)
741 /* Make sure this is the only frame on device. Windows printer can
742 handle only one job at a time. */
743 if (!NILP (DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f)))))
744 error ("Only one frame (print job) at a time is allowed on "
745 "this printer device.");
747 f->frame_data = xnew_and_zero (struct msprinter_frame);
749 /* Default margin size is 1" = 1440 twips */
750 FRAME_MSPRINTER_TOP_MARGIN(f) = 1440;
751 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = 1440;
752 FRAME_MSPRINTER_LEFT_MARGIN(f) = 1440;
753 FRAME_MSPRINTER_RIGHT_MARGIN(f) = 1440;
755 /* Negative for "uinspecified" */
756 FRAME_MSPRINTER_CHARWIDTH(f) = -1;
757 FRAME_MSPRINTER_CHARHEIGHT(f) = -1;
759 /* nil is for "system default" for these properties. */
760 FRAME_MSPRINTER_ORIENTATION(f) = Qnil;
761 FRAME_MSPRINTER_DUPLEX(f) = Qnil;
765 msprinter_init_frame_3 (struct frame *f)
768 struct device *device = XDEVICE (FRAME_DEVICE (f));
769 HDC hdc = DEVICE_MSPRINTER_HDC (device);
770 int frame_left, frame_top, frame_width, frame_height;
772 /* Change printer parameters */
774 DEVMODE* devmode = msprinter_get_devmode_copy (device);
775 devmode->dmFields = 0;
777 if (!NILP (FRAME_MSPRINTER_ORIENTATION(f)))
779 devmode->dmFields = DM_ORIENTATION;
780 if (EQ (FRAME_MSPRINTER_ORIENTATION(f), Qportrait))
781 devmode->dmOrientation = DMORIENT_PORTRAIT;
782 else if (EQ (FRAME_MSPRINTER_ORIENTATION(f), Qlandscape))
783 devmode->dmOrientation = DMORIENT_LANDSCAPE;
788 if (!NILP (FRAME_MSPRINTER_DUPLEX(f)))
790 devmode->dmFields = DM_DUPLEX;
791 if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qnone))
792 devmode->dmDuplex = DMDUP_SIMPLEX;
793 if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qvertical))
794 devmode->dmDuplex = DMDUP_VERTICAL;
795 if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qhorizontal))
796 devmode->dmDuplex = DMDUP_HORIZONTAL;
801 msprinter_apply_devmode (device, devmode);
804 /* Compute geometry properties */
805 frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
806 FRAME_MSPRINTER_LEFT_MARGIN(f), 1440)
807 - GetDeviceCaps (hdc, PHYSICALOFFSETX));
809 if (FRAME_MSPRINTER_CHARWIDTH(f) > 0)
811 char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH(f), 0,
813 FRAME_MSPRINTER_RIGHT_MARGIN(f) =
814 MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH)
815 - (frame_left + frame_width), 1440,
816 GetDeviceCaps (hdc, LOGPIXELSX));
819 frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH)
821 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
822 FRAME_MSPRINTER_RIGHT_MARGIN(f), 1440));
824 frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
825 FRAME_MSPRINTER_TOP_MARGIN(f), 1440)
826 - GetDeviceCaps (hdc, PHYSICALOFFSETY));
828 if (FRAME_MSPRINTER_CHARHEIGHT(f) > 0)
830 char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT(f),
831 NULL, &frame_height);
833 FRAME_MSPRINTER_BOTTOM_MARGIN(f) =
834 MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT)
835 - (frame_top + frame_height), 1440,
836 GetDeviceCaps (hdc, LOGPIXELSY));
839 frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT)
841 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
842 FRAME_MSPRINTER_BOTTOM_MARGIN(f), 1440));
844 /* Geometry sanity checks */
845 if (!frame_pixsize_valid_p (f, frame_width, frame_height))
846 error ("Area inside print margins has shrunk to naught.");
850 || frame_left + frame_width > GetDeviceCaps (hdc, HORZRES)
851 || frame_top + frame_height > GetDeviceCaps (hdc, VERTRES))
852 error ("Print area is ouside of the printer's hardware printable area.");
854 /* Apply XEmacs frame geometry and layout windows */
857 FRAME_PIXWIDTH(f) = frame_width;
858 FRAME_PIXHEIGHT(f) = frame_height;
859 pixel_to_char_size (f, frame_width, frame_height, &columns, &rows);
860 change_frame_size (f, rows, columns, 0);
863 /* Apply DC geometry */
864 SetTextAlign (hdc, TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
865 SetViewportOrgEx (hdc, frame_left, frame_top, NULL);
866 SetWindowOrgEx (hdc, 0, 0, NULL);
868 /* Start print job */
869 di.cbSize = sizeof (di);
870 di.lpszDocName = (STRINGP(f->name)
871 ? (char*) XSTRING_DATA(f->name)
872 : "XEmacs print document");
873 di.lpszOutput = NULL;
874 di.lpszDatatype = NULL;
877 if (StartDoc (hdc, &di) <= 0)
878 error ("Cannot start print job");
880 /* Finish frame setup */
881 FRAME_MSPRINTER_CDC(f) = CreateCompatibleDC (hdc);
882 FRAME_MSPRINTER_JOB_STARTED (f) = 1;
883 FRAME_VISIBLE_P(f) = 0;
887 msprinter_mark_frame (struct frame *f)
889 /* NOTE: These need not be marked as long as we allow only c-defined
890 symbols for their values. Although, marking these is safer than
891 expensive. [I know a proof to the theorem postulating that a
892 gator is longer than greener. Ask me. -- kkm] */
893 mark_object (FRAME_MSPRINTER_ORIENTATION (f));
894 mark_object (FRAME_MSPRINTER_DUPLEX (f));
898 msprinter_delete_frame (struct frame *f)
902 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
903 if (FRAME_MSPRINTER_PAGE_STARTED (f))
905 if (FRAME_MSPRINTER_JOB_STARTED (f))
907 if (FRAME_MSPRINTER_CDC(f))
908 DeleteDC (FRAME_MSPRINTER_CDC(f));
909 xfree (f->frame_data);
916 msprinter_frame_property (struct frame *f, Lisp_Object property)
918 if (EQ (Qleft_margin, property))
919 return make_int (FRAME_MSPRINTER_LEFT_MARGIN(f));
920 else if (EQ (Qtop_margin, property))
921 return make_int (FRAME_MSPRINTER_TOP_MARGIN(f));
922 if (EQ (Qright_margin, property))
923 return make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f));
924 else if (EQ (Qbottom_margin, property))
925 return make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f));
926 else if (EQ (Qorientation, property))
927 return FRAME_MSPRINTER_ORIENTATION(f);
928 else if (EQ (Qduplex, property))
929 return FRAME_MSPRINTER_DUPLEX(f);
935 msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property)
937 return (EQ (Qleft_margin, property) || EQ (Qtop_margin, property) ||
938 EQ (Qright_margin, property) || EQ (Qbottom_margin, property) ||
939 EQ (Qorientation, property) || EQ (Qduplex, property));
943 msprinter_frame_properties (struct frame *f)
945 Lisp_Object props = Qnil;
946 props = cons3 (Qorientation, FRAME_MSPRINTER_ORIENTATION(f), props);
947 props = cons3 (Qduplex, FRAME_MSPRINTER_DUPLEX(f), props);
948 props = cons3 (Qbottom_margin,
949 make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f)), props);
950 props = cons3 (Qright_margin,
951 make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f)), props);
952 props = cons3 (Qtop_margin,
953 make_int (FRAME_MSPRINTER_TOP_MARGIN(f)), props);
954 props = cons3 (Qleft_margin,
955 make_int (FRAME_MSPRINTER_LEFT_MARGIN(f)), props);
960 msprinter_set_frame_properties (struct frame *f, Lisp_Object plist)
964 /* Extract the properties from plist */
965 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
967 Lisp_Object prop = Fcar (tail);
968 Lisp_Object val = Fcar (Fcdr (tail));
972 if (EQ (prop, Qwidth))
974 maybe_error_if_job_active (f);
978 FRAME_MSPRINTER_CHARWIDTH(f) = XINT (val);
981 if (EQ (prop, Qheight))
983 maybe_error_if_job_active (f);
987 FRAME_MSPRINTER_CHARHEIGHT(f) = XINT (val);
990 else if (EQ (prop, Qleft_margin))
992 maybe_error_if_job_active (f);
994 FRAME_MSPRINTER_LEFT_MARGIN(f) = XINT (val);
996 else if (EQ (prop, Qtop_margin))
998 maybe_error_if_job_active (f);
1000 FRAME_MSPRINTER_TOP_MARGIN(f) = XINT (val);
1002 else if (EQ (prop, Qright_margin))
1004 maybe_error_if_job_active (f);
1006 FRAME_MSPRINTER_RIGHT_MARGIN(f) = XINT (val);
1008 else if (EQ (prop, Qbottom_margin))
1010 maybe_error_if_job_active (f);
1012 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = XINT (val);
1014 else if (EQ (prop, Qorientation))
1016 maybe_error_if_job_active (f);
1019 !EQ (val, Qportrait) &&
1020 !EQ (val, Qlandscape))
1021 signal_simple_error ("Page orientation can only be "
1022 "'portrait or 'landscape", val);
1023 FRAME_MSPRINTER_ORIENTATION(f) = val;
1025 else if (EQ (prop, Qduplex))
1027 maybe_error_if_job_active (f);
1031 !EQ (val, Qvertical) &&
1032 !EQ (val, Qhorizontal))
1033 signal_simple_error ("Duplex can only be 'none, "
1034 "'vertical or 'horizontal", val);
1035 FRAME_MSPRINTER_DUPLEX(f) = val;
1042 msprinter_set_frame_size (struct frame *f, int width, int height)
1044 /* We're absolutely unsizeable */
1045 error_frame_unsizable (f);
1049 msprinter_eject_page (struct frame *f)
1051 /* #### Should we eject empty pages? */
1052 if (FRAME_MSPRINTER_PAGE_STARTED (f))
1054 FRAME_MSPRINTER_PAGE_STARTED (f) = 0;
1055 EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
1061 console_type_create_frame_mswindows (void)
1063 /* Display frames */
1064 CONSOLE_HAS_METHOD (mswindows, init_frame_1);
1065 CONSOLE_HAS_METHOD (mswindows, init_frame_2);
1066 CONSOLE_HAS_METHOD (mswindows, init_frame_3);
1067 CONSOLE_HAS_METHOD (mswindows, after_init_frame);
1068 CONSOLE_HAS_METHOD (mswindows, mark_frame);
1069 CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
1070 CONSOLE_HAS_METHOD (mswindows, delete_frame);
1071 CONSOLE_HAS_METHOD (mswindows, get_mouse_position);
1072 CONSOLE_HAS_METHOD (mswindows, set_mouse_position);
1073 CONSOLE_HAS_METHOD (mswindows, raise_frame);
1074 CONSOLE_HAS_METHOD (mswindows, lower_frame);
1075 CONSOLE_HAS_METHOD (mswindows, make_frame_visible);
1076 CONSOLE_HAS_METHOD (mswindows, make_frame_invisible);
1077 CONSOLE_HAS_METHOD (mswindows, iconify_frame);
1078 CONSOLE_HAS_METHOD (mswindows, set_frame_size);
1079 CONSOLE_HAS_METHOD (mswindows, set_frame_position);
1080 CONSOLE_HAS_METHOD (mswindows, frame_property);
1081 CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p);
1082 CONSOLE_HAS_METHOD (mswindows, frame_properties);
1083 CONSOLE_HAS_METHOD (mswindows, set_frame_properties);
1084 CONSOLE_HAS_METHOD (mswindows, set_title_from_bufbyte);
1085 /* CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_bufbyte); */
1086 CONSOLE_HAS_METHOD (mswindows, frame_visible_p);
1087 CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p);
1088 CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
1089 CONSOLE_HAS_METHOD (mswindows, set_frame_pointer);
1090 CONSOLE_HAS_METHOD (mswindows, set_frame_icon);
1091 CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
1092 CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
1093 CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p);
1095 /* Printer frames, aka print jobs */
1096 CONSOLE_HAS_METHOD (msprinter, init_frame_1);
1097 CONSOLE_HAS_METHOD (msprinter, init_frame_3);
1098 CONSOLE_HAS_METHOD (msprinter, mark_frame);
1099 CONSOLE_HAS_METHOD (msprinter, delete_frame);
1100 CONSOLE_HAS_METHOD (msprinter, frame_property);
1101 CONSOLE_HAS_METHOD (msprinter, internal_frame_property_p);
1102 CONSOLE_HAS_METHOD (msprinter, frame_properties);
1103 CONSOLE_HAS_METHOD (msprinter, set_frame_properties);
1104 CONSOLE_HAS_METHOD (msprinter, set_frame_size);
1105 CONSOLE_HAS_METHOD (msprinter, eject_page);
1109 syms_of_frame_mswindows (void)
1114 reinit_vars_of_frame_mswindows (void)
1116 /* Needn't staticpro -- see comment above. */
1117 Vmswindows_frame_being_created = Qnil;
1121 vars_of_frame_mswindows (void)
1123 reinit_vars_of_frame_mswindows ();
1125 DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /*
1126 Controls whether to use system or XEmacs defaults for frame size.
1127 If nil then reasonable defaults are used for intial frame sizes. If t
1128 then the system will choose default sizes for the frame.
1130 Vmswindows_use_system_frame_size_defaults = Qnil;
1132 DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
1133 Plist of default frame-creation properties for mswindows frames.
1134 These override what is specified in `default-frame-plist', but are
1135 overridden by the arguments to the particular call to `make-frame'.
1137 Note: In many cases, properties of a frame are available as specifiers
1138 instead of through the frame-properties mechanism.
1140 Here is a list of recognized frame properties, other than those
1141 documented in `set-frame-properties' (they can be queried and
1142 set at any time, except as otherwise noted):
1144 initially-unmapped If non-nil, the frame will not be visible
1145 when it is created. In this case, you
1146 need to call `make-frame-visible' to make
1148 popup If non-nil, it should be a frame, and this
1149 frame will be created as a "popup" frame
1150 whose parent is the given frame. This
1151 will make the window manager treat the
1152 frame as a dialog box, which may entail
1153 doing different things (e.g. not asking
1154 for positioning, and not iconifying
1155 separate from its parent).
1156 top Y position (in pixels) of the upper-left
1157 outermost corner of the frame (i.e. the
1158 upper-left of the window-manager
1160 left X position (in pixels) of the upper-left
1161 outermost corner of the frame (i.e. the
1162 upper-left of the window-manager
1165 See also `default-frame-plist', which specifies properties which apply
1166 to all frames, not just mswindows frames.
1168 Vdefault_mswindows_frame_plist = Qnil;
1170 mswindows_console_methods->device_specific_frame_props =
1171 &Vdefault_mswindows_frame_plist;
1173 DEFVAR_LISP ("default-msprinter-frame-plist", &Vdefault_msprinter_frame_plist /*
1174 Plist of default frame-creation properties for msprinter print job frames.
1175 These override what is specified in `default-frame-plist', but are
1176 overridden by the arguments to the particular call to `make-frame'.
1178 Note: In many cases, properties of a frame are available as specifiers
1179 instead of through the frame-properties mechanism.
1181 Here is a list of recognized frame properties, other than those
1182 documented in `set-frame-properties' (they can be queried and
1183 set at any time, except as otherwise noted):
1185 left-margin Margin of the page, in twips. Twip is a
1186 top-margin typographical unit of measurement,
1187 right-margin equal to 1/1440 of an inch, or 1/20 of a
1188 bottom-margin point, and roughly equal to 7/400 of a
1189 millimeter. If not specifified, each margin
1190 defaults to one inch (25.4 mm).
1192 MARGINS NOTE. right-margin and bottom-margin are overridden by
1193 the height and width properties. If you want to specify size
1194 of the printable area in character, as with the rest of XEmacs,
1195 use these properties. If height and/or width are nil, then
1196 corresponding margin setting is taken into account. If you
1197 specify height and/or width in `default-frame-plist', but still
1198 want to specify right/bottom margins, set height/width in this
1199 plist to nil, as in this example:
1201 (setq default-frame-plist '(height 55 'width 80)
1202 default-msprinter-frame-plist '(height nil 'width nil))
1205 orientation Printer page orientation. Can be 'nil,
1206 indicating system default, 'portrait
1209 duplex Duplex printing mode, subject to printer
1210 support. Can be 'nil for the device default,
1211 'none for simplex printing, 'vertical or
1212 'horizontal for duplex page bound along
1213 the corresponding page direction.
1215 See also `default-frame-plist', which specifies properties which apply
1216 to all frames, not just mswindows frames.
1218 Vdefault_msprinter_frame_plist = Qnil;
1220 msprinter_console_methods->device_specific_frame_props =
1221 &Vdefault_msprinter_frame_plist;