static void EnumeratePrinters() { str::Str<WCHAR> output; PRINTER_INFO_5 *info5Arr = nullptr; DWORD bufSize = 0, printersCount; bool fOk = EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 5, nullptr, bufSize, &bufSize, &printersCount); if (fOk || GetLastError() == ERROR_INSUFFICIENT_BUFFER) { info5Arr = (PRINTER_INFO_5 *)malloc(bufSize); fOk = EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 5, (LPBYTE)info5Arr, bufSize, &bufSize, &printersCount); } if (!fOk || !info5Arr) { output.AppendFmt(L"Call to EnumPrinters failed with error %#x", GetLastError()); MessageBox(nullptr, output.Get(), L"SumatraPDF - EnumeratePrinters", MB_OK | MB_ICONERROR); free(info5Arr); return; } ScopedMem<WCHAR> defName(GetDefaultPrinterName()); for (DWORD i = 0; i < printersCount; i++) { const WCHAR *printerName = info5Arr[i].pPrinterName; const WCHAR *printerPort = info5Arr[i].pPortName; bool fDefault = str::Eq(defName, printerName); output.AppendFmt(L"%s (Port: %s, attributes: %#x%s)\n", printerName, printerPort, info5Arr[i].Attributes, fDefault ? L", default" : L""); DWORD bins = DeviceCapabilities(printerName, printerPort, DC_BINS, nullptr, nullptr); DWORD binNames = DeviceCapabilities(printerName, printerPort, DC_BINNAMES, nullptr, nullptr); CrashIf(bins != binNames); if (0 == bins) { output.Append(L" - no paper bins available\n"); } else if (bins == (DWORD)-1) { output.AppendFmt(L" - Call to DeviceCapabilities failed with error %#x\n", GetLastError()); } else { ScopedMem<WORD> binValues(AllocArray<WORD>(bins)); DeviceCapabilities(printerName, printerPort, DC_BINS, (WCHAR *)binValues.Get(), nullptr); ScopedMem<WCHAR> binNameValues(AllocArray<WCHAR>(24 * binNames)); DeviceCapabilities(printerName, printerPort, DC_BINNAMES, binNameValues.Get(), nullptr); for (DWORD j = 0; j < bins; j++) { output.AppendFmt(L" - '%s' (%d)\n", binNameValues.Get() + 24 * j, binValues.Get()[j]); } } } free(info5Arr); MessageBox(nullptr, output.Get(), L"SumatraPDF - EnumeratePrinters", MB_OK | MB_ICONINFORMATION); }
nsresult nsPrintOptions::_CreatePrintSettings(nsIPrintSettings **_retval) { // does not initially ref count nsPrintSettings * printSettings = new nsPrintSettings(); NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*_retval = printSettings); // ref count nsXPIDLString printerName; nsresult rv = GetDefaultPrinterName(getter_Copies(printerName)); NS_ENSURE_SUCCESS(rv, rv); (*_retval)->SetPrinterName(printerName.get()); (void)InitPrintSettingsFromPrefs(*_retval, PR_FALSE, nsIPrintSettings::kInitSaveAll); return NS_OK; }
static int fb_hPrinterBuildListDefault( FB_LIST *list, int iStartPort ) { char Buffer[32]; int iPort = iStartPort - 1; char *printer_name = GetDefaultPrinterName( ); if( printer_name!=NULL ) { if( fb_hListDevFindName( list, printer_name )==NULL ) { DEV_PRINTER_DEVICE* node; do { ++iPort; sprintf( Buffer, "LPT%d", iPort ); node = fb_hListDevFindDevice( list, Buffer ); } while( node!=NULL ); fb_hListDevElemAlloc ( list, Buffer, printer_name ); } free( printer_name ); } return iPort + 1; }
int fb_PrinterOpen( DEV_LPT_INFO *devInfo, int iPort, const char *pszDevice ) { int result = fb_ErrorSetNum( FB_RTERROR_OK ); const DEV_PRINTER_EMU_MODE *pFoundEmu = NULL; DWORD dwJob = 0; BOOL fResult; HANDLE hPrinter = NULL; HDC hDc = NULL; char *printer_name = NULL; char *doc_title = NULL; DEV_LPT_PROTOCOL *lpt_proto; if ( !fb_DevLptParseProtocol( &lpt_proto, pszDevice, strlen(pszDevice), TRUE ) ) { if( lpt_proto!=NULL ) free(lpt_proto); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } /* Allow only valid emulation modes */ if( *lpt_proto->emu!=0 ) { int i; for( i=0; i!=sizeof(aEmulationModes)/sizeof(aEmulationModes[0]); ++i ) { const DEV_PRINTER_EMU_MODE *pEmu = aEmulationModes + i; if( strcasecmp( lpt_proto->emu, pEmu->pszId )==0 ) { pFoundEmu = pEmu; break; } } if( !pFoundEmu ) { if( lpt_proto!=NULL ) free(lpt_proto); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } } if( iPort==0 ) { /* LPT:[PrinterName] */ if( *lpt_proto->name ) { printer_name = strdup( lpt_proto->name ); } else { printer_name = GetDefaultPrinterName(); } } else { /* LPTx: */ FB_LIST dev_printer_devs; DEV_PRINTER_DEVICE* node; fb_hListDevInit( &dev_printer_devs ); fb_hPrinterBuildList( &dev_printer_devs ); /* Find printer attached to specified device */ node = fb_hListDevFindDevice( &dev_printer_devs, lpt_proto->proto ); if( node!=NULL ) { printer_name = strdup( node->printer_name ); } fb_hListDevClear( &dev_printer_devs ); } if( printer_name == NULL ) { result = fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND ); } else { if( *lpt_proto->emu!= '\0' ) { /* When EMULATION is used, we have to use the DC instead of * the PRINTER directly */ hDc = CreateDCA( "WINSPOOL", printer_name, NULL, NULL ); fResult = hDc!=NULL; } else { /* User PRINTER directly */ fResult = OpenPrinter(printer_name, &hPrinter, NULL); } if( !fResult ) { result = fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND ); } } if( lpt_proto->title && *lpt_proto->title ) { doc_title = strdup( lpt_proto->title ); } else { doc_title = strdup( "FreeBASIC document" ); } if( result==FB_RTERROR_OK ) { if( *lpt_proto->emu!= '\0' ) { int iJob; DOCINFO docInfo; memset( &docInfo, 0, sizeof(DOCINFO) ); docInfo.cbSize = sizeof(DOCINFO); docInfo.lpszDocName = doc_title; iJob = StartDoc( hDc, &docInfo ); if( iJob <= 0 ) { result = fb_ErrorSetNum( FB_RTERROR_FILEIO ); } else { dwJob = (DWORD) iJob; } } else { DOC_INFO_1 DocInfo; DocInfo.pDocName = doc_title; DocInfo.pOutputFile = NULL; DocInfo.pDatatype = TEXT("RAW"); dwJob = StartDocPrinter( hPrinter, 1, (BYTE*) &DocInfo ); if( dwJob==0 ) { result = fb_ErrorSetNum( FB_RTERROR_FILEIO ); } } } if( result==FB_RTERROR_OK ) { W32_PRINTER_INFO *pInfo = calloc( 1, sizeof(W32_PRINTER_INFO) ); if( pInfo==NULL ) { result = fb_ErrorSetNum( FB_RTERROR_OUTOFMEM ); } else { devInfo->driver_opaque = pInfo; pInfo->hPrinter = hPrinter; pInfo->dwJob = dwJob; pInfo->hDc = hDc; if( hDc!=NULL ) { LOGFONT lf; pInfo->Emu.dwFullSizeX = GetDeviceCaps( hDc, PHYSICALWIDTH ); pInfo->Emu.dwFullSizeY = GetDeviceCaps( hDc, PHYSICALHEIGHT ); pInfo->Emu.dwSizeX = GetDeviceCaps( hDc, HORZRES ); pInfo->Emu.dwSizeY = GetDeviceCaps( hDc, VERTRES ); pInfo->Emu.dwOffsetX = GetDeviceCaps( hDc, PHYSICALOFFSETX ); pInfo->Emu.dwOffsetY = GetDeviceCaps( hDc, PHYSICALOFFSETY ); pInfo->Emu.dwDPI_X = GetDeviceCaps( hDc, LOGPIXELSX ); pInfo->Emu.dwDPI_Y = GetDeviceCaps( hDc, LOGPIXELSY ); #if 0 pInfo->Emu.dwCurrentX = pInfo->Emu.dwOffsetX; pInfo->Emu.dwCurrentY = pInfo->Emu.dwOffsetY; #else pInfo->Emu.dwCurrentX = 0; pInfo->Emu.dwCurrentY = 0; #endif pInfo->Emu.clFore = RGB(0,0,0); pInfo->Emu.clBack = RGB(255,255,255); /* Start in 12 CPI monospace mode */ EmuBuild_LOGFONT( &lf, pInfo, 12 ); /* Should never fail - except when some default fonts were * removed by hand (which is very unlikely) */ pInfo->Emu.hFont = CreateFontIndirect( &lf ); DBG_ASSERT( pInfo->Emu.hFont!=NULL ); /* Register PRINT function */ pInfo->Emu.pfnPrint = pFoundEmu->pfnPrint; /* Should not be necessary because this is the default */ SetTextAlign( hDc, TA_TOP | TA_LEFT | TA_NOUPDATECP ); EmuUpdateInfo( pInfo ); } } } if( result!=FB_RTERROR_OK ) { if( dwJob!=0 ) { if( *lpt_proto->emu != '\0' ) { EndDoc( hDc ); } else { EndDocPrinter( hPrinter ); } } if( hPrinter!=NULL ) { ClosePrinter( hPrinter ); } if( hDc!=NULL ) { DeleteDC( hDc ); } } if( printer_name!=NULL ) free( printer_name ); if( doc_title!=NULL ) free( doc_title ); if( lpt_proto!=NULL ) free(lpt_proto); return result; }
/* parse argument list. we assume that all unrecognized arguments are file names. */ void CommandLineInfo::ParseCommandLine(const WCHAR *cmdLine) { WStrVec argList; ParseCmdLine(cmdLine, argList); size_t argCount = argList.Count(); #define is_arg(txt) str::EqI(TEXT(txt), argument) #define is_arg_with_param(txt) (is_arg(txt) && (argCount > n + 1)) #define additional_param() argList.At(n + 1) #define has_additional_param() ((argCount > n + 1) && ('-' != additional_param()[0])) #define handle_string_param(name) name.Set(str::Dup(argList.At(++n))) #define handle_int_param(name) name = _wtoi(argList.At(++n)) for (size_t n = 1; n < argCount; n++) { WCHAR *argument = argList.At(n); if (is_arg("-register-for-pdf")) { makeDefault = true; exitImmediately = true; return; } else if (is_arg("-silent")) { // silences errors happening during -print-to and -print-to-default silent = true; } else if (is_arg("-print-to-default")) { printerName.Set(GetDefaultPrinterName()); if (!printerName) printDialog = true; exitWhenDone = true; } else if (is_arg_with_param("-print-to")) { handle_string_param(printerName); exitWhenDone = true; } else if (is_arg("-print-dialog")) { printDialog = true; } else if (is_arg_with_param("-print-settings")) { // argument is a comma separated list of page ranges and // advanced options [even|odd] and [noscale|shrink|fit] // e.g. -print-settings "1-3,5,10-8,odd,fit" handle_string_param(printSettings); str::RemoveChars(printSettings, L" "); str::TransChars(printSettings, L";", L","); } else if (is_arg("-exit-when-done") || is_arg("-exit-on-print")) { // only affects -print-dialog (-print-to and -print-to-default // always exit on print) and -stress-test (useful for profiling) exitWhenDone = true; } else if (is_arg_with_param("-inverse-search")) { str::ReplacePtr(&gGlobalPrefs->inverseSearchCmdLine, argList.At(++n)); gGlobalPrefs->enableTeXEnhancements = true; } else if ((is_arg_with_param("-forward-search") || is_arg_with_param("-fwdsearch")) && argCount > n + 2) { // -forward-search is for consistency with -inverse-search // -fwdsearch is for consistency with -fwdsearch-* handle_string_param(forwardSearchOrigin); handle_int_param(forwardSearchLine); } else if (is_arg_with_param("-nameddest") || is_arg_with_param("-named-dest")) { // -nameddest is for backwards compat (was used pre-1.3) // -named-dest is for consistency handle_string_param(destName); } else if (is_arg_with_param("-page")) { handle_int_param(pageNumber); } else if (is_arg("-restrict")) { restrictedUse = true; } else if (is_arg("-invertcolors") || is_arg("-invert-colors")) { // -invertcolors is for backwards compat (was used pre-1.3) // -invert-colors is for consistency // -invert-colors used to be a shortcut for -set-color-range 0xFFFFFF 0x000000 // now it non-permanently swaps textColor and backgroundColor gGlobalPrefs->fixedPageUI.invertColors = true; } else if (is_arg("-presentation")) { enterPresentation = true; } else if (is_arg("-fullscreen")) { enterFullScreen = true; } else if (is_arg_with_param("-view")) { ParseViewMode(&startView, argList.At(++n)); } else if (is_arg_with_param("-zoom")) { ParseZoomValue(&startZoom, argList.At(++n)); } else if (is_arg_with_param("-scroll")) { ParseScrollValue(&startScroll, argList.At(++n)); } else if (is_arg("-console")) { showConsole = true; } else if (is_arg_with_param("-plugin")) { // -plugin [<URL>] <parent HWND> if (argCount > n + 2 && !str::IsDigit(*argList.At(n + 1)) && *argList.At(n + 2) != '-') handle_string_param(pluginURL); // the argument is a (numeric) window handle to // become the parent of a frameless SumatraPDF // (used e.g. for embedding it into a browser plugin) hwndPluginParent = (HWND)_wtol(argList.At(++n)); } else if (is_arg_with_param("-stress-test")) { // -stress-test <file or dir path> [<file filter>] [<page/file range(s)>] [<cycle count>x] // e.g. -stress-test file.pdf 25x for rendering file.pdf 25 times // -stress-test file.pdf 1-3 render only pages 1, 2 and 3 of file.pdf // -stress-test dir 301- 2x render all files in dir twice, skipping first 300 // -stress-test dir *.pdf;*.xps render all files in dir that are either PDF or XPS handle_string_param(stressTestPath); int num; if (has_additional_param() && str::FindChar(additional_param(), '*')) handle_string_param(stressTestFilter); if (has_additional_param() && IsValidPageRange(additional_param())) handle_string_param(stressTestRanges); if (has_additional_param() && str::Parse(additional_param(), L"%dx%$", &num) && num > 0) { stressTestCycles = num; n++; } } else if (is_arg_with_param("-n")) { handle_int_param(stressParallelCount); } else if (is_arg("-rand")) { stressRandomizeFiles = true; } else if (is_arg_with_param("-bench")) { WCHAR *s = str::Dup(argList.At(++n)); pathsToBenchmark.Push(s); s = NULL; if (has_additional_param() && IsBenchPagesInfo(additional_param())) { s = str::Dup(argList.At(++n)); } pathsToBenchmark.Push(s); exitImmediately = true; } else if (is_arg("-crash-on-open")) { // to make testing of crash reporting system in pre-release/release // builds possible crashOnOpen = true; } else if (is_arg("-reuse-instance")) { // for backwards compatibility, -reuse-instance reuses whatever // instance has registered as DDE server reuseDdeInstance = true; } // TODO: remove the following deprecated options within a release or two else if (is_arg("-esc-to-exit")) { gGlobalPrefs->escToExit = true; } else if (is_arg_with_param("-bgcolor") || is_arg_with_param("-bg-color")) { // -bgcolor is for backwards compat (was used pre-1.3) // -bg-color is for consistency ParseColor(&gGlobalPrefs->mainWindowBackground, argList.At(++n)); } else if (is_arg_with_param("-lang")) { lang.Set(str::conv::ToAnsi(argList.At(++n))); } else if (is_arg("-set-color-range") && argCount > n + 2) { ParseColor(&gGlobalPrefs->fixedPageUI.textColor, argList.At(++n)); ParseColor(&gGlobalPrefs->fixedPageUI.backgroundColor, argList.At(++n)); } else if (is_arg_with_param("-fwdsearch-offset")) { handle_int_param(gGlobalPrefs->forwardSearch.highlightOffset); gGlobalPrefs->enableTeXEnhancements = true; } else if (is_arg_with_param("-fwdsearch-width")) { handle_int_param(gGlobalPrefs->forwardSearch.highlightWidth); gGlobalPrefs->enableTeXEnhancements = true; } else if (is_arg_with_param("-fwdsearch-color")) { ParseColor(&gGlobalPrefs->forwardSearch.highlightColor, argList.At(++n)); gGlobalPrefs->enableTeXEnhancements = true; } else if (is_arg_with_param("-fwdsearch-permanent")) { handle_int_param(gGlobalPrefs->forwardSearch.highlightPermanent); gGlobalPrefs->enableTeXEnhancements = true; } else if (is_arg_with_param("-manga-mode")) { const WCHAR *s = argList.At(++n); gGlobalPrefs->comicBookUI.cbxMangaMode = str::EqI(L"true", s) || str::Eq(L"1", s); } #if defined(SUPPORTS_AUTO_UPDATE) || defined(DEBUG) else if (is_arg_with_param("-autoupdate")) { n++; // this should have been handled already by AutoUpdateMain } #endif #ifdef DEBUG else if (is_arg("-enum-printers")) { EnumeratePrinters(); /* this is for testing only, exit immediately */ exitImmediately = true; return; } #endif else { // Remember this argument as a filename to open WCHAR *filePath = NULL; if (str::EndsWithI(argList.At(n), L".lnk")) filePath = ResolveLnk(argList.At(n)); if (!filePath) filePath = str::Dup(argList.At(n)); fileNames.Push(filePath); } } #undef is_arg #undef is_arg_with_param #undef additional_param #undef has_additional_param #undef handle_string_param #undef handle_int_param }
bool PrintFile(BaseEngine *engine, WCHAR *printerName, bool displayErrors, const WCHAR *settings) { bool ok = false; if (!HasPermission(Perm_PrinterAccess)) return false; #ifndef DISABLE_DOCUMENT_RESTRICTIONS if (engine && !engine->AllowsPrinting()) engine = NULL; #endif if (!engine) { if (displayErrors) MessageBoxWarning(NULL, _TR("Cannot print this file"), _TR("Printing problem.")); return false; } ScopedMem<WCHAR> defaultPrinter; if (!printerName) { defaultPrinter.Set(GetDefaultPrinterName()); printerName = defaultPrinter; } HANDLE printer; BOOL res = OpenPrinter(printerName, &printer, NULL); if (!res) { if (displayErrors) MessageBoxWarning(NULL, _TR("Printer with given name doesn't exist"), _TR("Printing problem.")); return false; } LPDEVMODE devMode = NULL; // get printer driver information DWORD needed = 0; GetPrinter(printer, 2, NULL, 0, &needed); ScopedMem<PRINTER_INFO_2> infoData((PRINTER_INFO_2 *)AllocArray<BYTE>(needed)); if (infoData) res = GetPrinter(printer, 2, (LPBYTE)infoData.Get(), needed, &needed); if (!res || !infoData || needed <= sizeof(PRINTER_INFO_2)) goto Exit; LONG structSize = DocumentProperties(NULL, printer, printerName, NULL, /* Asking for size, so */ NULL, /* not used. */ 0); /* Zero returns buffer size. */ if (structSize < sizeof(DEVMODE)) { // If failure, inform the user, cleanup and return failure. if (displayErrors) MessageBoxWarning(NULL, _TR("Could not obtain Printer properties"), _TR("Printing problem.")); goto Exit; } devMode = (LPDEVMODE)malloc(structSize); if (!devMode) goto Exit; // Get the default DevMode for the printer and modify it for your needs. LONG returnCode = DocumentProperties(NULL, printer, printerName, devMode, /* The address of the buffer to fill. */ NULL, /* Not using the input buffer. */ DM_OUT_BUFFER); /* Have the output buffer filled. */ if (IDOK != returnCode) { // If failure, inform the user, cleanup and return failure. if (displayErrors) MessageBoxWarning(NULL, _TR("Could not obtain Printer properties"), _TR("Printing problem.")); goto Exit; } ClosePrinter(printer); printer = NULL; { Print_Advanced_Data advanced; Vec<PRINTPAGERANGE> ranges; ApplyPrintSettings(settings, engine->PageCount(), ranges, advanced, devMode); PrintData pd(engine, infoData, devMode, ranges, advanced); ok = PrintToDevice(pd); if (!ok && displayErrors) MessageBoxWarning(NULL, _TR("Couldn't initialize printer"), _TR("Printing problem.")); } Exit: free(devMode); if (printer) ClosePrinter(printer); return ok; }
/* parse argument list. we assume that all unrecognized arguments are file names. */ void CommandLineInfo::ParseCommandLine(const WCHAR* cmdLine) { WStrVec argList; ParseCmdLine(cmdLine, argList); size_t argCount = argList.size(); #define is_arg_with_param(_argNo) (param && _argNo == arg) #define additional_param() argList.at(n + 1) #define has_additional_param() ((argCount > n + 1) && ('-' != additional_param()[0])) #define handle_string_param(name) name.SetCopy(argList.at(++n)) #define handle_int_param(name) name = _wtoi(argList.at(++n)) for (size_t n = 1; n < argCount; n++) { WCHAR* argName = argList.at(n); int arg = GetArgNo(argName); WCHAR* param = nullptr; if (argCount > n + 1) { param = argList.at(n + 1); } if (RegisterForPdf == arg) { makeDefault = true; exitImmediately = true; return; } else if (Silent == arg) { // silences errors happening during -print-to and -print-to-default silent = true; } else if (PrintToDefault == arg) { printerName.Set(GetDefaultPrinterName()); if (!printerName) printDialog = true; exitWhenDone = true; } else if (is_arg_with_param(PrintTo)) { handle_string_param(printerName); exitWhenDone = true; } else if (PrintDialog == arg) { printDialog = true; } else if (is_arg_with_param(PrintSettings)) { // argument is a comma separated list of page ranges and // advanced options [even|odd], [noscale|shrink|fit] and [autorotation|portrait|landscape] // e.g. -print-settings "1-3,5,10-8,odd,fit" handle_string_param(printSettings); str::RemoveChars(printSettings, L" "); str::TransChars(printSettings, L";", L","); } else if (ExitWhenDone == arg || ExitOnPrint == arg) { // only affects -print-dialog (-print-to and -print-to-default // always exit on print) and -stress-test (useful for profiling) exitWhenDone = true; } else if (is_arg_with_param(InverseSearch)) { inverseSearchCmdLine.SetCopy(argList.at(++n)); } else if ((is_arg_with_param(ForwardSearch) || is_arg_with_param(FwdSearch)) && argCount > n + 2) { // -forward-search is for consistency with -inverse-search // -fwdsearch is for consistency with -fwdsearch-* handle_string_param(forwardSearchOrigin); handle_int_param(forwardSearchLine); } else if (is_arg_with_param(NamedDest) || is_arg_with_param(NamedDest2)) { // -nameddest is for backwards compat (was used pre-1.3) // -named-dest is for consistency handle_string_param(destName); } else if (is_arg_with_param(Page)) { handle_int_param(pageNumber); } else if (Restrict == arg) { restrictedUse = true; } else if (InvertColors1 == arg || InvertColors2 == arg) { // -invertcolors is for backwards compat (was used pre-1.3) // -invert-colors is for consistency // -invert-colors used to be a shortcut for -set-color-range 0xFFFFFF 0x000000 // now it non-permanently swaps textColor and backgroundColor invertColors = true; } else if (Presentation == arg) { enterPresentation = true; } else if (Fullscreen == arg) { enterFullScreen = true; } else if (is_arg_with_param(View)) { ParseViewMode(&startView, param); ++n; } else if (is_arg_with_param(Zoom)) { ParseZoomValue(&startZoom, param); ++n; } else if (is_arg_with_param(Scroll)) { ParseScrollValue(&startScroll, param); ++n; } else if (Console == arg) { showConsole = true; } else if (is_arg_with_param(AppData)) { appdataDir.SetCopy(param); ++n; } else if (is_arg_with_param(Plugin)) { // -plugin [<URL>] <parent HWND> if (argCount > n + 2 && !str::IsDigit(*argList.at(n + 1)) && *argList.at(n + 2) != '-') handle_string_param(pluginURL); // the argument is a (numeric) window handle to // become the parent of a frameless SumatraPDF // (used e.g. for embedding it into a browser plugin) hwndPluginParent = (HWND)(INT_PTR)_wtol(argList.at(++n)); } else if (is_arg_with_param(StressTest)) { // -stress-test <file or dir path> [<file filter>] [<page/file range(s)>] [<cycle // count>x] // e.g. -stress-test file.pdf 25x for rendering file.pdf 25 times // -stress-test file.pdf 1-3 render only pages 1, 2 and 3 of file.pdf // -stress-test dir 301- 2x render all files in dir twice, skipping first 300 // -stress-test dir *.pdf;*.xps render all files in dir that are either PDF or XPS handle_string_param(stressTestPath); int num; if (has_additional_param() && str::FindChar(additional_param(), '*')) handle_string_param(stressTestFilter); if (has_additional_param() && IsValidPageRange(additional_param())) handle_string_param(stressTestRanges); if (has_additional_param() && str::Parse(additional_param(), L"%dx%$", &num) && num > 0) { stressTestCycles = num; n++; } } else if (is_arg_with_param(ArgN)) { handle_int_param(stressParallelCount); } else if (is_arg_with_param(Render)) { handle_int_param(pageNumber); testRenderPage = true; } else if (is_arg_with_param(ExtractText)) { handle_int_param(pageNumber); testExtractPage = true; } else if (Rand == arg) { stressRandomizeFiles = true; } else if (is_arg_with_param(Bench)) { WCHAR* s = str::Dup(param); ++n; pathsToBenchmark.Push(s); s = nullptr; if (has_additional_param() && IsBenchPagesInfo(additional_param())) { s = str::Dup(argList.at(++n)); } pathsToBenchmark.Push(s); exitImmediately = true; } else if (CrashOnOpen == arg) { // to make testing of crash reporting system in pre-release/release // builds possible crashOnOpen = true; } else if (ReuseInstance == arg) { // for backwards compatibility, -reuse-instance reuses whatever // instance has registered as DDE server reuseDdeInstance = true; } // TODO: remove the following deprecated options within a release or two else if (is_arg_with_param(Lang)) { auto tmp = str::conv::ToAnsi(param); lang.Set(tmp.StealData()); ++n; } else if (EscToExit == arg) { globalPrefArgs.Append(str::Dup(argList.at(n))); } else if (is_arg_with_param(BgColor) || is_arg_with_param(BgColor2) || is_arg_with_param(FwdSearchOffset) || is_arg_with_param(FwdSearchWidth) || is_arg_with_param(FwdSearchColor) || is_arg_with_param(FwdSearchPermanent) || is_arg_with_param(MangaMode)) { globalPrefArgs.Append(str::Dup(argList.at(n))); globalPrefArgs.Append(str::Dup(argList.at(++n))); } else if (SetColorRange == arg && argCount > n + 2) { globalPrefArgs.Append(str::Dup(argList.at(n))); globalPrefArgs.Append(str::Dup(argList.at(++n))); globalPrefArgs.Append(str::Dup(argList.at(++n))); } #ifdef DEBUG else if (ArgEnumPrinters == arg) { EnumeratePrinters(); /* this is for testing only, exit immediately */ exitImmediately = true; return; } #endif // this should have been handled already by AutoUpdateMain else if (is_arg_with_param(AutoUpdate)) { n++; } else { // Remember this argument as a filename to open WCHAR* filePath = nullptr; if (str::EndsWithI(argName, L".lnk")) filePath = ResolveLnk(argName); if (!filePath) filePath = str::Dup(argName); fileNames.Push(filePath); } } #undef is_arg_with_param #undef additional_param #undef has_additional_param #undef handle_string_param #undef handle_int_param }
/* parse argument list. we assume that all unrecognized arguments are file names. */ void CommandLineInfo::ParseCommandLine(WCHAR *cmdLine) { WStrVec argList; ParseCmdLine(cmdLine, argList); size_t argCount = argList.Count(); #define is_arg(txt) str::EqI(TEXT(txt), argument) #define is_arg_with_param(txt) (is_arg(txt) && param != NULL) #define additional_param() argList.At(n + 1) #define has_additional_param() ((argCount > n + 1) && ('-' != additional_param()[0])) for (size_t n = 1; n < argCount; n++) { WCHAR *argument = argList.At(n); WCHAR *param = NULL; if (argCount > n + 1) param = argList.At(n + 1); if (is_arg("-register-for-pdf")) { makeDefault = true; exitImmediately = true; return; } else if (is_arg("-silent")) { // silences errors happening during -print-to and -print-to-default silent = true; } else if (is_arg("-print-to-default")) { WCHAR *name = GetDefaultPrinterName(); if (name) { str::ReplacePtr(&printerName, name); free(name); } exitWhenDone = true; } else if (is_arg_with_param("-print-to")) { str::ReplacePtr(&printerName, argList.At(++n)); exitWhenDone = true; } else if (is_arg("-print-dialog")) { printDialog = true; } else if (is_arg_with_param("-print-settings")) { // argument is a comma separated list of page ranges and // advanced options [even|odd] and [noscale|shrink|fit] // e.g. -print-settings "1-3,5,10-8,odd,fit" str::ReplacePtr(&printSettings, argList.At(++n)); str::RemoveChars(printSettings, L" "); } else if (is_arg("-exit-when-done") || is_arg("-exit-on-print")) { // only affects -print-dialog (-print-to and -print-to-default // always exit on print) and -stress-test (useful for profiling) exitWhenDone = true; } else if (is_arg_with_param("-bgcolor") || is_arg_with_param("-bg-color")) { // -bgcolor is for backwards compat (was used pre-1.3) // -bg-color is for consistency ParseColor(&bgColor, argList.At(++n)); } else if (is_arg_with_param("-inverse-search")) { str::ReplacePtr(&inverseSearchCmdLine, argList.At(++n)); } else if ((is_arg_with_param("-forward-search") || is_arg_with_param("-fwdsearch")) && argCount > n + 2) { // -forward-search is for consistency with -inverse-search // -fwdsearch is for consistency with -fwdsearch-* str::ReplacePtr(&forwardSearchOrigin, argList.At(++n)); forwardSearchLine = _wtoi(argList.At(++n)); } else if (is_arg_with_param("-fwdsearch-offset")) { fwdSearch.offset = _wtoi(argList.At(++n)); } else if (is_arg_with_param("-fwdsearch-width")) { fwdSearch.width = _wtoi(argList.At(++n)); } else if (is_arg_with_param("-fwdsearch-color")) { ParseColor(&fwdSearch.color, argList.At(++n)); } else if (is_arg_with_param("-fwdsearch-permanent")) { fwdSearch.permanent = _wtoi(argList.At(++n)); } else if (is_arg("-esc-to-exit")) { escToExit = true; } else if (is_arg("-reuse-instance")) { // find the window handle of a running instance of SumatraPDF // TODO: there should be a mutex here to reduce possibility of // race condition and having more than one copy launch because // FindWindow() in one process is called before a window is created // in another process reuseInstance = (FindWindow(FRAME_CLASS_NAME, 0) != NULL); } else if (is_arg_with_param("-lang")) { free(lang); lang = str::conv::ToAnsi(argList.At(++n)); } else if (is_arg_with_param("-nameddest") || is_arg_with_param("-named-dest")) { // -nameddest is for backwards compat (was used pre-1.3) // -named-dest is for consistency str::ReplacePtr(&destName, argList.At(++n)); } else if (is_arg_with_param("-page")) { pageNumber = _wtoi(argList.At(++n)); } else if (is_arg("-restrict")) { restrictedUse = true; } // TODO: remove -invert-colors and -set-color-range in favor // of the UI settable gGlobalPrefs.useSysColors(?) else if (is_arg("-invertcolors") || is_arg("-invert-colors")) { // -invertcolors is for backwards compat (was used pre-1.3) // -invert-colors is for consistency // -invert-colors is a shortcut for -set-color-range 0xFFFFFF 0x000000 // (i.e. it sets white as foreground color and black as background color) colorRange[0] = WIN_COL_WHITE; colorRange[1] = WIN_COL_BLACK; } else if (is_arg("-set-color-range") && argCount > n + 2) { STATIC_ASSERT(sizeof(colorRange[0]) == sizeof(int), colorref_as_int); ParseColor((int *)&colorRange[0], argList.At(++n)); ParseColor((int *)&colorRange[1], argList.At(++n)); } else if (is_arg("-presentation")) { enterPresentation = true; } else if (is_arg("-fullscreen")) { enterFullscreen = true; } else if (is_arg_with_param("-view")) { ParseViewMode(&startView, argList.At(++n)); } else if (is_arg_with_param("-zoom")) { ParseZoomValue(&startZoom, argList.At(++n)); } else if (is_arg_with_param("-scroll")) { ParseScrollValue(&startScroll, argList.At(++n)); } else if (is_arg("-console")) { showConsole = true; } else if (is_arg_with_param("-plugin")) { // -plugin [<URL>] <parent HWND> if (!str::IsDigit(*param) && has_additional_param()) str::ReplacePtr(&pluginURL, argList.At(++n)); // the argument is a (numeric) window handle to // become the parent of a frameless SumatraPDF // (used e.g. for embedding it into a browser plugin) hwndPluginParent = (HWND)_wtol(argList.At(++n)); } else if (is_arg_with_param("-stress-test")) { // -stress-test <file or dir path> [<file filter>] [<page/file range(s)>] [<cycle count>x] // e.g. -stress-test file.pdf 25x for rendering file.pdf 25 times // -stress-test file.pdf 1-3 render only pages 1, 2 and 3 of file.pdf // -stress-test dir 301- 2x render all files in dir twice, skipping first 300 // -stress-test dir *.pdf;*.xps render all files in dir that are either PDF or XPS str::ReplacePtr(&stressTestPath, argList.At(++n)); int num; if (has_additional_param() && str::FindChar(additional_param(), '*')) { str::ReplacePtr(&stressTestFilter, additional_param()); n++; } if (has_additional_param() && IsValidPageRange(additional_param())) { str::ReplacePtr(&stressTestRanges, additional_param()); n++; } if (has_additional_param() && str::Parse(additional_param(), L"%dx%$", &num) && num > 0) { stressTestCycles = num; n++; } } else if (is_arg_with_param("-n")) { stressParallelCount = _wtoi(argList.At(++n)); } else if (is_arg("-rand")) { stressRandomizeFiles = true; } else if (is_arg_with_param("-bench")) { WCHAR *s = str::Dup(argList.At(++n)); pathsToBenchmark.Push(s); s = NULL; if (has_additional_param() && IsBenchPagesInfo(additional_param())) { s = str::Dup(additional_param()); n++; } pathsToBenchmark.Push(s); exitImmediately = true; } else if (is_arg("-crash-on-open")) { // to make testing of crash reporting system in pre-release/release // builds possible crashOnOpen = true; } else if (is_arg_with_param("-manga-mode")) { // TODO: we should have a ui for this instead of remembering it globally // in prefs WCHAR *s = argList.At(++n); cbxR2L = str::EqI(L"true", s) || str::Eq(L"1", s); } #if defined(SUPPORTS_AUTO_UPDATE) || defined(DEBUG) else if (is_arg_with_param("-autoupdate")) { n++; // this should have been handled already by AutoUpdateMain } #endif #ifdef DEBUG else if (is_arg("-enum-printers")) { EnumeratePrinters(); /* this is for testing only, exit immediately */ exitImmediately = true; return; } #endif else { // Remember this argument as a filename to open WCHAR *filePath = NULL; if (str::EndsWithI(argList.At(n), L".lnk")) filePath = ResolveLnk(argList.At(n)); if (!filePath) filePath = str::Dup(argList.At(n)); fileNames.Push(filePath); } } #undef is_arg #undef is_arg_with_param #undef additional_param #undef has_additional_param }