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_TABLE1 (f) =
144 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
145 FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f) =
146 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
147 FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f) =
148 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
149 /* Will initialize these in WM_SIZE handler. We cannot do it now,
150 because we do not know what is CW_USEDEFAULT height and width */
152 FRAME_HEIGHT (f) = 0;
153 FRAME_PIXWIDTH (f) = 0;
154 FRAME_PIXHEIGHT (f) = 0;
158 style = MSWINDOWS_FRAME_STYLE;
159 exstyle = MSWINDOWS_FRAME_EXSTYLE;
162 rect_default.left = rect_default.top = CW_USEDEFAULT;
163 rect_default.width = rect_default.height = CW_USEDEFAULT;
167 style = MSWINDOWS_POPUP_STYLE;
168 exstyle = MSWINDOWS_POPUP_EXSTYLE;
170 CHECK_MSWINDOWS_FRAME (popup);
171 hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
172 assert (IsWindow (hwnd_parent));
174 /* We cannot use CW_USEDEFAULT when creating a popup window.
175 So by default, we offset the new popup 30 pixels right
176 and down from its parent, and give it size of 30x10 characters.
177 These dimensions look adequate on both high and low res monitors */
178 GetWindowRect (hwnd_parent, &rect);
179 rect_default.left = rect.left + POPUP_OFFSET;
180 rect_default.top = rect.top + POPUP_OFFSET;
181 char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
182 &rect_default.width, &rect_default.height);
185 AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
187 XSETFRAME (frame_obj, f);
189 Vmswindows_frame_being_created = frame_obj;
191 hwnd = CreateWindowEx (exstyle,
193 STRINGP(f->name) ? XSTRING_DATA(f->name) :
195 (const Extbyte*)XSTRING_DATA(name) :
196 (const Extbyte*)XEMACS_CLASS),
198 rect_default.left, rect_default.top,
199 rect_default.width, rect_default.height,
200 hwnd_parent, NULL, NULL, NULL);
202 Vmswindows_frame_being_created = Qnil;
205 error ("System call to create frame failed");
207 FRAME_MSWINDOWS_HANDLE(f) = hwnd;
209 SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
210 FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
211 SetTextAlign (FRAME_MSWINDOWS_DC(f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
215 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
217 if (NILP (Vmswindows_use_system_frame_size_defaults))
219 /* I don't think anything can set the frame size before this
220 since we don't have X resources. This may change if we look
221 at the registry. Even so these values can get overridden
223 XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH,
224 DEFAULT_FRAME_HEIGHT };
225 mswindows_size_frame_internal (f, &dest);
229 /* Called after frame's properties are set */
231 mswindows_init_frame_3 (struct frame *f)
233 /* Don't do this earlier or we get a WM_PAINT before the frame is ready.
234 * The SW_x parameter in the first call that an app makes to ShowWindow is
235 * ignored, and the parameter specified in the caller's STARTUPINFO is
236 * substituted instead. That parameter is SW_HIDE if we were started by
237 * runemacs, so call this twice. #### runemacs is evil */
238 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
239 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
240 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
241 DragAcceptFiles (FRAME_MSWINDOWS_HANDLE(f), TRUE);
245 mswindows_after_init_frame (struct frame *f, int first_on_device,
246 int first_on_console)
248 /* Windows, unlike X, is very synchronous. After the initial
249 frame is created, it will never be displayed, except for
250 hollow border, unless we start pumping messages. Load progress
251 messages show in the bottom of the hollow frame, which is ugly.
252 We redisplay the initial frame here, so modeline and root window
255 if (first_on_console)
260 mswindows_mark_frame (struct frame *f)
262 mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
264 mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
266 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f));
267 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f));
268 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f));
272 mswindows_focus_on_frame (struct frame *f)
274 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
278 mswindows_delete_frame (struct frame *f)
282 ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
283 DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
284 xfree (f->frame_data);
290 mswindows_set_frame_size (struct frame *f, int width, int height)
293 rect.left = rect.top = 0;
295 rect.bottom = height;
297 AdjustWindowRectEx (&rect,
298 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
299 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
300 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
302 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
303 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
305 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
306 0, 0, rect.right-rect.left, rect.bottom-rect.top,
307 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
311 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
313 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
315 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
319 mswindows_make_frame_visible (struct frame *f)
321 if (!FRAME_VISIBLE_P(f))
322 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
324 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOW);
330 mswindows_make_frame_invisible (struct frame *f)
332 if (!FRAME_VISIBLE_P(f))
335 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
340 mswindows_frame_totally_visible_p (struct frame *f)
342 RECT rc_me, rc_other, rc_temp;
343 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
345 /* We test against not a whole window rectangle, only against its
346 client part. So, if non-client are is covered and client area is
347 not, we return true. */
348 GetClientRect (hwnd, &rc_me);
349 MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2);
351 /* First see if we're off the desktop */
352 GetWindowRect (GetDesktopWindow(), &rc_other);
353 UnionRect(&rc_temp, &rc_me, &rc_other);
354 if (!EqualRect (&rc_temp, &rc_other))
357 /* Then see if any window above us obscures us */
358 while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
359 if (IsWindowVisible (hwnd))
361 GetWindowRect (hwnd, &rc_other);
362 if (IntersectRect(&rc_temp, &rc_me, &rc_other))
370 mswindows_frame_visible_p (struct frame *f)
372 return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
373 && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
378 mswindows_iconify_frame (struct frame *f)
380 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
386 mswindows_frame_iconified_p (struct frame *f)
388 return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
392 mswindows_set_frame_icon (struct frame *f)
394 if (IMAGE_INSTANCEP (f->icon)
395 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
397 if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
399 mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon),
403 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON,
404 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
409 mswindows_set_frame_pointer (struct frame *f)
411 if (IMAGE_INSTANCEP (f->pointer)
412 && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
414 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR,
415 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
416 /* we only have to do this because GC doesn't cause a mouse
417 event and doesn't give time to event processing even if it
419 SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
424 mswindows_set_mouse_position (struct window *w, int x, int y)
426 struct frame *f = XFRAME (w->frame);
429 pt.x = w->pixel_left + x;
430 pt.y = w->pixel_top + y;
431 ClientToScreen (FRAME_MSWINDOWS_HANDLE(f), &pt);
432 SetCursorPos (pt.x, pt.y);
436 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
443 /* What's under cursor? */
444 hwnd = WindowFromPoint (pt);
448 /* Get grandest parent of the window */
451 while ((hwnd_parent = GetParent (hwnd)) != NULL)
455 /* Make sure it belongs to us */
456 if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
459 /* And that the window is an XEmacs frame */
461 char class_name [sizeof(XEMACS_CLASS) + 1];
462 if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
463 || strcmp (class_name, XEMACS_CLASS) != 0)
468 ScreenToClient (hwnd, &pt);
469 VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
476 mswindows_raise_frame (struct frame *f)
478 BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
482 mswindows_lower_frame (struct frame *f)
484 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
485 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
489 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title)
491 unsigned int new_checksum = hash_string (title, strlen (title));
492 if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
494 FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
495 SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
500 mswindows_frame_property (struct frame *f, Lisp_Object property)
502 if (EQ (Qleft, property) || EQ (Qtop, property))
505 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
506 return make_int (EQ (Qtop, property) ? rc.top : rc.left);
512 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
514 return EQ (property, Qleft)
515 || EQ (property, Qtop);
516 /* #### frame-x.c has also this. Why?
517 || STRINGP (property);
522 mswindows_frame_properties (struct frame *f)
524 Lisp_Object props = Qnil;
526 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
528 props = cons3 (Qtop, make_int (rc.top), props);
529 props = cons3 (Qleft, make_int (rc.left), props);
535 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
538 int width = -1, height = -1;
539 BOOL width_specified_p = FALSE;
540 BOOL height_specified_p = FALSE;
541 BOOL x_specified_p = FALSE;
542 BOOL y_specified_p = FALSE;
545 /* Extract the properties from plist */
546 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
548 Lisp_Object prop = Fcar (tail);
549 Lisp_Object val = Fcar (Fcdr (tail));
553 /* Kludge to handle the font property. */
554 if (EQ (prop, Qfont))
556 /* If the value is not a string we silently ignore it. */
559 Lisp_Object frm, font_spec;
562 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
564 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
565 update_frame_face_values (f);
568 else if (EQ (prop, Qwidth))
572 width_specified_p = TRUE;
574 else if (EQ (prop, Qheight))
578 height_specified_p = TRUE;
580 else if (EQ (prop, Qleft))
584 x_specified_p = TRUE;
586 else if (EQ (prop, Qtop))
590 y_specified_p = TRUE;
595 /* Now we've extracted the properties, apply them.
596 Do not apply geometric properties during frame creation. This
597 is excessive anyways, and this loses becuase WM_SIZE has not
598 been sent yet, so frame width and height fields are not initialized.
600 unfortunately WM_SIZE loses as well since the resize is only
601 applied once and the first time WM_SIZE is applied not everything
602 is initialised in the frame (toolbars for instance). enabling
603 this always makes no visible difference and fixes a whole host of
604 bugs (and is more consistent with X) so I am going to reenable it.
606 if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
607 && (width_specified_p || height_specified_p
608 || x_specified_p || y_specified_p))
610 XEMACS_RECT_WH dest = { x, y, width, height };
612 mswindows_size_frame_internal (f, &dest);
616 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
619 int pixel_width, pixel_height;
620 int size_p = (dest->width >=0 || dest->height >=0);
621 int move_p = (dest->top >=0 || dest->left >=0);
622 char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height);
625 pixel_width = FRAME_PIXWIDTH (f);
626 if (dest->height < 0)
627 pixel_height = FRAME_PIXHEIGHT (f);
629 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
631 dest->left = rect.left;
633 dest->top = rect.top;
635 rect.left = rect.top = 0;
636 rect.right = pixel_width;
637 rect.bottom = pixel_height;
639 AdjustWindowRectEx (&rect,
640 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
641 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
642 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
644 /* resize and move the window so that it fits in the workspace. This is
645 not restrictive since this will happen later anyway in WM_SIZE. We
646 have to do this after adjusting the rect to account for menubar
648 msw_get_workspace_coords (&ws_rect);
649 pixel_width = rect.right - rect.left;
650 pixel_height = rect.bottom - rect.top;
651 if (pixel_width > ws_rect.right - ws_rect.left)
653 pixel_width = ws_rect.right - ws_rect.left;
656 if (pixel_height > ws_rect.bottom - ws_rect.top)
658 pixel_height = ws_rect.bottom - ws_rect.top;
662 /* adjust position so window is in workspace */
663 if (dest->left + pixel_width > ws_rect.right)
665 dest->left = ws_rect.right - pixel_width;
668 if (dest->left < ws_rect.left)
670 dest->left = ws_rect.left;
674 if (dest->top + pixel_height > ws_rect.bottom)
676 dest->top = ws_rect.bottom - pixel_height;
679 if (dest->top < ws_rect.top)
681 dest->top = ws_rect.top;
685 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f))
686 || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
687 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
689 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
690 dest->left, dest->top, pixel_width, pixel_height,
691 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
692 | (size_p ? 0 : SWP_NOSIZE)
693 | (move_p ? 0 : SWP_NOMOVE));
697 mswindows_get_frame_parent (struct frame *f)
699 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
700 hwnd = GetParent (hwnd);
704 VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
705 assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
713 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
718 mswindows_frame_size_fixed_p (struct frame *f)
720 /* Frame size cannot change if the frame is maximized */
721 return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
724 /*---------------------------------------------------------------------*/
725 /*----- PRINTER FRAME -----*/
726 /*---------------------------------------------------------------------*/
729 msprinter_start_page (struct frame *f)
731 if (!FRAME_MSPRINTER_PAGE_STARTED (f))
733 FRAME_MSPRINTER_PAGE_STARTED (f) = 1;
734 StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
739 error_frame_unsizable (struct frame *f)
742 XSETFRAME (frame, f);
743 signal_simple_error ("Cannot resize frame (margins)"
744 " after print job has started.", frame);
748 maybe_error_if_job_active (struct frame *f)
750 if (FRAME_MSPRINTER_JOB_STARTED (f))
751 error_frame_unsizable (f);
755 msprinter_init_frame_1 (struct frame *f, Lisp_Object props)
757 /* Make sure this is the only frame on device. Windows printer can
758 handle only one job at a time. */
759 if (!NILP (DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f)))))
760 error ("Only one frame (print job) at a time is allowed on "
761 "this printer device.");
763 f->frame_data = xnew_and_zero (struct msprinter_frame);
765 /* Default margin size is 1" = 1440 twips */
766 FRAME_MSPRINTER_TOP_MARGIN(f) = 1440;
767 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = 1440;
768 FRAME_MSPRINTER_LEFT_MARGIN(f) = 1440;
769 FRAME_MSPRINTER_RIGHT_MARGIN(f) = 1440;
771 /* Negative for "uinspecified" */
772 FRAME_MSPRINTER_CHARWIDTH(f) = -1;
773 FRAME_MSPRINTER_CHARHEIGHT(f) = -1;
775 /* nil is for "system default" for these properties. */
776 FRAME_MSPRINTER_ORIENTATION(f) = Qnil;
777 FRAME_MSPRINTER_DUPLEX(f) = Qnil;
781 msprinter_init_frame_3 (struct frame *f)
784 struct device *device = XDEVICE (FRAME_DEVICE (f));
786 int frame_left, frame_top, frame_width, frame_height;
788 /* Change printer parameters */
790 DEVMODE* devmode = msprinter_get_devmode_copy (device);
791 devmode->dmFields = 0;
793 if (!NILP (FRAME_MSPRINTER_ORIENTATION(f)))
795 devmode->dmFields = DM_ORIENTATION;
796 if (EQ (FRAME_MSPRINTER_ORIENTATION(f), Qportrait))
797 devmode->dmOrientation = DMORIENT_PORTRAIT;
798 else if (EQ (FRAME_MSPRINTER_ORIENTATION(f), Qlandscape))
799 devmode->dmOrientation = DMORIENT_LANDSCAPE;
804 if (!NILP (FRAME_MSPRINTER_DUPLEX(f)))
806 devmode->dmFields = DM_DUPLEX;
807 if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qnone))
808 devmode->dmDuplex = DMDUP_SIMPLEX;
809 if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qvertical))
810 devmode->dmDuplex = DMDUP_VERTICAL;
811 if (EQ (FRAME_MSPRINTER_DUPLEX(f), Qhorizontal))
812 devmode->dmDuplex = DMDUP_HORIZONTAL;
817 assert (!FRAME_MSPRINTER_PAGE_STARTED (f));
818 msprinter_apply_devmode (device, devmode);
821 /* DC might be recreated in msprinter_apply_devmode,
822 so do not initialize until now */
823 hdc = DEVICE_MSPRINTER_HDC (device);
825 /* Compute geometry properties */
826 frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
827 FRAME_MSPRINTER_LEFT_MARGIN(f), 1440)
828 - GetDeviceCaps (hdc, PHYSICALOFFSETX));
830 if (FRAME_MSPRINTER_CHARWIDTH(f) > 0)
832 char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH(f), 0,
834 FRAME_MSPRINTER_RIGHT_MARGIN(f) =
835 MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH)
836 - (frame_left + frame_width), 1440,
837 GetDeviceCaps (hdc, LOGPIXELSX));
840 frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH)
842 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
843 FRAME_MSPRINTER_RIGHT_MARGIN(f), 1440));
845 frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
846 FRAME_MSPRINTER_TOP_MARGIN(f), 1440)
847 - GetDeviceCaps (hdc, PHYSICALOFFSETY));
849 if (FRAME_MSPRINTER_CHARHEIGHT(f) > 0)
851 char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT(f),
852 NULL, &frame_height);
854 FRAME_MSPRINTER_BOTTOM_MARGIN(f) =
855 MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT)
856 - (frame_top + frame_height), 1440,
857 GetDeviceCaps (hdc, LOGPIXELSY));
860 frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT)
862 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
863 FRAME_MSPRINTER_BOTTOM_MARGIN(f), 1440));
865 /* Geometry sanity checks */
866 if (!frame_pixsize_valid_p (f, frame_width, frame_height))
867 error ("Area inside print margins has shrunk to naught.");
871 || frame_left + frame_width > GetDeviceCaps (hdc, HORZRES)
872 || frame_top + frame_height > GetDeviceCaps (hdc, VERTRES))
873 error ("Print area is ouside of the printer's hardware printable area.");
875 /* Apply XEmacs frame geometry and layout windows */
878 FRAME_PIXWIDTH(f) = frame_width;
879 FRAME_PIXHEIGHT(f) = frame_height;
880 pixel_to_char_size (f, frame_width, frame_height, &columns, &rows);
881 change_frame_size (f, rows, columns, 0);
884 /* Apply DC geometry */
885 SetTextAlign (hdc, TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
886 SetViewportOrgEx (hdc, frame_left, frame_top, NULL);
887 SetWindowOrgEx (hdc, 0, 0, NULL);
889 /* Start print job */
890 di.cbSize = sizeof (di);
891 di.lpszDocName = (STRINGP(f->name)
892 ? (char*) XSTRING_DATA(f->name)
893 : "XEmacs print document");
894 di.lpszOutput = NULL;
895 di.lpszDatatype = NULL;
898 if (StartDoc (hdc, &di) <= 0)
899 error ("Cannot start print job");
901 /* Finish frame setup */
902 FRAME_MSPRINTER_JOB_STARTED (f) = 1;
903 FRAME_VISIBLE_P(f) = 0;
907 msprinter_mark_frame (struct frame *f)
909 /* NOTE: These need not be marked as long as we allow only c-defined
910 symbols for their values. Although, marking these is safer than
911 expensive. [I know a proof to the theorem postulating that a
912 gator is longer than greener. Ask me. -- kkm] */
913 mark_object (FRAME_MSPRINTER_ORIENTATION (f));
914 mark_object (FRAME_MSPRINTER_DUPLEX (f));
918 msprinter_delete_frame (struct frame *f)
922 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
923 if (FRAME_MSPRINTER_PAGE_STARTED (f))
925 if (FRAME_MSPRINTER_JOB_STARTED (f))
927 xfree (f->frame_data);
934 msprinter_frame_property (struct frame *f, Lisp_Object property)
936 if (EQ (Qleft_margin, property))
937 return make_int (FRAME_MSPRINTER_LEFT_MARGIN(f));
938 else if (EQ (Qtop_margin, property))
939 return make_int (FRAME_MSPRINTER_TOP_MARGIN(f));
940 if (EQ (Qright_margin, property))
941 return make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f));
942 else if (EQ (Qbottom_margin, property))
943 return make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f));
944 else if (EQ (Qorientation, property))
945 return FRAME_MSPRINTER_ORIENTATION(f);
946 else if (EQ (Qduplex, property))
947 return FRAME_MSPRINTER_DUPLEX(f);
953 msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property)
955 return (EQ (Qleft_margin, property) || EQ (Qtop_margin, property) ||
956 EQ (Qright_margin, property) || EQ (Qbottom_margin, property) ||
957 EQ (Qorientation, property) || EQ (Qduplex, property));
961 msprinter_frame_properties (struct frame *f)
963 Lisp_Object props = Qnil;
964 props = cons3 (Qorientation, FRAME_MSPRINTER_ORIENTATION(f), props);
965 props = cons3 (Qduplex, FRAME_MSPRINTER_DUPLEX(f), props);
966 props = cons3 (Qbottom_margin,
967 make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f)), props);
968 props = cons3 (Qright_margin,
969 make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f)), props);
970 props = cons3 (Qtop_margin,
971 make_int (FRAME_MSPRINTER_TOP_MARGIN(f)), props);
972 props = cons3 (Qleft_margin,
973 make_int (FRAME_MSPRINTER_LEFT_MARGIN(f)), props);
978 msprinter_set_frame_properties (struct frame *f, Lisp_Object plist)
982 /* Extract the properties from plist */
983 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
985 Lisp_Object prop = Fcar (tail);
986 Lisp_Object val = Fcar (Fcdr (tail));
990 if (EQ (prop, Qwidth))
992 maybe_error_if_job_active (f);
996 FRAME_MSPRINTER_CHARWIDTH(f) = XINT (val);
999 if (EQ (prop, Qheight))
1001 maybe_error_if_job_active (f);
1005 FRAME_MSPRINTER_CHARHEIGHT(f) = XINT (val);
1008 else if (EQ (prop, Qleft_margin))
1010 maybe_error_if_job_active (f);
1012 FRAME_MSPRINTER_LEFT_MARGIN(f) = XINT (val);
1014 else if (EQ (prop, Qtop_margin))
1016 maybe_error_if_job_active (f);
1018 FRAME_MSPRINTER_TOP_MARGIN(f) = XINT (val);
1020 else if (EQ (prop, Qright_margin))
1022 maybe_error_if_job_active (f);
1024 FRAME_MSPRINTER_RIGHT_MARGIN(f) = XINT (val);
1026 else if (EQ (prop, Qbottom_margin))
1028 maybe_error_if_job_active (f);
1030 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = XINT (val);
1032 else if (EQ (prop, Qorientation))
1034 maybe_error_if_job_active (f);
1037 !EQ (val, Qportrait) &&
1038 !EQ (val, Qlandscape))
1039 signal_simple_error ("Page orientation can only be "
1040 "'portrait or 'landscape", val);
1041 FRAME_MSPRINTER_ORIENTATION(f) = val;
1043 else if (EQ (prop, Qduplex))
1045 maybe_error_if_job_active (f);
1049 !EQ (val, Qvertical) &&
1050 !EQ (val, Qhorizontal))
1051 signal_simple_error ("Duplex can only be 'none, "
1052 "'vertical or 'horizontal", val);
1053 FRAME_MSPRINTER_DUPLEX(f) = val;
1060 msprinter_set_frame_size (struct frame *f, int width, int height)
1062 /* We're absolutely unsizeable */
1063 error_frame_unsizable (f);
1067 msprinter_eject_page (struct frame *f)
1069 /* #### Should we eject empty pages? */
1070 if (FRAME_MSPRINTER_PAGE_STARTED (f))
1072 FRAME_MSPRINTER_PAGE_STARTED (f) = 0;
1073 EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
1079 console_type_create_frame_mswindows (void)
1081 /* Display frames */
1082 CONSOLE_HAS_METHOD (mswindows, init_frame_1);
1083 CONSOLE_HAS_METHOD (mswindows, init_frame_2);
1084 CONSOLE_HAS_METHOD (mswindows, init_frame_3);
1085 CONSOLE_HAS_METHOD (mswindows, after_init_frame);
1086 CONSOLE_HAS_METHOD (mswindows, mark_frame);
1087 CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
1088 CONSOLE_HAS_METHOD (mswindows, delete_frame);
1089 CONSOLE_HAS_METHOD (mswindows, get_mouse_position);
1090 CONSOLE_HAS_METHOD (mswindows, set_mouse_position);
1091 CONSOLE_HAS_METHOD (mswindows, raise_frame);
1092 CONSOLE_HAS_METHOD (mswindows, lower_frame);
1093 CONSOLE_HAS_METHOD (mswindows, make_frame_visible);
1094 CONSOLE_HAS_METHOD (mswindows, make_frame_invisible);
1095 CONSOLE_HAS_METHOD (mswindows, iconify_frame);
1096 CONSOLE_HAS_METHOD (mswindows, set_frame_size);
1097 CONSOLE_HAS_METHOD (mswindows, set_frame_position);
1098 CONSOLE_HAS_METHOD (mswindows, frame_property);
1099 CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p);
1100 CONSOLE_HAS_METHOD (mswindows, frame_properties);
1101 CONSOLE_HAS_METHOD (mswindows, set_frame_properties);
1102 CONSOLE_HAS_METHOD (mswindows, set_title_from_bufbyte);
1103 /* CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_bufbyte); */
1104 CONSOLE_HAS_METHOD (mswindows, frame_visible_p);
1105 CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p);
1106 CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
1107 CONSOLE_HAS_METHOD (mswindows, set_frame_pointer);
1108 CONSOLE_HAS_METHOD (mswindows, set_frame_icon);
1109 CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
1110 CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
1111 CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p);
1113 /* Printer frames, aka print jobs */
1114 CONSOLE_HAS_METHOD (msprinter, init_frame_1);
1115 CONSOLE_HAS_METHOD (msprinter, init_frame_3);
1116 CONSOLE_HAS_METHOD (msprinter, mark_frame);
1117 CONSOLE_HAS_METHOD (msprinter, delete_frame);
1118 CONSOLE_HAS_METHOD (msprinter, frame_property);
1119 CONSOLE_HAS_METHOD (msprinter, internal_frame_property_p);
1120 CONSOLE_HAS_METHOD (msprinter, frame_properties);
1121 CONSOLE_HAS_METHOD (msprinter, set_frame_properties);
1122 CONSOLE_HAS_METHOD (msprinter, set_frame_size);
1123 CONSOLE_HAS_METHOD (msprinter, eject_page);
1127 syms_of_frame_mswindows (void)
1132 reinit_vars_of_frame_mswindows (void)
1134 /* Needn't staticpro -- see comment above. */
1135 Vmswindows_frame_being_created = Qnil;
1139 vars_of_frame_mswindows (void)
1141 reinit_vars_of_frame_mswindows ();
1143 DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /*
1144 Controls whether to use system or XEmacs defaults for frame size.
1145 If nil then reasonable defaults are used for intial frame sizes. If t
1146 then the system will choose default sizes for the frame.
1148 Vmswindows_use_system_frame_size_defaults = Qnil;
1150 DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
1151 Plist of default frame-creation properties for mswindows frames.
1152 These override what is specified in `default-frame-plist', but are
1153 overridden by the arguments to the particular call to `make-frame'.
1155 Note: In many cases, properties of a frame are available as specifiers
1156 instead of through the frame-properties mechanism.
1158 Here is a list of recognized frame properties, other than those
1159 documented in `set-frame-properties' (they can be queried and
1160 set at any time, except as otherwise noted):
1162 initially-unmapped If non-nil, the frame will not be visible
1163 when it is created. In this case, you
1164 need to call `make-frame-visible' to make
1166 popup If non-nil, it should be a frame, and this
1167 frame will be created as a "popup" frame
1168 whose parent is the given frame. This
1169 will make the window manager treat the
1170 frame as a dialog box, which may entail
1171 doing different things (e.g. not asking
1172 for positioning, and not iconifying
1173 separate from its parent).
1174 top Y position (in pixels) of the upper-left
1175 outermost corner of the frame (i.e. the
1176 upper-left of the window-manager
1178 left X position (in pixels) of the upper-left
1179 outermost corner of the frame (i.e. the
1180 upper-left of the window-manager
1183 See also `default-frame-plist', which specifies properties which apply
1184 to all frames, not just mswindows frames.
1186 Vdefault_mswindows_frame_plist = Qnil;
1188 mswindows_console_methods->device_specific_frame_props =
1189 &Vdefault_mswindows_frame_plist;
1191 DEFVAR_LISP ("default-msprinter-frame-plist", &Vdefault_msprinter_frame_plist /*
1192 Plist of default frame-creation properties for msprinter print job frames.
1193 These override what is specified in `default-frame-plist', but are
1194 overridden by the arguments to the particular call to `make-frame'.
1196 Note: In many cases, properties of a frame are available as specifiers
1197 instead of through the frame-properties mechanism.
1199 Here is a list of recognized frame properties, other than those
1200 documented in `set-frame-properties' (they can be queried and
1201 set at any time, except as otherwise noted):
1203 left-margin Margin of the page, in twips. Twip is a
1204 top-margin typographical unit of measurement,
1205 right-margin equal to 1/1440 of an inch, or 1/20 of a
1206 bottom-margin point, and roughly equal to 7/400 of a
1207 millimeter. If not specifified, each margin
1208 defaults to one inch (25.4 mm).
1210 MARGINS NOTE. right-margin and bottom-margin are overridden by
1211 the height and width properties. If you want to specify size
1212 of the printable area in character, as with the rest of XEmacs,
1213 use these properties. If height and/or width are nil, then
1214 corresponding margin setting is taken into account. If you
1215 specify height and/or width in `default-frame-plist', but still
1216 want to specify right/bottom margins, set height/width in this
1217 plist to nil, as in this example:
1219 (setq default-frame-plist '(height 55 'width 80)
1220 default-msprinter-frame-plist '(height nil 'width nil))
1223 orientation Printer page orientation. Can be 'nil,
1224 indicating system default, 'portrait
1227 duplex Duplex printing mode, subject to printer
1228 support. Can be 'nil for the device default,
1229 'none for simplex printing, 'vertical or
1230 'horizontal for duplex page bound along
1231 the corresponding page direction.
1233 See also `default-frame-plist', which specifies properties which apply
1234 to all frames, not just mswindows frames.
1236 Vdefault_msprinter_frame_plist = Qnil;
1238 msprinter_console_methods->device_specific_frame_props =
1239 &Vdefault_msprinter_frame_plist;