"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. For more information about "XpdfApp.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.03_vs_4.04.

    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 }