/* * R : A Computer Language for Statistical Data Analysis * Copyright (C) 1999, 2000 Guido Masarotto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, a copy is available at * https://www.R-project.org/Licenses/ */ /* Copyright (C) 2023 The R Core Team Path length limitations */ /* Support for printer * printer newprinter() - return a printer object - to draw to the * printer use drawto(...) and the drawXXX * functions + nextpage(printer) * printers can be deleted by 'del(printer)' */ #include "win-nls.h" #include "internal.h" #include "rui.h" #include /* * Internal printer deletion function. */ static void private_delprinter(printer obj) { HDC h = (HDC) obj->handle; if (!obj || !h || (obj->kind != PrinterObject)) return; EndPage(h); EndDoc(h); DeleteDC(h); return; } /* * Create/return the base printer object. */ static object get_printer_base(void) { static object printer_base = NULL; if (! printer_base) printer_base = new_object(BaseObject, 0, NULL); return printer_base; } static HDC chooseprinter(void) { PRINTDLG pd; HDC dc; DWORD rc; char *cwd = NULL; /* FIXME: can PrintDlg change the current directory? */ rc = GetCurrentDirectory(0, NULL); if (rc) { cwd = (char *)malloc(rc); if (cwd) { DWORD rc1 = GetCurrentDirectory(rc, cwd); if (rc1 <= 0 || rc1 >= rc) { free(cwd); cwd = NULL; } } } pd.lStructSize = sizeof( PRINTDLG ); pd.hwndOwner = NULL; pd.hDevMode = (HANDLE)NULL; pd.hDevNames = (HANDLE)NULL; pd.Flags = PD_RETURNDC | PD_NOSELECTION | PD_NOPAGENUMS | PD_USEDEVMODECOPIES; pd.nFromPage = 0; pd.nToPage = 0; pd.nMinPage = 0; pd.nMaxPage = 0; pd.nCopies = 1; pd.hInstance = (HINSTANCE)NULL; pd.lCustData = (LPARAM)0; pd.lpfnPrintHook = 0; pd.lpfnSetupHook = 0; pd.lpPrintTemplateName = (LPCSTR) 0; pd.lpSetupTemplateName = (LPCSTR) 0; pd.hPrintTemplate = (HGLOBAL)0; pd.hSetupTemplate = (HGLOBAL)0; /* FIXME: use PrintDlgEx? */ dc = PrintDlg( &pd ) ? pd.hDC : NULL; if (cwd) { SetCurrentDirectory(cwd); free(cwd); } if (!dc) { rc = CommDlgExtendedError(); /* 0 means user cancelled */ if (rc) R_ShowMessage(G_("Unable to choose printer")); } return dc; } printer newprinter(double width, double height, const char *name) { DOCINFO docinfo; printer obj; HDC hDC; double dd,AL; int ww,hh,x0,y0; if(strlen(name)) { OSVERSIONINFO verinfo; verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&verinfo); switch(verinfo.dwPlatformId) { case VER_PLATFORM_WIN32_NT: hDC = CreateDC("WINSPOOL", name, NULL, NULL); default: hDC = CreateDC(NULL, name, NULL, NULL); } } else hDC = chooseprinter(); if ( !hDC ) return NULL; obj = new_object(PrinterObject, (HANDLE) hDC, get_printer_base()); if ( !obj ) { R_ShowMessage(G_("Insufficient memory for new printer")); DeleteDC(hDC); return NULL; } if ((width == 0.0) && (height == 0.0)) { ww = GetDeviceCaps(hDC, HORZRES); hh = GetDeviceCaps(hDC, VERTRES); } else { if (width < 0.1) width = 0.1; if (height < 0.1) height = 0.1; dd = GetDeviceCaps(hDC, HORZSIZE) / width; AL = (dd < 1.0) ? dd : 1.0; dd = GetDeviceCaps(hDC, VERTSIZE) / height; AL = (dd < AL) ? dd : AL; ww = (AL * width) * GetDeviceCaps(hDC, LOGPIXELSX) / 25.4; hh = (AL * height) * GetDeviceCaps(hDC, LOGPIXELSY) / 25.4; } x0 = (GetDeviceCaps(hDC, HORZRES) - ww) / 2; y0 = (GetDeviceCaps(hDC, VERTRES) - hh) / 2; obj->rect = rect(x0, y0, ww, hh); obj->depth = GetDeviceCaps(hDC, BITSPIXEL)* GetDeviceCaps(hDC, PLANES); obj->die = private_delprinter; obj->drawstate = copydrawstate(); obj->drawstate->dest = obj; docinfo.cbSize = sizeof(DOCINFO); /* set this size... */ docinfo.lpszDocName = "GraphAppPrintJob"; docinfo.lpszOutput = 0; /* no file output... */ docinfo.lpszDatatype = 0; docinfo.fwType = 0; /* Note: this fails when trying to print to a file using a long path, seen on Windows 10 19045, "Microsoft Print to PDF". However, this is the same as with other applications, seems to be a Windows issue. */ if (StartDoc(hDC, &docinfo) <= 0) { R_ShowMessage(G_("Unable to start the print job")); del(obj); return NULL; } StartPage(hDC); return obj; } void nextpage(printer p) { if (!p || (p->kind != PrinterObject)) return; EndPage((HDC) p->handle); StartPage((HDC) p->handle); }