"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 }