+/* printer methods */
+/************************************************************************/
+
+static void
+signal_open_printer_error (struct device *d)
+{
+ signal_simple_error ("Failed to open printer", DEVICE_CONNECTION (d));
+}
+
+static void
+msprinter_init_device (struct device *d, Lisp_Object props)
+{
+ char* printer_name;
+
+ DEVICE_INFD (d) = DEVICE_OUTFD (d) = -1;
+
+ CHECK_STRING (DEVICE_CONNECTION (d));
+
+ TO_EXTERNAL_FORMAT (LISP_STRING, DEVICE_CONNECTION (d),
+ C_STRING_ALLOCA, printer_name,
+ Qctext);
+
+ d->device_data = xnew_and_zero (struct msprinter_device);
+
+ DEVICE_MSPRINTER_NAME(d) = xstrdup (printer_name);
+
+ if (!OpenPrinter (printer_name, &DEVICE_MSPRINTER_HPRINTER (d), NULL))
+ {
+ DEVICE_MSPRINTER_HPRINTER (d) = NULL;
+ signal_open_printer_error (d);
+ }
+
+ DEVICE_MSPRINTER_HDC (d) = CreateDC ("WINSPOOL", printer_name,
+ NULL, NULL);
+ if (DEVICE_MSPRINTER_HDC (d) == NULL)
+ signal_open_printer_error (d);
+
+ /* Determinie DEVMODE size and store the default DEVMODE */
+ DEVICE_MSPRINTER_DEVMODE_SIZE(d) =
+ DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d),
+ printer_name, NULL, NULL, 0);
+ if (DEVICE_MSPRINTER_DEVMODE_SIZE(d) <= 0)
+ signal_open_printer_error (d);
+
+ DEVICE_MSPRINTER_DEVMODE(d) =
+ (DEVMODE*) xmalloc (DEVICE_MSPRINTER_DEVMODE_SIZE(d));
+ DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d),
+ printer_name, DEVICE_MSPRINTER_DEVMODE(d),
+ NULL, DM_OUT_BUFFER);
+
+ /* We do not use printer fon list as we do with the display
+ device. Rather, we allow GDI to pick the closest match to the
+ display font. */
+ DEVICE_MSPRINTER_FONTLIST (d) = Qnil;
+
+ DEVICE_CLASS (d) = (GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), BITSPIXEL)
+ * GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), PLANES)
+ > 1) ? Qcolor : Qmono;
+}
+
+static Lisp_Object
+msprinter_device_system_metrics (struct device *d,
+ enum device_metrics m)
+{
+ switch (m)
+ {
+ /* Device sizes - pixel and mm */
+#define FROB(met, index1, index2) \
+ case DM_##met: \
+ return build_devicecaps_cons \
+ (DEVICE_MSPRINTER_HDC(d), index1, index2);
+
+ FROB (size_device, PHYSICALWIDTH, PHYSICALHEIGHT);
+ FROB (size_device_mm, HORZSIZE, VERTSIZE);
+ FROB (size_workspace, HORZRES, VERTRES);
+ FROB (offset_workspace, PHYSICALOFFSETX, PHYSICALOFFSETY);
+ FROB (device_dpi, LOGPIXELSX, LOGPIXELSY);
+#undef FROB
+
+ case DM_num_bit_planes:
+ /* this is what X means by bitplanes therefore we ought to be
+ consistent. num planes is always 1 under mswindows and
+ therefore useless */
+ return make_int (GetDeviceCaps (DEVICE_MSPRINTER_HDC(d), BITSPIXEL));
+
+ case DM_num_color_cells: /* Prnters are non-palette devices */
+ case DM_slow_device: /* Animation would be a really bad idea */
+ case DM_security: /* Not provided by windows */
+ return Qzero;
+ }
+
+ /* Do not know such property */
+ return Qunbound;
+}
+
+static void
+msprinter_delete_device (struct device *d)
+{
+ if (d->device_data)
+ {
+ if (DEVICE_MSPRINTER_HPRINTER (d))
+ ClosePrinter (DEVICE_MSPRINTER_HPRINTER (d));
+ if (DEVICE_MSPRINTER_HDC (d))
+ DeleteDC (DEVICE_MSPRINTER_HDC (d));
+ if (DEVICE_MSPRINTER_NAME (d))
+ free (DEVICE_MSPRINTER_NAME (d));
+ if (DEVICE_MSPRINTER_DEVMODE (d))
+ free (DEVICE_MSPRINTER_DEVMODE (d));
+ if (DEVICE_MSPRINTER_DEVMODE_MIRROR (d))
+ free (DEVICE_MSPRINTER_DEVMODE_MIRROR (d));
+
+ free (d->device_data);
+ }
+}
+
+static void
+msprinter_mark_device (struct device *d)
+{
+ mark_object (DEVICE_MSPRINTER_FONTLIST (d));
+}
+
+static unsigned int
+msprinter_device_implementation_flags (void)
+{
+ return ( XDEVIMPF_PIXEL_GEOMETRY
+ | XDEVIMPF_IS_A_PRINTER
+ | XDEVIMPF_NO_AUTO_REDISPLAY
+ | XDEVIMPF_FRAMELESS_OK );
+}
+
+\f
+/************************************************************************/
+/* printer external functions */
+/************************************************************************/
+
+/*
+ * Return a copy of default DEVMODE. The copy returned is in
+ * a static buffer which will be overwritten by next call.
+ */
+DEVMODE*
+msprinter_get_devmode_copy (struct device *d)
+{
+ assert (DEVICE_MSPRINTER_P (d));
+
+ if (DEVICE_MSPRINTER_DEVMODE_MIRROR(d) == NULL)
+ DEVICE_MSPRINTER_DEVMODE_MIRROR(d) =
+ (DEVMODE*) xmalloc (DEVICE_MSPRINTER_DEVMODE_SIZE(d));
+
+ memcpy (DEVICE_MSPRINTER_DEVMODE_MIRROR(d),
+ DEVICE_MSPRINTER_DEVMODE(d),
+ DEVICE_MSPRINTER_DEVMODE_SIZE(d));
+
+ return DEVICE_MSPRINTER_DEVMODE_MIRROR(d);
+}
+
+/*
+ * Apply settings from the DEVMODE. The settings are considered
+ * incremental to the default DEVMODE, so that changes in the
+ * passed structure supercede parameters of the printer.
+ *
+ * The passed structure is overwritten by the fuction call;
+ * complete printer settings are returned.
+ */
+void
+msprinter_apply_devmode (struct device *d, DEVMODE *devmode)
+{
+ assert (DEVICE_MSPRINTER_P (d));
+
+ DocumentProperties (NULL,
+ DEVICE_MSPRINTER_HPRINTER(d),
+ DEVICE_MSPRINTER_NAME(d),
+ devmode, devmode,
+ DM_IN_BUFFER | DM_OUT_BUFFER);
+
+ ResetDC (DEVICE_MSPRINTER_HDC (d), devmode);
+}
+
+\f
+/************************************************************************/