"Fossies" - the Fresh Open Source Software Archive 
Member "xpdf-4.04/xpdf-qt/XpdfApp.cc" (18 Apr 2022, 14925 Bytes) of package /linux/misc/xpdf-4.04.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 //========================================================================
2 //
3 // XpdfApp.cc
4 //
5 // Copyright 2015 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <QFileInfo>
14 #include <QLocalSocket>
15 #ifdef _WIN32
16 # include <shlobj.h>
17 #endif
18 #include "config.h"
19 #include "parseargs.h"
20 #include "GString.h"
21 #include "GList.h"
22 #include "gfile.h"
23 #include "GlobalParams.h"
24 #include "XpdfViewer.h"
25 #include "XpdfApp.h"
26 #include "gmempp.h"
27
28 //------------------------------------------------------------------------
29 // command line options
30 //------------------------------------------------------------------------
31
32 static GBool openArg = gFalse;
33 static GBool reverseVideoArg = gFalse;
34 static char paperColorArg[256] = "";
35 static char matteColorArg[256] = "";
36 static char fsMatteColorArg[256] = "";
37 static char initialZoomArg[256] = "";
38 static int rotateArg = 0;
39 static char antialiasArg[16] = "";
40 static char vectorAntialiasArg[16] = "";
41 static char textEncArg[128] = "";
42 static char passwordArg[33] = "";
43 static GBool fullScreen = gFalse;
44 static char remoteServerArg[256] = "";
45 static char tabStateFile[256] = "";
46 static char cfgFileArg[256] = "";
47 static GBool printCommandsArg = gFalse;
48 static GBool printVersionArg = gFalse;
49 static GBool printHelpArg = gFalse;
50
51 static ArgDesc argDesc[] = {
52 {"-open", argFlag, &openArg, 0, "open file using a default remote server"},
53 {"-rv", argFlag, &reverseVideoArg, 0, "reverse video"},
54 {"-papercolor", argString, paperColorArg, sizeof(paperColorArg), "color of paper background"},
55 {"-mattecolor", argString, matteColorArg, sizeof(matteColorArg), "color of matte background"},
56 {"-fsmattecolor", argString, fsMatteColorArg, sizeof(fsMatteColorArg), "color of matte background in full-screen mode"},
57 {"-z", argString, initialZoomArg, sizeof(initialZoomArg), "initial zoom level (percent, 'page', 'width')"},
58 {"-rot", argInt, &rotateArg, 0, "initial page rotation: 0, 90, 180, or 270"},
59 {"-aa", argString, antialiasArg, sizeof(antialiasArg), "enable font anti-aliasing: yes, no"},
60 {"-aaVector", argString, vectorAntialiasArg, sizeof(vectorAntialiasArg), "enable vector anti-aliasing: yes, no"},
61 {"-enc", argString, textEncArg, sizeof(textEncArg), "output text encoding name"},
62 {"-pw", argString, passwordArg, sizeof(passwordArg), "password (for encrypted files)"},
63 {"-fullscreen", argFlag, &fullScreen, 0, "run in full-screen (presentation) mode"},
64 {"-remote", argString, remoteServerArg, sizeof(remoteServerArg), "remote server mode - remaining args are commands"},
65 {"-cmd", argFlag, &printCommandsArg, 0, "print commands as they're executed"},
66 {"-tabstate", argString, tabStateFile, sizeof(tabStateFile), "file for saving/loading tab state"},
67 {"-cfg", argString, cfgFileArg, sizeof(cfgFileArg), "configuration file to use in place of .xpdfrc"},
68 {"-v", argFlag, &printVersionArg, 0, "print copyright and version info"},
69 {"-h", argFlag, &printHelpArg, 0, "print usage information"},
70 {"-help", argFlag, &printHelpArg, 0, "print usage information"},
71 {"--help", argFlag, &printHelpArg, 0, "print usage information"},
72 {"-?", argFlag, &printHelpArg, 0, "print usage information"},
73 {NULL}
74 };
75
76 //------------------------------------------------------------------------
77 // XpdfApp
78 //------------------------------------------------------------------------
79
80 static void mungeOpenFileName(const char *fileName, GString *cmd);
81
82 XpdfApp::XpdfApp(int &argc, char **argv):
83 QApplication(argc, argv)
84 {
85 XpdfViewer *viewer;
86 QLocalSocket *sock;
87 QString sockName;
88 const char *fileName, *dest;
89 GString *color, *cmd;
90 GBool ok;
91 int pg, i;
92
93 setApplicationName("XpdfReader");
94 setApplicationVersion(xpdfVersion);
95
96 ok = parseArgs(argDesc, &argc, argv);
97 if (!ok || printVersionArg || printHelpArg) {
98 fprintf(stderr, "xpdf version %s [www.xpdfreader.com]\n", xpdfVersion);
99 fprintf(stderr, "%s\n", xpdfCopyright);
100 if (!printVersionArg) {
101 printUsage("xpdf", "[<PDF-file> [:<page> | +<dest>]] ...", argDesc);
102 }
103 ::exit(99);
104 }
105
106 //--- set up GlobalParams; handle command line arguments
107 GlobalParams::defaultTextEncoding = "UCS-2";
108 globalParams = new GlobalParams(cfgFileArg);
109 #ifdef _WIN32
110 QString dir = applicationDirPath();
111 globalParams->setBaseDir(dir.toLocal8Bit().constData());
112 dir += "/t1fonts";
113 globalParams->setupBaseFonts(dir.toLocal8Bit().constData());
114 #else
115 globalParams->setupBaseFonts(NULL);
116 #endif
117 if (initialZoomArg[0]) {
118 globalParams->setInitialZoom(initialZoomArg);
119 }
120 reverseVideo = reverseVideoArg;
121 if (paperColorArg[0]) {
122 paperColor = QColor(paperColorArg);
123 } else {
124 color = globalParams->getPaperColor();
125 paperColor = QColor(color->getCString());
126 delete color;
127 }
128 if (reverseVideo) {
129 paperColor = QColor(255 - paperColor.red(),
130 255 - paperColor.green(),
131 255 - paperColor.blue());
132 }
133 if (matteColorArg[0]) {
134 matteColor = QColor(matteColorArg);
135 } else {
136 color = globalParams->getMatteColor();
137 matteColor = QColor(color->getCString());
138 delete color;
139 }
140 if (fsMatteColorArg[0]) {
141 fsMatteColor = QColor(fsMatteColorArg);
142 } else {
143 color = globalParams->getFullScreenMatteColor();
144 fsMatteColor = QColor(color->getCString());
145 delete color;
146 }
147 color = globalParams->getSelectionColor();
148 selectionColor = QColor(color->getCString());
149 delete color;
150 if (antialiasArg[0]) {
151 if (!globalParams->setAntialias(antialiasArg)) {
152 fprintf(stderr, "Bad '-aa' value on command line\n");
153 }
154 }
155 if (vectorAntialiasArg[0]) {
156 if (!globalParams->setVectorAntialias(vectorAntialiasArg)) {
157 fprintf(stderr, "Bad '-aaVector' value on command line\n");
158 }
159 }
160 if (textEncArg[0]) {
161 globalParams->setTextEncoding(textEncArg);
162 }
163 if (tabStateFile[0]) {
164 globalParams->setTabStateFile(tabStateFile);
165 }
166 if (printCommandsArg) {
167 globalParams->setPrintCommands(gTrue);
168 }
169
170 errorEventType = QEvent::registerEventType();
171
172 viewers = new GList();
173
174 //--- remote server mode
175 if (remoteServerArg[0]) {
176 sock = new QLocalSocket(this);
177 sockName = "xpdf_";
178 sockName += remoteServerArg;
179 sock->connectToServer(sockName, QIODevice::WriteOnly);
180 if (sock->waitForConnected(5000)) {
181 for (i = 1; i < argc; ++i) {
182 sock->write(argv[i]);
183 sock->write("\n");
184 }
185 while (sock->bytesToWrite()) {
186 sock->waitForBytesWritten(5000);
187 }
188 delete sock;
189 ::exit(0);
190 } else {
191 delete sock;
192 viewer = newWindow(gFalse, remoteServerArg);
193 for (i = 1; i < argc; ++i) {
194 viewer->execCmd(argv[i], NULL);
195 }
196 return;
197 }
198 }
199
200 //--- default remote server
201 if (openArg) {
202 sock = new QLocalSocket(this);
203 sockName = "xpdf_default";
204 sock->connectToServer(sockName, QIODevice::WriteOnly);
205 if (sock->waitForConnected(5000)) {
206 if (argc >= 2) {
207 cmd = new GString("openFileIn(");
208 mungeOpenFileName(argv[1], cmd);
209 cmd->append(",tab)\nraise\n");
210 sock->write(cmd->getCString());
211 delete cmd;
212 while (sock->bytesToWrite()) {
213 sock->waitForBytesWritten(5000);
214 }
215 }
216 delete sock;
217 ::exit(0);
218 } else {
219 delete sock;
220 if (argc >= 2) {
221 // on Windows: xpdf.cc converts command line args to UTF-8
222 // on Linux: command line args are in the local 8-bit charset
223 #ifdef _WIN32
224 QString qFileName = QString::fromUtf8(argv[1]);
225 #else
226 QString qFileName = QString::fromLocal8Bit(argv[1]);
227 #endif
228 openInNewWindow(qFileName, 1, "", rotateArg, passwordArg,
229 fullScreen, "default");
230 } else {
231 newWindow(fullScreen, "default");
232 }
233 return;
234 }
235 }
236
237 //--- load PDF file(s) requested on the command line
238 if (argc >= 2) {
239 i = 1;
240 while (i < argc) {
241 pg = -1;
242 dest = "";
243 if (i+1 < argc && argv[i+1][0] == ':') {
244 fileName = argv[i];
245 pg = atoi(argv[i+1] + 1);
246 i += 2;
247 } else if (i+1 < argc && argv[i+1][0] == '+') {
248 fileName = argv[i];
249 dest = argv[i+1] + 1;
250 i += 2;
251 } else {
252 fileName = argv[i];
253 ++i;
254 }
255 // on Windows: xpdf.cc converts command line args to UTF-8
256 // on Linux: command line args are in the local 8-bit charset
257 #ifdef _WIN32
258 QString qFileName = QString::fromUtf8(fileName);
259 #else
260 QString qFileName = QString::fromLocal8Bit(fileName);
261 #endif
262 if (viewers->getLength() > 0) {
263 ok = ((XpdfViewer *)viewers->get(0))
264 ->openInNewTab(qFileName, pg, dest, rotateArg,
265 passwordArg, gFalse);
266 } else {
267 ok = openInNewWindow(qFileName, pg, dest, rotateArg,
268 passwordArg, fullScreen);
269 }
270 }
271 } else {
272 newWindow(fullScreen);
273 }
274 }
275
276 // Process the file name for the "-open" flag: convert a relative path
277 // to absolute, and add escape chars as needed. Append the modified
278 // name to [cmd].
279 static void mungeOpenFileName(const char *fileName, GString *cmd) {
280 GString *path = new GString(fileName);
281 makePathAbsolute(path);
282 for (int i = 0; i < path->getLength(); ++i) {
283 char c = path->getChar(i);
284 if (c == '(' || c == ')' || c == ',' || c == '\x01') {
285 cmd->append('\x01');
286 }
287 cmd->append(c);
288 }
289 delete path;
290 }
291
292 XpdfApp::~XpdfApp() {
293 delete viewers;
294 delete globalParams;
295 }
296
297 int XpdfApp::getNumViewers() {
298 return viewers->getLength();
299 }
300
301 XpdfViewer *XpdfApp::newWindow(GBool fullScreen,
302 const char *remoteServerName) {
303 XpdfViewer *viewer = new XpdfViewer(this, fullScreen);
304 viewers->append(viewer);
305 if (remoteServerName) {
306 viewer->startRemoteServer(remoteServerName);
307 }
308 viewer->tweakSize();
309 viewer->show();
310 return viewer;
311 }
312
313 GBool XpdfApp::openInNewWindow(QString fileName, int page, QString dest,
314 int rotate, QString password, GBool fullScreen,
315 const char *remoteServerName) {
316 XpdfViewer *viewer;
317
318 viewer = XpdfViewer::create(this, fileName, page, dest, rotate,
319 password, fullScreen);
320 if (!viewer) {
321 return gFalse;
322 }
323 viewers->append(viewer);
324 if (remoteServerName) {
325 viewer->startRemoteServer(remoteServerName);
326 }
327 viewer->tweakSize();
328 viewer->show();
329 return gTrue;
330 }
331
332 void XpdfApp::closeWindowOrQuit(XpdfViewer *viewer) {
333 int i;
334
335 viewer->close();
336 for (i = 0; i < viewers->getLength(); ++i) {
337 if ((XpdfViewer *)viewers->get(i) == viewer) {
338 viewers->del(i);
339 break;
340 }
341 }
342 }
343
344 void XpdfApp::quit() {
345 XpdfViewer *viewer;
346
347 while (viewers->getLength()) {
348 viewer = (XpdfViewer *)viewers->del(0);
349 viewer->close();
350 }
351 QApplication::quit();
352 }
353
354 //------------------------------------------------------------------------
355
356 void XpdfApp::startUpdatePagesFile() {
357 if (!globalParams->getSavePageNumbers()) {
358 return;
359 }
360 readPagesFile();
361 savedPagesFileChanged = gFalse;
362 }
363
364 void XpdfApp::updatePagesFile(const QString &fileName, int pageNumber) {
365 if (!globalParams->getSavePageNumbers()) {
366 return;
367 }
368 if (fileName.isEmpty()) {
369 return;
370 }
371 QString canonicalFileName = QFileInfo(fileName).canonicalFilePath();
372 if (canonicalFileName.isEmpty()) {
373 return;
374 }
375 XpdfSavedPageNumber s(canonicalFileName, pageNumber);
376 for (int i = 0; i < maxSavedPageNumbers; ++i) {
377 XpdfSavedPageNumber next = savedPageNumbers[i];
378 savedPageNumbers[i] = s;
379 if (next.fileName == canonicalFileName) {
380 break;
381 }
382 s = next;
383 }
384 savedPagesFileChanged = gTrue;
385 }
386
387 void XpdfApp::finishUpdatePagesFile() {
388 if (!globalParams->getSavePageNumbers()) {
389 return;
390 }
391 if (savedPagesFileChanged) {
392 writePagesFile();
393 }
394 }
395
396 int XpdfApp::getSavedPageNumber(const QString &fileName) {
397 if (!globalParams->getSavePageNumbers()) {
398 return 1;
399 }
400 readPagesFile();
401 QString canonicalFileName = QFileInfo(fileName).canonicalFilePath();
402 if (canonicalFileName.isEmpty()) {
403 return 1;
404 }
405 for (int i = 0; i < maxSavedPageNumbers; ++i) {
406 if (savedPageNumbers[i].fileName == canonicalFileName) {
407 return savedPageNumbers[i].pageNumber;
408 }
409 }
410 return 1;
411 }
412
413 void XpdfApp::readPagesFile() {
414 // construct the file name (first time only)
415 if (savedPagesFileName.isEmpty()) {
416 #ifdef _WIN32
417 char path[MAX_PATH];
418 if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
419 SHGFP_TYPE_CURRENT, path) != S_OK) {
420 return;
421 }
422 savedPagesFileName = QString::fromLocal8Bit(path);
423 savedPagesFileName.append("/xpdf");
424 CreateDirectory(savedPagesFileName.toLocal8Bit().constData(), NULL);
425 savedPagesFileName.append("/xpdf.pages");
426 #else
427 GString *path = getHomeDir();
428 savedPagesFileName = QString::fromUtf8(path->getCString());
429 delete path;
430 savedPagesFileName.append("/.xpdf.pages");
431 #endif
432 }
433
434 // no change since last read, so no need to re-read
435 if (savedPagesFileTimestamp.isValid() &&
436 QFileInfo(savedPagesFileName).lastModified() == savedPagesFileTimestamp) {
437 return;
438 }
439
440 // mark all entries invalid
441 for (int i = 0; i < maxSavedPageNumbers; ++i) {
442 savedPageNumbers[i].fileName.clear();
443 savedPageNumbers[i].pageNumber = 1;
444 }
445
446 // read the file
447 FILE *f = openFile(savedPagesFileName.toUtf8().constData(), "rb");
448 if (!f) {
449 return;
450 }
451 char buf[1024];
452 if (!fgets(buf, sizeof(buf), f) ||
453 strcmp(buf, "xpdf.pages-1\n") != 0) {
454 fclose(f);
455 return;
456 }
457 int i = 0;
458 while (i < maxSavedPageNumbers && fgets(buf, sizeof(buf), f)) {
459 int n = (int)strlen(buf);
460 if (n > 0 && buf[n-1] == '\n') {
461 buf[n-1] = '\0';
462 }
463 char *p = buf;
464 while (*p != ' ' && *p) {
465 ++p;
466 }
467 if (!*p) {
468 continue;
469 }
470 *p++ = '\0';
471 savedPageNumbers[i].pageNumber = atoi(buf);
472 savedPageNumbers[i].fileName = QString::fromUtf8(p);
473 ++i;
474 }
475 fclose(f);
476
477 // save the timestamp
478 savedPagesFileTimestamp = QFileInfo(savedPagesFileName).lastModified();
479 }
480
481 void XpdfApp::writePagesFile() {
482 if (savedPagesFileName.isEmpty()) {
483 return;
484 }
485 FILE *f = openFile(savedPagesFileName.toUtf8().constData(), "wb");
486 if (!f) {
487 return;
488 }
489 fprintf(f, "xpdf.pages-1\n");
490 for (int i = 0; i < maxSavedPageNumbers; ++i) {
491 if (!savedPageNumbers[i].fileName.isEmpty()) {
492 fprintf(f, "%d %s\n",
493 savedPageNumbers[i].pageNumber,
494 savedPageNumbers[i].fileName.toUtf8().constData());
495 }
496 }
497 fclose(f);
498 savedPagesFileTimestamp = QFileInfo(savedPagesFileName).lastModified();
499 }