]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/Printer.java
Merge branch 'bug-623' into release/1.43.0
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / printing / Printer.java
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/Printer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/Printer.java
new file mode 100644 (file)
index 0000000..4e68b8b
--- /dev/null
@@ -0,0 +1,617 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.printing;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class are used to print to a printer.
+ * Applications create a GC on a printer using <code>new GC(printer)</code>
+ * and then draw on the printer GC using the usual graphics calls.
+ * <p>
+ * A <code>Printer</code> object may be constructed by providing
+ * a <code>PrinterData</code> object which identifies the printer.
+ * A <code>PrintDialog</code> presents a print dialog to the user
+ * and returns an initialized instance of <code>PrinterData</code>.
+ * Alternatively, calling <code>new Printer()</code> will construct a
+ * printer object for the user's default printer.
+ * </p><p>
+ * Application code must explicitly invoke the <code>Printer.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see PrinterData
+ * @see PrintDialog
+ * @see <a href="http://www.eclipse.org/swt/snippets/#printing">Printing snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class Printer extends Device {
+       /**
+        * the handle to the printer DC
+        * (Warning: This field is platform dependent)
+        * <p>
+        * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+        * public API. It is marked public only so that it can be shared
+        * within the packages provided by SWT. It is not available on all
+        * platforms and should never be accessed from application code.
+        * </p>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+       /**
+        * the printer data describing this printer
+        */
+       PrinterData data;
+
+       /**
+        * whether or not a GC was created for this printer
+        */
+       boolean isGCCreated = false;
+
+       /**
+        * strings used to access the Windows registry
+        */
+       static TCHAR profile;
+       static TCHAR appName;
+       static TCHAR keyName;
+       static {
+               profile = new TCHAR(0, "PrinterPorts", true); //$NON-NLS-1$
+               appName = new TCHAR(0, "windows", true); //$NON-NLS-1$
+               keyName = new TCHAR(0, "device", true); //$NON-NLS-1$
+       }
+
+/**
+ * Returns an array of <code>PrinterData</code> objects
+ * representing all available printers.  If there are no
+ * printers, the array will be empty.
+ *
+ * @return an array of PrinterData objects representing the available printers
+ */
+public static PrinterData[] getPrinterList() {
+       int length = 1024;
+       /* Use the character encoding for the default locale */
+       TCHAR buf = new TCHAR(0, length);
+       TCHAR nullBuf = new TCHAR(0, 1);
+       int n = OS.GetProfileString(profile, null, nullBuf, buf, length);
+       if (n == 0) return new PrinterData[0];
+       String[] deviceNames = new String[5];
+       int nameCount = 0;
+       int index = 0;
+       for (int i = 0; i < n; i++) {
+               if (buf.tcharAt(i) == 0) {
+                       if (nameCount == deviceNames.length) {
+                               String[] newNames = new String[deviceNames.length + 5];
+                               System.arraycopy(deviceNames, 0, newNames, 0, deviceNames.length);
+                               deviceNames = newNames;
+                       }
+                       deviceNames[nameCount] = buf.toString(index, i - index);
+                       nameCount++;
+                       index = i + 1;
+               }
+       }
+       PrinterData printerList[] = new PrinterData[nameCount];
+       for (int p = 0; p < nameCount; p++) {
+               String device = deviceNames[p];
+               String driver = ""; //$NON-NLS-1$
+               if (OS.GetProfileString(profile, new TCHAR(0, device, true), nullBuf, buf, length) > 0) {
+                       int commaIndex = 0;
+                       while (buf.tcharAt(commaIndex) != ',' && commaIndex < length) commaIndex++;
+                       if (commaIndex < length) {
+                               driver = buf.toString(0, commaIndex);
+                       }
+               }
+               printerList[p] = new PrinterData(driver, device);
+       }
+       return printerList;
+}
+
+/**
+ * Returns a <code>PrinterData</code> object representing
+ * the default printer or <code>null</code> if there is no
+ * default printer.
+ *
+ * @return the default printer data or null
+ *
+ * @since 2.1
+ */
+public static PrinterData getDefaultPrinterData() {
+       String deviceName = null;
+       int length = 1024;
+       /* Use the character encoding for the default locale */
+       TCHAR buf = new TCHAR(0, length);
+       TCHAR nullBuf = new TCHAR(0, 1);
+       int n = OS.GetProfileString(appName, keyName, nullBuf, buf, length);
+       if (n == 0) return null;
+       int commaIndex = 0;
+       while(buf.tcharAt(commaIndex) != ',' && commaIndex < length) commaIndex++;
+       if (commaIndex < length) {
+               deviceName = buf.toString(0, commaIndex);
+       }
+       if (deviceName == null) return null;
+       String driver = ""; //$NON-NLS-1$
+       if (OS.GetProfileString(profile, new TCHAR(0, deviceName, true), nullBuf, buf, length) > 0) {
+               commaIndex = 0;
+               while (buf.tcharAt(commaIndex) != ',' && commaIndex < length) commaIndex++;
+               if (commaIndex < length) {
+                       driver = buf.toString(0, commaIndex);
+               }
+       }
+       return new PrinterData(driver, deviceName);
+}
+
+static DeviceData checkNull (PrinterData data) {
+       if (data == null) data = new PrinterData();
+       if (data.driver == null || data.name == null) {
+               PrinterData defaultPrinter = getDefaultPrinterData();
+               if (defaultPrinter == null) SWT.error(SWT.ERROR_NO_HANDLES);
+               data.driver = defaultPrinter.driver;
+               data.name = defaultPrinter.name;
+       }
+       return data;
+}
+
+/**
+ * Constructs a new printer representing the default printer.
+ * <p>
+ * Note: You must dispose the printer when it is no longer required.
+ * </p>
+ *
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if there is no valid default printer
+ * </ul>
+ *
+ * @see Device#dispose
+ */
+public Printer() {
+       this(null);
+}
+
+/**
+ * Constructs a new printer given a <code>PrinterData</code>
+ * object representing the desired printer. If the argument
+ * is null, then the default printer will be used.
+ * <p>
+ * Note: You must dispose the printer when it is no longer required.
+ * </p>
+ *
+ * @param data the printer data for the specified printer, or null to use the default printer
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the specified printer data does not represent a valid printer
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if there are no valid printers
+ * </ul>
+ *
+ * @see Device#dispose
+ */
+public Printer(PrinterData data) {
+       super(checkNull(data));
+}
+
+/**
+ * Creates the printer handle.
+ * This method is called internally by the instance creation
+ * mechanism of the <code>Device</code> class.
+ * @param deviceData the device data
+ */
+@Override
+protected void create(DeviceData deviceData) {
+       data = (PrinterData)deviceData;
+       /* Use the character encoding for the default locale */
+       TCHAR driver = new TCHAR(0, data.driver, true);
+       TCHAR device = new TCHAR(0, data.name, true);
+       long lpInitData = 0;
+       byte devmodeData [] = data.otherData;
+       long hHeap = OS.GetProcessHeap();
+       if (devmodeData != null && devmodeData.length != 0) {
+               /* If user setup info from a print dialog was specified, restore the DEVMODE struct. */
+               lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, devmodeData.length);
+               OS.MoveMemory(lpInitData, devmodeData, devmodeData.length);
+       } else {
+               long [] hPrinter = new long [1];
+               OS.OpenPrinter(device, hPrinter, 0);
+               if (hPrinter[0] != 0) {
+                       int dwNeeded = OS.DocumentProperties(0, hPrinter[0], device, 0, 0, 0);
+                       if (dwNeeded >= 0) {
+                               lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, dwNeeded);
+                               int rc = OS.DocumentProperties(0, hPrinter[0], device, lpInitData, 0, OS.DM_OUT_BUFFER);
+                               if (rc != OS.IDOK) {
+                                       OS.HeapFree(hHeap, 0, lpInitData);
+                                       lpInitData = 0;
+                               }
+                       }
+                       OS.ClosePrinter(hPrinter[0]);
+               }
+       }
+
+       /* Initialize DEVMODE struct fields from the printerData. */
+       if (lpInitData != 0) {
+               DEVMODE devmode = new DEVMODE ();
+               OS.MoveMemory(devmode, lpInitData, DEVMODE.sizeof);
+               devmode.dmFields |= OS.DM_ORIENTATION;
+               devmode.dmOrientation = data.orientation == PrinterData.LANDSCAPE ? OS.DMORIENT_LANDSCAPE : OS.DMORIENT_PORTRAIT;
+               if (data.copyCount != 1) {
+                       devmode.dmFields |= OS.DM_COPIES;
+                       devmode.dmCopies = (short)data.copyCount;
+               }
+               if (data.collate != false) {
+                       devmode.dmFields |= OS.DM_COLLATE;
+                       devmode.dmCollate = OS.DMCOLLATE_TRUE;
+               }
+               if (data.duplex != SWT.DEFAULT) {
+                       devmode.dmFields |= OS.DM_DUPLEX;
+                       switch (data.duplex) {
+                               case PrinterData.DUPLEX_SHORT_EDGE: devmode.dmDuplex = OS.DMDUP_HORIZONTAL; break;
+                               case PrinterData.DUPLEX_LONG_EDGE: devmode.dmDuplex = OS.DMDUP_VERTICAL; break;
+                               default: devmode.dmDuplex = OS.DMDUP_SIMPLEX;
+                       }
+               }
+               OS.MoveMemory(lpInitData, devmode, DEVMODE.sizeof);
+       }
+       handle = OS.CreateDC(driver, device, 0, lpInitData);
+       if (lpInitData != 0) OS.HeapFree(hHeap, 0, lpInitData);
+       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Printer</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public long internal_new_GC(GCData data) {
+       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       if (data != null) {
+               if (isGCCreated) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+               if ((data.style & mask) != 0) {
+                       data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0;
+               } else {
+                       data.style |= SWT.LEFT_TO_RIGHT;
+               }
+               data.device = this;
+               data.font = Font.win32_new(this, OS.GetCurrentObject(handle, OS.OBJ_FONT));
+               isGCCreated = true;
+       }
+       return handle;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Printer</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public void internal_dispose_GC(long hDC, GCData data) {
+       if (data != null) isGCCreated = false;
+}
+
+/**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public boolean isAutoScalable() {
+       return false;
+}
+
+/**
+ * Starts a print job and returns true if the job started successfully
+ * and false otherwise.
+ * <p>
+ * This must be the first method called to initiate a print job,
+ * followed by any number of startPage/endPage calls, followed by
+ * endJob. Calling startPage, endPage, or endJob before startJob
+ * will result in undefined behavior.
+ * </p>
+ *
+ * @param jobName the name of the print job to start
+ * @return true if the job started successfully and false otherwise.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #startPage
+ * @see #endPage
+ * @see #endJob
+ */
+public boolean startJob(String jobName) {
+       checkDevice();
+       DOCINFO di = new DOCINFO();
+       di.cbSize = DOCINFO.sizeof;
+       long hHeap = OS.GetProcessHeap();
+       long lpszDocName = 0;
+       if (jobName != null && jobName.length() != 0) {
+               /* Use the character encoding for the default locale */
+               TCHAR buffer = new TCHAR(0, jobName, true);
+               int byteCount = buffer.length() * TCHAR.sizeof;
+               lpszDocName = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory(lpszDocName, buffer, byteCount);
+               di.lpszDocName = lpszDocName;
+       }
+       long lpszOutput = 0;
+       if (data.printToFile) {
+               if (data.fileName == null) {
+                       /* Prompt the user for a file name. */
+                       data.fileName = "FILE:"; //$NON-NLS-1$
+               }
+               /* Use the character encoding for the default locale */
+               TCHAR buffer = new TCHAR(0, data.fileName, true);
+               int byteCount = buffer.length() * TCHAR.sizeof;
+               lpszOutput = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory(lpszOutput, buffer, byteCount);
+               di.lpszOutput = lpszOutput;
+       }
+       int rc = OS.StartDoc(handle, di);
+       if (lpszDocName != 0) OS.HeapFree(hHeap, 0, lpszDocName);
+       if (lpszOutput != 0) OS.HeapFree(hHeap, 0, lpszOutput);
+       return rc > 0;
+}
+
+/**
+ * Ends the current print job.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #startJob
+ * @see #startPage
+ * @see #endPage
+ */
+public void endJob() {
+       checkDevice();
+       OS.EndDoc(handle);
+}
+
+/**
+ * Cancels a print job in progress.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void cancelJob() {
+       checkDevice();
+       OS.AbortDoc(handle);
+}
+
+/**
+ * Starts a page and returns true if the page started successfully
+ * and false otherwise.
+ * <p>
+ * After calling startJob, this method may be called any number of times
+ * along with a matching endPage.
+ * </p>
+ *
+ * @return true if the page started successfully and false otherwise.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #endPage
+ * @see #startJob
+ * @see #endJob
+ */
+public boolean startPage() {
+       checkDevice();
+       int rc = OS.StartPage(handle);
+       if (rc <= 0) OS.AbortDoc(handle);
+       return rc > 0;
+}
+
+/**
+ * Ends the current page.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #startPage
+ * @see #startJob
+ * @see #endJob
+ */
+public void endPage() {
+       checkDevice();
+       OS.EndPage(handle);
+}
+
+/**
+ * Returns a point whose x coordinate is the horizontal
+ * dots per inch of the printer, and whose y coordinate
+ * is the vertical dots per inch of the printer.
+ *
+ * @return the horizontal and vertical DPI
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+@Override
+public Point getDPI() {
+       checkDevice();
+       int dpiX = OS.GetDeviceCaps(handle, OS.LOGPIXELSX);
+       int dpiY = OS.GetDeviceCaps(handle, OS.LOGPIXELSY);
+       return new Point(dpiX, dpiY);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location.
+ * <p>
+ * For a printer, this is the size of the physical page, in pixels.
+ * </p>
+ *
+ * @return the bounding rectangle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getClientArea
+ * @see #computeTrim
+ */
+@Override
+public Rectangle getBounds() {
+       checkDevice();
+       int width = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+       int height = OS.GetDeviceCaps(handle, OS.PHYSICALHEIGHT);
+       return new Rectangle(0, 0, width, height);
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ * <p>
+ * For a printer, this is the size of the printable area
+ * of the page, in pixels.
+ * </p>
+ *
+ * @return the client area
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ * @see #computeTrim
+ */
+@Override
+public Rectangle getClientArea () {
+       checkDevice();
+       int width = OS.GetDeviceCaps(handle, OS.HORZRES);
+       int height = OS.GetDeviceCaps(handle, OS.VERTRES);
+       return new Rectangle(0, 0, width, height);
+}
+
+/**
+ * Given a <em>client area</em> (as described by the arguments),
+ * returns a rectangle, relative to the client area's coordinates,
+ * that is the client area expanded by the printer's trim (or minimum margins).
+ * <p>
+ * Most printers have a minimum margin on each edge of the paper where the
+ * printer device is unable to print.  This margin is known as the "trim."
+ * This method can be used to calculate the printer's minimum margins
+ * by passing in a client area of 0, 0, 0, 0 and then using the resulting
+ * x and y coordinates (which will be &lt;= 0) to determine the minimum margins
+ * for the top and left edges of the paper, and the resulting width and height
+ * (offset by the resulting x and y) to determine the minimum margins for the
+ * bottom and right edges of the paper, as follows:
+ * </p>
+ * <ul>
+ *             <li>The left trim width is -x pixels</li>
+ *             <li>The top trim height is -y pixels</li>
+ *             <li>The right trim width is (x + width) pixels</li>
+ *             <li>The bottom trim height is (y + height) pixels</li>
+ * </ul>
+ *
+ * @param x the x coordinate of the client area
+ * @param y the y coordinate of the client area
+ * @param width the width of the client area
+ * @param height the height of the client area
+ * @return a rectangle, relative to the client area's coordinates, that is
+ *             the client area expanded by the printer's trim (or minimum margins)
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ * @see #getClientArea
+ */
+public Rectangle computeTrim(int x, int y, int width, int height) {
+       checkDevice();
+       int printX = -OS.GetDeviceCaps(handle, OS.PHYSICALOFFSETX);
+       int printY = -OS.GetDeviceCaps(handle, OS.PHYSICALOFFSETY);
+       int printWidth = OS.GetDeviceCaps(handle, OS.HORZRES);
+       int printHeight = OS.GetDeviceCaps(handle, OS.VERTRES);
+       int paperWidth = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+       int paperHeight = OS.GetDeviceCaps(handle, OS.PHYSICALHEIGHT);
+       int hTrim = paperWidth - printWidth;
+       int vTrim = paperHeight - printHeight;
+       return new Rectangle(x + printX, y + printY, width + hTrim, height + vTrim);
+}
+
+/**
+ * Returns a <code>PrinterData</code> object representing the
+ * target printer for this print job.
+ *
+ * @return a PrinterData object describing the receiver
+ */
+public PrinterData getPrinterData() {
+       return data;
+}
+
+/**
+ * Checks the validity of this device.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+@Override
+protected void checkDevice() {
+       if (handle == 0) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+}
+
+/**
+ * Releases any internal state prior to destroying this printer.
+ * This method is called internally by the dispose
+ * mechanism of the <code>Device</code> class.
+ */
+@Override
+protected void release() {
+       super.release();
+       data = null;
+}
+
+/**
+ * Destroys the printer handle.
+ * This method is called internally by the dispose
+ * mechanism of the <code>Device</code> class.
+ */
+@Override
+protected void destroy() {
+       if (handle != 0) OS.DeleteDC(handle);
+       handle = 0;
+}
+
+}