Rev 82652 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** 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 TeamPath 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 <stdlib.h>/** 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 isthe 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);}