X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=inline;f=pdf%2Fxpdf%2Fxpdf.cc;h=ff5455031535202237a758ff383dab047c40cfa6;hb=f08fe47c41d7b8393c93c14395ef25a0acb57fef;hp=dd31b941538af58be53e33e292242f2141799fbc;hpb=f4fb298e749b16d591ebd1cb15cfec8c2c3efeec;p=evince.git diff --git a/pdf/xpdf/xpdf.cc b/pdf/xpdf/xpdf.cc index dd31b941..ff545503 100644 --- a/pdf/xpdf/xpdf.cc +++ b/pdf/xpdf/xpdf.cc @@ -2,14 +2,16 @@ // // xpdf.cc // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // //======================================================================== +#include #include #include #include #include +#include #include #include #include @@ -18,6 +20,7 @@ #include "parseargs.h" #include "gfile.h" #include "gmem.h" +#include "GlobalParams.h" #include "LTKAll.h" #include "Object.h" #include "Stream.h" @@ -32,7 +35,6 @@ #include "LTKOutputDev.h" #include "PSOutputDev.h" #include "TextOutputDev.h" -#include "Params.h" #include "Error.h" #include "config.h" @@ -51,18 +53,58 @@ typedef char *XPointer; #ifndef XK_Page_Down #define XK_Page_Down 0xFF56 #endif +#ifndef XK_KP_Home +#define XK_KP_Home 0xFF95 +#endif +#ifndef XK_KP_Left +#define XK_KP_Left 0xFF96 +#endif +#ifndef XK_KP_Up +#define XK_KP_Up 0xFF97 +#endif +#ifndef XK_KP_Right +#define XK_KP_Right 0xFF98 +#endif +#ifndef XK_KP_Down +#define XK_KP_Down 0xFF99 +#endif +#ifndef XK_KP_Prior +#define XK_KP_Prior 0xFF9A +#endif +#ifndef XK_KP_Page_Up +#define XK_KP_Page_Up 0xFF9A +#endif +#ifndef XK_KP_Next +#define XK_KP_Next 0xFF9B +#endif +#ifndef XK_KP_Page_Down +#define XK_KP_Page_Down 0xFF9B +#endif +#ifndef XK_KP_End +#define XK_KP_End 0xFF9C +#endif +#ifndef XK_KP_Begin +#define XK_KP_Begin 0xFF9D +#endif +#ifndef XK_KP_Insert +#define XK_KP_Insert 0xFF9E +#endif +#ifndef XK_KP_Delete +#define XK_KP_Delete 0xFF9F +#endif //------------------------------------------------------------------------ // misc constants / enums //------------------------------------------------------------------------ -#define remoteCmdLength 256 +#define remoteCmdLength 512 enum XpdfMenuItem { menuOpen, + menuReload, menuSavePDF, - menuRotateLeft, - menuRotateRight, + menuRotateCCW, + menuRotateCW, menuQuit }; @@ -72,7 +114,9 @@ enum XpdfMenuItem { // loadFile / displayPage static GBool loadFile(GString *fileName); -static void displayPage(int page1, int zoom1, int rotate1, GBool addToHist); +static void displayPage(int page1, int zoomA, int rotateA, GBool addToHist); +static void displayDest(LinkDest *dest, int zoomA, int rotateA, + GBool addToHist); // key press and menu callbacks static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers, @@ -92,8 +136,10 @@ static void mouseDragCbk(LTKWidget *widget, int widgetNum, // button callbacks static void nextPageCbk(LTKWidget *button, int n, GBool on); static void nextTenPageCbk(LTKWidget *button, int n, GBool on); +static void gotoNextPage(int inc, GBool top); static void prevPageCbk(LTKWidget *button, int n, GBool on); static void prevTenPageCbk(LTKWidget *button, int n, GBool on); +static void gotoPrevPage(int dec, GBool top, GBool bottom); static void backCbk(LTKWidget *button, int n, GBool on); static void forwardCbk(LTKWidget *button, int n, GBool on); static void pageNumCbk(LTKWidget *textIn, int n, GString *text); @@ -119,6 +165,9 @@ static void mapOpenDialog(); static void openButtonCbk(LTKWidget *button, int n, GBool on); static void openSelectCbk(LTKWidget *widget, int n, GString *name); +// "Reload" +static void reloadCbk(); + // "Save PDF" dialog static void mapSaveDialog(); static void saveButtonCbk(LTKWidget *button, int n, GBool on); @@ -131,6 +180,9 @@ static void psButtonCbk(LTKWidget *button, int n, GBool on); // "About" window static void mapAboutWin(); static void closeAboutCbk(LTKWidget *button, int n, GBool on); +static void aboutLayoutCbk(LTKWindow *winA); +static void aboutScrollVertCbk(LTKWidget *scrollbar, int n, int val); +static void aboutScrollHorizCbk(LTKWidget *scrollbar, int n, int val); // "Find" window static void findCbk(LTKWidget *button, int n, GBool on); @@ -142,88 +194,172 @@ static void doFind(char *s); static void killCbk(LTKWindow *win1); //------------------------------------------------------------------------ -// command line options +// "About" window text //------------------------------------------------------------------------ -static XrmOptionDescRec opts[] = { - {"-display", ".display", XrmoptionSepArg, NULL}, - {"-foreground", ".foreground", XrmoptionSepArg, NULL}, - {"-fg", ".foreground", XrmoptionSepArg, NULL}, - {"-background", ".background", XrmoptionSepArg, NULL}, - {"-bg", ".background", XrmoptionSepArg, NULL}, - {"-geometry", ".geometry", XrmoptionSepArg, NULL}, - {"-g", ".geometry", XrmoptionSepArg, NULL}, - {"-font", ".font", XrmoptionSepArg, NULL}, - {"-fn", ".font", XrmoptionSepArg, NULL}, - {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"}, - {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL}, - {"-papercolor", ".paperColor", XrmoptionSepArg, NULL}, -#if JAPANESE_SUPPORT - {"-eucjp", ".eucjp", XrmoptionNoArg, (XPointer)"off"}, -#endif -#if HAVE_T1LIB_H - {"-t1lib", ".t1libControl", XrmoptionSepArg, NULL}, -#endif - {"-z", ".initialZoom", XrmoptionSepArg, NULL}, - {"-ps", ".psFile", XrmoptionSepArg, NULL}, - {"-paperw", ".psPaperWidth", XrmoptionSepArg, NULL}, - {"-paperh", ".psPaperHeight", XrmoptionSepArg, NULL}, - {"-level1", ".psLevel1", XrmoptionNoArg, (XPointer)"false"}, - {NULL} +static char *aboutWinText[] = { + "X X d fff", + " X X d f f", + " X X d f", + " X pppp dddd ffff", + " X X p p d d f", + " X X p p d d f", + "X X pppp dddd f Version " xpdfVersion, + " p", + " p", + " p", + "", + xpdfCopyright, + "", + "http://www.foolabs.com/xpdf/", + "derekn@foolabs.com", + "", + "Licensed under the GNU General Public License (GPL).", + "See the 'COPYING' file for details.", + "", + "Supports PDF version " supportedPDFVersionStr ".", + "", + "The PDF data structures, operators, and specification", + "are copyright 1985-2001 Adobe Systems Inc.", + "", + "Mouse bindings:", + " button 1: select text / follow link", + " button 2: pan window", + " button 3: menu", + "", + "Key bindings:", + " o = open file", + " r = reload", + " f = find text", + " n = = next page", + " p = = previous page", + " = scroll down", + " = = scroll up", + " v = forward (history path)", + " b = backward (history path)", + " 0 / + / - = zoom zero / in / out", + " z / w = zoom page / page width", + " ctrl-L = redraw", + " q = quit", + " / = top / bottom of page", + " = scroll", + "", + "For more information, please read the xpdf(1) man page.", + NULL }; -GBool printCommands = gFalse; -static GBool printHelp = gFalse; +//------------------------------------------------------------------------ +// command line options +//------------------------------------------------------------------------ + +static char initialZoomStr[32] = ""; +static char t1libControlStr[16] = ""; +static char freetypeControlStr[16] = ""; +static char psFileArg[256]; +static char paperSize[15] = ""; +static int paperWidth = 0; +static int paperHeight = 0; +static GBool level1 = gFalse; +static char textEncName[128] = ""; +static char textEOL[16] = ""; +static char ownerPassword[33] = ""; +static char userPassword[33] = ""; +static GBool fullScreen = gFalse; static char remoteName[100] = "xpdf_"; static GBool doRemoteRaise = gFalse; static GBool doRemoteQuit = gFalse; +static GBool printCommands = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; static GBool viKeys = gFalse; static ArgDesc argDesc[] = { - {"-err", argFlag, &errorsToTTY, 0, - "send error messages to /dev/tty instead of stderr"}, - {"-z", argStringDummy, NULL, 0, - "initial zoom level (-5..5, page, width)"}, {"-g", argStringDummy, NULL, 0, "initial window geometry"}, {"-geometry", argStringDummy, NULL, 0, "initial window geometry"}, - {"-remote", argString, remoteName + 5, sizeof(remoteName) - 5, - "start/contact xpdf remote server with specified name"}, - {"-raise", argFlag, &doRemoteRaise, 0, - "raise xpdf remote server window (with -remote only)"}, - {"-quit", argFlag, &doRemoteQuit, 0, - "kill xpdf remote server (with -remote only)"}, + {"-title", argStringDummy, NULL, 0, + "window title"}, {"-cmap", argFlagDummy, NULL, 0, "install a private colormap"}, {"-rgb", argIntDummy, NULL, 0, "biggest RGB cube to allocate (default is 5)"}, + {"-rv", argFlagDummy, NULL, 0, + "reverse video"}, {"-papercolor", argStringDummy, NULL, 0, "color of paper background"}, -#if JAPANESE_SUPPORT - {"-eucjp", argStringDummy, NULL, 0, - "convert Japanese text to EUC-JP"}, -#endif + {"-z", argString, initialZoomStr, sizeof(initialZoomStr), + "initial zoom level (-5..5, page, width)"}, #if HAVE_T1LIB_H - {"-t1lib", argStringDummy, NULL, 0, - "t1lib font control: none, plain, low, high"}, + {"-t1lib", argString, t1libControlStr, sizeof(t1libControlStr), + "t1lib font rasterizer control: none, plain, low, high"}, +#endif +#if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H + {"-freetype", argString, freetypeControlStr, sizeof(freetypeControlStr), + "FreeType font rasterizer control: none, plain, low, high"}, #endif - {"-ps", argStringDummy, NULL, 0, - "default PostScript file/command name"}, - {"-paperw", argIntDummy, NULL, 0, + {"-ps", argString, psFileArg, sizeof(psFileArg), + "default PostScript file name or command"}, + {"-paper", argString, paperSize, sizeof(paperSize), + "paper size (letter, legal, A4, A3)"}, + {"-paperw", argInt, &paperWidth, 0, "paper width, in points"}, - {"-paperh", argIntDummy, NULL, 0, + {"-paperh", argInt, &paperHeight, 0, "paper height, in points"}, - {"-level1", argFlagDummy, NULL, 0, + {"-level1", argFlag, &level1, 0, "generate Level 1 PostScript"}, + {"-enc", argString, textEncName, sizeof(textEncName), + "output text encoding name"}, + {"-eol", argString, textEOL, sizeof(textEOL), + "output end-of-line convention (unix, dos, or mac)"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-fullscreen", argFlag, &fullScreen, 0, + "run in full-screen (presentation) mode"}, + {"-remote", argString, remoteName + 5, sizeof(remoteName) - 5, + "start/contact xpdf remote server with specified name"}, + {"-raise", argFlag, &doRemoteRaise, 0, + "raise xpdf remote server window (with -remote only)"}, + {"-quit", argFlag, &doRemoteQuit, 0, + "kill xpdf remote server (with -remote only)"}, {"-cmd", argFlag, &printCommands, 0, "print commands as they're executed"}, - {"-q", argFlag, &errQuiet, 0, + {"-q", argFlag, &quiet, 0, "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, {"-h", argFlag, &printHelp, 0, "print usage information"}, {"-help", argFlag, &printHelp, 0, "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +static XrmOptionDescRec opts[] = { + {"-display", ".display", XrmoptionSepArg, NULL}, + {"-foreground", ".foreground", XrmoptionSepArg, NULL}, + {"-fg", ".foreground", XrmoptionSepArg, NULL}, + {"-background", ".background", XrmoptionSepArg, NULL}, + {"-bg", ".background", XrmoptionSepArg, NULL}, + {"-geometry", ".geometry", XrmoptionSepArg, NULL}, + {"-g", ".geometry", XrmoptionSepArg, NULL}, + {"-font", ".font", XrmoptionSepArg, NULL}, + {"-fn", ".font", XrmoptionSepArg, NULL}, + {"-title", ".title", XrmoptionSepArg, NULL}, + {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"}, + {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL}, + {"-rv", ".reverseVideo", XrmoptionNoArg, (XPointer)"true"}, + {"-papercolor", ".paperColor", XrmoptionSepArg, NULL}, {NULL} }; @@ -236,13 +372,12 @@ static ArgDesc argDesc[] = { #define maxZoom 5 #define zoomPage 100 #define zoomWidth 101 +#define defZoom 1 static int zoomDPI[maxZoom - minZoom + 1] = { 29, 35, 42, 50, 60, 72, 86, 104, 124, 149, 179 }; -#define defZoom 1 -#define defZoomStr "1" static PDFDoc *doc; @@ -253,6 +388,8 @@ static int zoom; static int rotate; static GBool quit; +static time_t modTime; // last modification time of PDF file + static LinkAction *linkAction; // mouse pointer is over this link static int // coordinates of current selection: selectXMin, selectYMin, // (xMin==xMax || yMin==yMax) means there @@ -274,7 +411,6 @@ static int historyBLen; // number of valid entries backward from static int historyFLen; // number of valid entries forward from // current entry -static GString *defPSFileName; static GString *psFileName; static int psFirstPage, psLastPage; @@ -282,6 +418,8 @@ static GString *fileReqDir; // current directory for file requesters static GString *urlCommand; // command to execute for URI links +static GString *windowTitle; // window title string + static LTKApp *app; static Display *display; static LTKWindow *win; @@ -293,10 +431,13 @@ static LTKLabel *numPagesLabel; static LTKLabel *linkLabel; static LTKMenuButton *zoomMenuBtn; static LTKWindow *aboutWin; +static LTKList *aboutList; +static LTKScrollbar *aboutHScrollbar, *aboutVScrollbar; static LTKWindow *psDialog; static LTKWindow *openDialog; static LTKWindow *saveDialog; static LTKWindow *findWin; +static LTKTextIn *findTextIn; static Atom remoteAtom; static GC selectGC; @@ -327,11 +468,17 @@ int main(int argc, char *argv[]) { LTKMenu *menu; GString *name; GString *title; + GString *initialZoom; + GBool reverseVideo; unsigned long paperColor; + GBool installCmap; + int rgbCubeSize; int pg; + GString *destName; + LinkDest *dest; int x, y; Guint width, height; - GString *zoomStr; + double width1, height1; GBool ok; char s[20]; int i; @@ -343,23 +490,60 @@ int main(int argc, char *argv[]) { out = NULL; remoteAtom = None; doc = NULL; - xref = NULL; psFileName = NULL; fileReqDir = getCurrentDir(); ret = 0; // parse args - paperWidth = paperHeight = -1; ok = parseArgs(argDesc, &argc, argv); - // init error file - errorInit(); - // read config file - initParams(xpdfConfigFile); + globalParams = new GlobalParams(cfgFileName); + if (psFileArg[0]) { + globalParams->setPSFile(psFileArg); + } + if (paperSize[0]) { + if (!globalParams->setPSPaperSize(paperSize)) { + fprintf(stderr, "Invalid paper size\n"); + } + } else { + if (paperWidth) { + globalParams->setPSPaperWidth(paperWidth); + } + if (paperHeight) { + globalParams->setPSPaperHeight(paperHeight); + } + } + if (level1) { + globalParams->setPSLevel(psLevel1); + } + if (textEncName[0]) { + globalParams->setTextEncoding(textEncName); + } + if (textEOL[0]) { + if (!globalParams->setTextEOL(textEOL)) { + fprintf(stderr, "Bad '-eol' value on command line\n"); + } + } + if (initialZoomStr[0]) { + globalParams->setInitialZoom(initialZoomStr); + } + if (t1libControlStr[0]) { + if (!globalParams->setT1libControl(t1libControlStr)) { + fprintf(stderr, "Bad '-t1lib' value on command line\n"); + } + } + if (freetypeControlStr[0]) { + if (!globalParams->setFreeTypeControl(freetypeControlStr)) { + fprintf(stderr, "Bad '-freetype' value on command line\n"); + } + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } // create LTKApp (and parse X-related args) - app = new LTKApp("xpdf", opts, &argc, argv); + app = new LTKApp("xpdf", "Xpdf", opts, &argc, argv); app->setKillCbk(&killCbk); display = app->getDisplay(); @@ -370,21 +554,29 @@ int main(int argc, char *argv[]) { ok = ok && remoteName[5] && argc == 1; else ok = ok && argc >= 1 && argc <= 3; - if (!ok || printHelp) { + if (!ok || printVersion || printHelp) { fprintf(stderr, "xpdf version %s\n", xpdfVersion); fprintf(stderr, "%s\n", xpdfCopyright); - printUsage("xpdf", "[ []]", argDesc); + if (!printVersion) { + printUsage("xpdf", "[ [ | +]]", argDesc); + } ret = 1; goto done2; } - if (argc >= 2) + if (argc >= 2) { name = new GString(argv[1]); - else + } else { name = NULL; - if (argc == 3) - pg = atoi(argv[2]); - else - pg = 1; + } + pg = 1; + destName = NULL; + if (argc == 3) { + if (argv[2][0] == '+') { + destName = new GString(&argv[2][1]); + } else { + pg = atoi(argv[2]); + } + } // look for already-running remote server if (remoteName[5]) { @@ -392,8 +584,14 @@ int main(int argc, char *argv[]) { xwin = XGetSelectionOwner(display, remoteAtom); if (xwin != None) { if (name) { - sprintf(cmd, "%c %d %.200s", doRemoteRaise ? 'D' : 'd', - pg, name->getCString()); + if (destName) { + sprintf(cmd, "%c +%.256s %.200s", doRemoteRaise ? 'D' : 'd', + destName->getCString(), name->getCString()); + delete destName; + } else { + sprintf(cmd, "%c %d %.200s", doRemoteRaise ? 'D' : 'd', + pg, name->getCString()); + } XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8, PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1); delete name; @@ -406,14 +604,12 @@ int main(int argc, char *argv[]) { } goto done2; } - if (doRemoteQuit) + if (doRemoteQuit) { + if (destName) { + delete destName; + } goto done2; - } - - // print banner - if (!errQuiet) { - fprintf(errFile, "xpdf version %s\n", xpdfVersion); - fprintf(errFile, "%s\n", xpdfCopyright); + } } // no history yet @@ -423,7 +619,6 @@ int main(int argc, char *argv[]) { history[i].fileName = NULL; // open PDF file - defPSFileName = app->getStringResource("psFile", NULL); if (name) { if (!loadFile(name)) { ret = 1; @@ -434,13 +629,20 @@ int main(int argc, char *argv[]) { } // check for legal page number - if (doc && (pg < 1 || pg > doc->getNumPages())) + if (doc && (pg < 1 || pg > doc->getNumPages())) { pg = 1; + } // create window menu = makeMenu(); - zoomMenu = makeZoomMenu(); - win = makeWindow(app); + if (fullScreen) { + zoomMenu = NULL; + win = makeFullScreenWindow(app); + win->setDecorated(gFalse); + } else { + zoomMenu = makeZoomMenu(); + win = makeWindow(app); + } win->setMenu(menu); canvas = (LTKScrollingCanvas *)win->findWidget("canvas"); hScrollbar = (LTKScrollbar *)win->findWidget("hScrollbar"); @@ -455,100 +657,98 @@ int main(int argc, char *argv[]) { canvas->setButtonReleaseCbk(&buttonReleaseCbk); canvas->setMouseMoveCbk(&mouseMoveCbk); canvas->setMouseDragCbk(&mouseDragCbk); - hScrollbar->setRepeatPeriod(0); - vScrollbar->setRepeatPeriod(0); + if (!fullScreen) { + hScrollbar->setRepeatPeriod(0); + vScrollbar->setRepeatPeriod(0); + } + + // get parameters + urlCommand = globalParams->getURLCommand(); // get X resources - paperWidth = app->getIntResource("psPaperWidth", defPaperWidth); - paperHeight = app->getIntResource("psPaperHeight", defPaperHeight); - psOutLevel1 = app->getBoolResource("psLevel1", gFalse); - urlCommand = app->getStringResource("urlCommand", NULL); + windowTitle = app->getStringResource("title", NULL); installCmap = app->getBoolResource("installCmap", gFalse); - if (installCmap) + if (installCmap) { win->setInstallCmap(gTrue); + } rgbCubeSize = app->getIntResource("rgbCubeSize", defaultRGBCube); - paperColor = app->getColorResource("paperColor", "white", - WhitePixel(display, app->getScreenNum()), - NULL); -#if JAPANESE_SUPPORT - useEUCJP = app->getBoolResource("eucjp", gFalse); -#else - useEUCJP = gFalse; -#endif -#if HAVE_T1LIB_H - t1libControl = app->getStringResource("t1libControl", "low"); -#endif - t1Courier = app->getStringResource("t1Courier", NULL); - t1CourierBold = app->getStringResource("t1CourierBold", NULL); - t1CourierBoldOblique = app->getStringResource("t1CourierBoldOblique", NULL); - t1CourierOblique = app->getStringResource("t1CourierOblique", NULL); - t1Helvetica = app->getStringResource("t1Helvetica", NULL); - t1HelveticaBold = app->getStringResource("t1HelveticaBold", NULL); - t1HelveticaBoldOblique = - app->getStringResource("t1HelveticaBoldOblique", NULL); - t1HelveticaOblique = app->getStringResource("t1HelveticaOblique", NULL); - t1Symbol = app->getStringResource("t1Symbol", NULL); - t1TimesBold = app->getStringResource("t1TimesBold", NULL); - t1TimesBoldItalic = app->getStringResource("t1TimesBoldItalic", NULL); - t1TimesItalic = app->getStringResource("t1TimesItalic", NULL); - t1TimesRoman = app->getStringResource("t1TimesRoman", NULL); - t1ZapfDingbats = app->getStringResource("t1ZapfDingbats", NULL); -#if JAPANESE_SUPPORT - japan12Font = app->getStringResource("japaneseFont", NULL); -#endif - zoomStr = app->getStringResource("initialZoom", defZoomStr); - if (!zoomStr->cmp("page")) { + reverseVideo = app->getBoolResource("reverseVideo", gFalse); + paperColor = app->getColorResource( + "paperColor", + reverseVideo ? (char *)"black" : (char *)"white", + reverseVideo ? BlackPixel(display, app->getScreenNum()) + : WhitePixel(display, app->getScreenNum()), + NULL); + if (fullScreen) { zoom = zoomPage; - i = maxZoom - minZoom + 2; - } else if (!zoomStr->cmp("width")) { - zoom = zoomWidth; - i = maxZoom - minZoom + 3; } else { - zoom = atoi(zoomStr->getCString()); - if (zoom < minZoom) - zoom = minZoom; - else if (zoom > maxZoom) - zoom = maxZoom; - i = zoom - minZoom; - } - delete zoomStr; - zoomMenuBtn->setInitialMenuItem(zoomMenu->getItem(i)); + initialZoom = globalParams->getInitialZoom(); + if (!initialZoom->cmp("page")) { + zoom = zoomPage; + i = maxZoom - minZoom + 2; + } else if (!initialZoom->cmp("width")) { + zoom = zoomWidth; + i = maxZoom - minZoom + 3; + } else { + zoom = atoi(initialZoom->getCString()); + if (zoom < minZoom) { + zoom = minZoom; + } else if (zoom > maxZoom) { + zoom = maxZoom; + } + i = zoom - minZoom; + } + zoomMenuBtn->setInitialMenuItem(zoomMenu->getItem(i)); + } viKeys = app->getBoolResource("viKeys", gFalse); // get geometry - x = y = -1; - width = height = 0; - app->getGeometryResource("geometry", &x, &y, &width, &height); - if (width == 0 || height == 0) { - if (!doc || doc->getNumPages() == 0) { - width = 612; - height = 792; - } else if (doc->getPageRotate(pg) == 90 || doc->getPageRotate(pg) == 270) { - width = (int)(doc->getPageHeight(pg) + 0.5); - height = (int)(doc->getPageWidth(pg) + 0.5); - } else { - width = (int)(doc->getPageWidth(pg) + 0.5); - height = (int)(doc->getPageHeight(pg) + 0.5); - } - if (zoom == zoomPage || zoom == zoomWidth) { - width = (width * zoomDPI[defZoom - minZoom]) / 72 + 28; - height = (height * zoomDPI[defZoom - minZoom]) / 72 + 56; - } else { - width = (width * zoomDPI[zoom - minZoom]) / 72 + 28; - height = (height * zoomDPI[zoom - minZoom]) / 72 + 56; - } - if (width > (Guint)app->getDisplayWidth() - 100) { - width = app->getDisplayWidth() - 100; - } - if (height > (Guint)app->getDisplayHeight() - 100) { - height = app->getDisplayHeight() - 100; + if (fullScreen) { + x = y = 0; + width = app->getDisplayWidth(); + height = app->getDisplayHeight(); + } else { + x = y = -1; + width = height = 0; + app->getGeometryResource("geometry", &x, &y, &width, &height); + if (width == 0 || height == 0) { + if (!doc || doc->getNumPages() == 0) { + width1 = 612; + height1 = 792; + } else if (doc->getPageRotate(pg) == 90 || + doc->getPageRotate(pg) == 270) { + width1 = doc->getPageHeight(pg); + height1 = doc->getPageWidth(pg); + } else { + width1 = doc->getPageWidth(pg); + height1 = doc->getPageHeight(pg); + } + if (zoom == zoomPage || zoom == zoomWidth) { + width = (int)((width1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5); + height = (int)((height1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5); + } else { + width = (int)((width1 * zoomDPI[zoom - minZoom]) / 72 + 0.5); + height = (int)((height1 * zoomDPI[zoom - minZoom]) / 72 + 0.5); + } + width += 28; + height += 56; + if (width > (Guint)app->getDisplayWidth() - 100) { + width = app->getDisplayWidth() - 100; + } + if (height > (Guint)app->getDisplayHeight() - 100) { + height = app->getDisplayHeight() - 100; + } } } // finish setting up window - sprintf(s, "of %d", doc ? doc->getNumPages() : 0); - numPagesLabel->setText(s); - if (name) { + if (!fullScreen) { + sprintf(s, "of %d", doc ? doc->getNumPages() : 0); + numPagesLabel->setText(s); + } + if (windowTitle) { + title = windowTitle->copy(); + } else if (name) { title = new GString("xpdf: "); title->append(name); } else { @@ -576,11 +776,25 @@ int main(int argc, char *argv[]) { } // create output device - out = new LTKOutputDev(win, paperColor); - out->startDoc(); + out = new LTKOutputDev(win, reverseVideo, paperColor, + installCmap, rgbCubeSize, !fullScreen); + out->startDoc(doc ? doc->getXRef() : (XRef *)NULL); // display first page - displayPage(pg, zoom, 0, gTrue); + if (destName) { + if (doc) { + if ((dest = doc->findDest(destName))) { + displayDest(dest, zoom, 0, gTrue); + delete dest; + } else { + error(-1, "Unknown named destination '%s'", destName->getCString()); + displayPage(1, zoom, 0, gTrue); + } + } + delete destName; + } else { + displayPage(pg, zoom, 0, gTrue); + } // event loop quit = gFalse; @@ -595,82 +809,55 @@ int main(int argc, char *argv[]) { done2: // free stuff - if (out) + if (out) { delete out; - if (win) + } + if (win) { delete win; - if (aboutWin) + } + if (aboutWin) { delete aboutWin; - if (findWin) + } + if (findWin) { delete findWin; - if (app) + } + if (app) { delete app; - if (doc) + } + if (doc) { delete doc; - if (psFileName) + } + if (psFileName) { delete psFileName; - if (defPSFileName) - delete defPSFileName; - if (fileReqDir) + } + if (fileReqDir) { delete fileReqDir; - if (urlCommand) - delete urlCommand; -#if HAVE_T1LIB_H - if (t1libControl) - delete t1libControl; -#endif - if (t1Courier) - delete t1Courier; - if (t1CourierBold) - delete t1CourierBold; - if (t1CourierBoldOblique) - delete t1CourierBoldOblique; - if (t1CourierOblique) - delete t1CourierOblique; - if (t1Helvetica) - delete t1Helvetica; - if (t1HelveticaBold) - delete t1HelveticaBold; - if (t1HelveticaBoldOblique) - delete t1HelveticaBoldOblique; - if (t1HelveticaOblique) - delete t1HelveticaOblique; - if (t1Symbol) - delete t1Symbol; - if (t1TimesBold) - delete t1TimesBold; - if (t1TimesBoldItalic) - delete t1TimesBoldItalic; - if (t1TimesItalic) - delete t1TimesItalic; - if (t1TimesRoman) - delete t1TimesRoman; - if (t1ZapfDingbats) - delete t1ZapfDingbats; -#if JAPANESE_FONT - if (japan12Font) - delete japan12Font; -#endif + } + if (windowTitle) { + delete windowTitle; + } for (i = 0; i < historySize; ++i) { - if (history[i].fileName) + if (history[i].fileName) { delete history[i].fileName; + } } - freeParams(); + delete globalParams; // check for memory leaks - Object::memCheck(errFile ? errFile : stderr); - gMemReport(errFile ? errFile : stderr); + Object::memCheck(stderr); + gMemReport(stderr); return ret; } //------------------------------------------------------------------------ -// loadFile / displayPage +// loadFile / displayPage / displayDest //------------------------------------------------------------------------ static GBool loadFile(GString *fileName) { GString *title; PDFDoc *newDoc; + GString *ownerPW, *userPW; char s[20]; char *p; @@ -679,7 +866,23 @@ static GBool loadFile(GString *fileName) { win->setBusyCursor(gTrue); // open PDF file - newDoc = new PDFDoc(fileName); + if (ownerPassword[0]) { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0]) { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + newDoc = new PDFDoc(fileName, ownerPW, userPW, printCommands); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } if (!newDoc->isOk()) { delete newDoc; if (win) @@ -691,17 +894,21 @@ static GBool loadFile(GString *fileName) { if (doc) delete doc; doc = newDoc; - if (out) - out->startDoc(); + if (out) { + out->startDoc(doc->getXRef()); + } // nothing displayed yet page = -99; + // save the modification time + modTime = getModTime(fileName->getCString()); + // init PostScript output params if (psFileName) delete psFileName; - if (defPSFileName) { - psFileName = defPSFileName->copy(); + if (globalParams->getPSFile()) { + psFileName = globalParams->getPSFile()->copy(); } else { p = fileName->getCString() + fileName->getLength() - 4; if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) @@ -716,11 +923,15 @@ static GBool loadFile(GString *fileName) { // set up title, number-of-pages display; back to normal cursor if (win) { - title = new GString("xpdf: "); - title->append(fileName); - win->setTitle(title); - sprintf(s, "of %d", doc->getNumPages()); - numPagesLabel->setText(s); + if (!windowTitle) { + title = new GString("xpdf: "); + title->append(fileName); + win->setTitle(title); + } + if (!fullScreen) { + sprintf(s, "of %d", doc->getNumPages()); + numPagesLabel->setText(s); + } win->setBusyCursor(gFalse); } @@ -728,7 +939,8 @@ static GBool loadFile(GString *fileName) { return gTrue; } -static void displayPage(int page1, int zoom1, int rotate1, GBool addToHist) { +static void displayPage(int pageA, int zoomA, int rotateA, GBool addToHist) { + time_t modTime1; double hDPI, vDPI, dpi; int rot; char s[20]; @@ -738,19 +950,32 @@ static void displayPage(int page1, int zoom1, int rotate1, GBool addToHist) { if (!doc || doc->getNumPages() == 0) return; + // check for changes to the file + modTime1 = getModTime(doc->getFileName()->getCString()); + if (modTime1 != modTime) { + if (loadFile(doc->getFileName()->copy())) { + if (pageA > doc->getNumPages()) { + pageA = doc->getNumPages(); + } + } + modTime = modTime1; + } + // busy cursor if (win) win->setBusyCursor(gTrue); // new page/zoom/rotate values - page = page1; - zoom = zoom1; - rotate = rotate1; + page = pageA; + zoom = zoomA; + rotate = rotateA; // initialize mouse-related stuff linkAction = NULL; win->setDefaultCursor(); - linkLabel->setText(NULL); + if (!fullScreen) { + linkLabel->setText(NULL); + } selectXMin = selectXMax = 0; selectYMin = selectYMax = 0; lastDragLeft = lastDragTop = gTrue; @@ -761,30 +986,41 @@ static void displayPage(int page1, int zoom1, int rotate1, GBool addToHist) { rot -= 360; else if (rotate < 0) rot += 360; - if (zoom == zoomPage) { + if (fullScreen) { if (rot == 90 || rot == 270) { - hDPI = ((win->getWidth() - 28) / doc->getPageHeight(page)) * 72; - vDPI = ((win->getHeight() - 56) / doc->getPageWidth(page)) * 72; + hDPI = (win->getWidth() / doc->getPageHeight(page)) * 72; + vDPI = (win->getHeight() / doc->getPageWidth(page)) * 72; } else { - hDPI = ((win->getWidth() - 28) / doc->getPageWidth(page)) * 72; - vDPI = ((win->getHeight() - 56) / doc->getPageHeight(page)) * 72; + hDPI = (win->getWidth() / doc->getPageWidth(page)) * 72; + vDPI = (win->getHeight() / doc->getPageHeight(page)) * 72; + } + dpi = (hDPI < vDPI) ? hDPI : vDPI; + } else if (zoom == zoomPage) { + if (rot == 90 || rot == 270) { + hDPI = (canvas->getWidth() / doc->getPageHeight(page)) * 72; + vDPI = (canvas->getHeight() / doc->getPageWidth(page)) * 72; + } else { + hDPI = (canvas->getWidth() / doc->getPageWidth(page)) * 72; + vDPI = (canvas->getHeight() / doc->getPageHeight(page)) * 72; } dpi = (hDPI < vDPI) ? hDPI : vDPI; } else if (zoom == zoomWidth) { if (rot == 90 || rot == 270) { - dpi = ((win->getWidth() - 28) / doc->getPageHeight(page)) * 72; + dpi = (canvas->getWidth() / doc->getPageHeight(page)) * 72; } else { - dpi = ((win->getWidth() - 28) / doc->getPageWidth(page)) * 72; + dpi = (canvas->getWidth() / doc->getPageWidth(page)) * 72; } } else { dpi = zoomDPI[zoom - minZoom]; } - doc->displayPage(out, page, (double)dpi, rotate, gTrue); + doc->displayPage(out, page, dpi, rotate, gTrue); updateScrollbars(); // update page number display - sprintf(s, "%d", page); - pageNumText->setText(s); + if (!fullScreen) { + sprintf(s, "%d", page); + pageNumText->setText(s); + } // add to history if (addToHist) { @@ -804,6 +1040,75 @@ static void displayPage(int page1, int zoom1, int rotate1, GBool addToHist) { win->setBusyCursor(gFalse); } +static void displayDest(LinkDest *dest, int zoomA, int rotateA, + GBool addToHist) { + Ref pageRef; + int pg; + int dx, dy; + + if (dest->isPageRef()) { + pageRef = dest->getPageRef(); + pg = doc->findPage(pageRef.num, pageRef.gen); + } else { + pg = dest->getPageNum(); + } + if (pg <= 0 || pg > doc->getNumPages()) { + pg = 1; + } + if (pg != page) { + displayPage(pg, zoomA, rotateA, addToHist); + } + + if (fullScreen) { + return; + } + switch (dest->getKind()) { + case destXYZ: + out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy); + if (dest->getChangeLeft() || dest->getChangeTop()) { + if (dest->getChangeLeft()) { + hScrollbar->setPos(dx, canvas->getWidth()); + } + if (dest->getChangeTop()) { + vScrollbar->setPos(dy, canvas->getHeight()); + } + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + } + //~ what is the zoom parameter? + break; + case destFit: + case destFitB: + //~ do fit + hScrollbar->setPos(0, canvas->getWidth()); + vScrollbar->setPos(0, canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + break; + case destFitH: + case destFitBH: + //~ do fit + out->cvtUserToDev(0, dest->getTop(), &dx, &dy); + hScrollbar->setPos(0, canvas->getWidth()); + vScrollbar->setPos(dy, canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + break; + case destFitV: + case destFitBV: + //~ do fit + out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy); + hScrollbar->setPos(dx, canvas->getWidth()); + vScrollbar->setPos(0, canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + break; + case destFitR: + //~ do fit + out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy); + hScrollbar->setPos(dx, canvas->getWidth()); + vScrollbar->setPos(dy, canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + break; + } +} + //------------------------------------------------------------------------ // key press and menu callbacks //------------------------------------------------------------------------ @@ -816,22 +1121,27 @@ static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers, case 'o': mapOpenDialog(); break; + case 'R': + case 'r': + reloadCbk(); + break; case 'F': case 'f': mapFindWin(); break; case 'N': case 'n': - nextPageCbk(NULL, 0, gTrue); + gotoNextPage(1, !(modifiers & Mod5Mask)); break; case 'P': case 'p': - prevPageCbk(NULL, 0, gTrue); + gotoPrevPage(1, !(modifiers & Mod5Mask), gFalse); break; case ' ': - if (vScrollbar->getPos() >= - canvas->getRealHeight() - canvas->getHeight()) { - nextPageCbk(NULL, 0, gTrue); + if (fullScreen || + vScrollbar->getPos() >= + canvas->getRealHeight() - canvas->getHeight()) { + gotoNextPage(1, gTrue); } else { vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(), canvas->getHeight()); @@ -840,41 +1150,101 @@ static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers, break; case '\b': // bs case '\177': // del - if (vScrollbar->getPos() == 0) { - prevPageCbk(NULL, 0, gTrue); - vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(), - canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + if (fullScreen) { + gotoPrevPage(1, gTrue, gFalse); + } else if (vScrollbar->getPos() == 0) { + gotoPrevPage(1, gFalse, gTrue); } else { vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(), canvas->getHeight()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); } break; + case 'v': + forwardCbk(NULL, 0, gTrue); + break; + case 'b': + backCbk(NULL, 0, gTrue); + break; + case 'g': + if (fullScreen) { + break; + } + pageNumText->selectAll(); + pageNumText->activate(gTrue); + break; case 'h': // vi-style left + if (fullScreen) { + break; + } if (viKeys) { hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); } break; case 'l': // vi-style right + if (fullScreen) { + break; + } if (viKeys) { hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); } break; case 'k': // vi-style up + if (fullScreen) { + break; + } if (viKeys) { vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); } break; case 'j': // vi-style down + if (fullScreen) { + break; + } if (viKeys) { vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); } break; + case '0': + if (fullScreen) { + break; + } + if (zoom != defZoom) { + zoomMenuBtn->setMenuItem(zoomMenu->getItem(defZoom - minZoom)); + } + break; + case '+': + if (fullScreen) { + break; + } + if (zoom >= minZoom && zoom < maxZoom) { + zoomMenuBtn->setMenuItem(zoomMenu->getItem(zoom + 1 - minZoom)); + } + break; + case '-': + if (fullScreen) { + break; + } + if (zoom > minZoom && zoom <= maxZoom) { + zoomMenuBtn->setMenuItem(zoomMenu->getItem(zoom - 1 - minZoom)); + } + break; + case 'z': + if (fullScreen) { + break; + } + zoomMenuBtn->setMenuItem(zoomMenu->getItem(maxZoom - minZoom + 2)); + break; + case 'w': + if (fullScreen) { + break; + } + zoomMenuBtn->setMenuItem(zoomMenu->getItem(maxZoom - minZoom + 3)); + break; case '\014': // ^L win->redraw(); displayPage(page, zoom, rotate, gFalse); @@ -888,12 +1258,18 @@ static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers, switch (key) { case XK_Home: case XK_KP_Home: + if (fullScreen) { + break; + } hScrollbar->setPos(0, canvas->getWidth()); vScrollbar->setPos(0, canvas->getHeight()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); break; case XK_End: case XK_KP_End: + if (fullScreen) { + break; + } hScrollbar->setPos(canvas->getRealWidth() - canvas->getWidth(), canvas->getWidth()); vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(), @@ -902,11 +1278,10 @@ static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers, break; case XK_Page_Up: case XK_KP_Page_Up: - if (vScrollbar->getPos() == 0) { - prevPageCbk(NULL, 0, gTrue); - vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(), - canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + if (fullScreen) { + gotoPrevPage(1, gTrue, gFalse); + } else if (vScrollbar->getPos() == 0) { + gotoPrevPage(1, gFalse, gTrue); } else { vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(), canvas->getHeight()); @@ -915,9 +1290,10 @@ static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers, break; case XK_Page_Down: case XK_KP_Page_Down: - if (vScrollbar->getPos() >= - canvas->getRealHeight() - canvas->getHeight()) { - nextPageCbk(NULL, 0, gTrue); + if (fullScreen || + vScrollbar->getPos() >= + canvas->getRealHeight() - canvas->getHeight()) { + gotoNextPage(1, gTrue); } else { vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(), canvas->getHeight()); @@ -926,21 +1302,33 @@ static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers, break; case XK_Left: case XK_KP_Left: + if (fullScreen) { + break; + } hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); break; case XK_Right: case XK_KP_Right: + if (fullScreen) { + break; + } hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); break; case XK_Up: case XK_KP_Up: + if (fullScreen) { + break; + } vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); break; case XK_Down: case XK_KP_Down: + if (fullScreen) { + break; + } vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight()); canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); break; @@ -955,17 +1343,20 @@ static void menuCbk(LTKMenuItem *item) { case menuOpen: mapOpenDialog(); break; + case menuReload: + reloadCbk(); + break; case menuSavePDF: if (doc) mapSaveDialog(); break; - case menuRotateLeft: + case menuRotateCCW: if (doc) { r = (rotate == 0) ? 270 : rotate - 90; displayPage(page, zoom, r, gFalse); } break; - case menuRotateRight: + case menuRotateCW: if (doc) { r = (rotate == 270) ? 0 : rotate + 90; displayPage(page, zoom, r, gFalse); @@ -983,13 +1374,53 @@ static void menuCbk(LTKMenuItem *item) { static void buttonPressCbk(LTKWidget *canvas1, int n, int mx, int my, int button, GBool dblClick) { - if (!doc || doc->getNumPages() == 0) + if (!doc || doc->getNumPages() == 0) { return; - if (button == 1) { + } + switch (button) { + case 1: setSelection(mx, my, mx, my); - } else if (button == 2) { - panMX = mx - hScrollbar->getPos(); - panMY = my - vScrollbar->getPos(); + break; + case 2: + if (!fullScreen) { + panMX = mx - hScrollbar->getPos(); + panMY = my - vScrollbar->getPos(); + } + break; + case 4: // mouse wheel up + if (fullScreen) { + gotoPrevPage(1, gTrue, gFalse); + } else if (vScrollbar->getPos() == 0) { + gotoPrevPage(1, gFalse, gTrue); + } else { + vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + } + break; + case 5: // mouse wheel down + if (fullScreen || + vScrollbar->getPos() >= + canvas->getRealHeight() - canvas->getHeight()) { + gotoNextPage(1, gTrue); + } else { + vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + } + break; + case 6: // second mouse wheel right + if (fullScreen) { + return; + } + hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + break; + case 7: // second mouse wheel left + if (fullScreen) { + return; + } + hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + break; } } @@ -1027,11 +1458,10 @@ static void doLink(int mx, int my) { GString *namedDest; char *s; GString *fileName; - Ref pageRef; - int pg; + GString *actionName; double x, y; - int dx, dy; LTKButtonDialog *dialog; + int i; // look for a link out->cvtDevToUser(mx, my, &x, &y); @@ -1074,64 +1504,13 @@ static void doLink(int mx, int my) { dest = doc->findDest(namedDest); delete namedDest; } - if (!dest) { - if (kind == actionGoToR) - displayPage(1, zoom, 0, gTrue); + if (dest) { + displayDest(dest, zoom, rotate, gTrue); + delete dest; } else { - if (dest->isPageRef()) { - pageRef = dest->getPageRef(); - pg = doc->findPage(pageRef.num, pageRef.gen); - } else { - pg = dest->getPageNum(); - } - if (pg > 0 && pg != page) - displayPage(pg, zoom, rotate, gTrue); - else if (pg <= 0) - displayPage(1, zoom, rotate, gTrue); - switch (dest->getKind()) { - case destXYZ: - out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy); - if (dest->getChangeLeft() || dest->getChangeTop()) { - if (dest->getChangeLeft()) - hScrollbar->setPos(dx, canvas->getWidth()); - if (dest->getChangeTop()) - vScrollbar->setPos(dy, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - } - //~ what is the zoom parameter? - break; - case destFit: - case destFitB: - //~ do fit - hScrollbar->setPos(0, canvas->getWidth()); - vScrollbar->setPos(0, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - break; - case destFitH: - case destFitBH: - //~ do fit - out->cvtUserToDev(0, dest->getTop(), &dx, &dy); - hScrollbar->setPos(0, canvas->getWidth()); - vScrollbar->setPos(dy, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - break; - case destFitV: - case destFitBV: - //~ do fit - out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy); - hScrollbar->setPos(dx, canvas->getWidth()); - vScrollbar->setPos(0, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - break; - case destFitR: - //~ do fit - out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy); - hScrollbar->setPos(dx, canvas->getWidth()); - vScrollbar->setPos(dy, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - break; + if (kind == actionGoToR) { + displayPage(1, zoom, 0, gTrue); } - delete dest; } break; @@ -1178,13 +1557,30 @@ static void doLink(int mx, int my) { case actionURI: if (urlCommand) { for (s = urlCommand->getCString(); *s; ++s) { - if (s[0] == '%' && s[1] == 's') + if (s[0] == '%' && s[1] == 's') { break; + } } if (s) { - fileName = new GString(urlCommand->getCString(), - s - urlCommand->getCString()); - fileName->append(((LinkURI *)action)->getURI()); + fileName = ((LinkURI *)action)->getURI()->copy(); + // filter out any quote marks (' or ") to avoid a potential + // security hole + i = 0; + while (i < fileName->getLength()) { + if (fileName->getChar(i) == '"') { + fileName->del(i); + fileName->insert(i, "%22"); + i += 3; + } else if (fileName->getChar(i) == '\'') { + fileName->del(i); + fileName->insert(i, "%27"); + i += 3; + } else { + ++i; + } + } + fileName->insert(0, urlCommand->getCString(), + s - urlCommand->getCString()); fileName->append(s+2); } else { fileName = urlCommand->copy(); @@ -1199,8 +1595,33 @@ static void doLink(int mx, int my) { system(fileName->getCString()); delete fileName; } else { - fprintf(errFile, "URI: %s\n", - ((LinkURI *)action)->getURI()->getCString()); + printf("URI: %s\n", ((LinkURI *)action)->getURI()->getCString()); + } + break; + + // Named action + case actionNamed: + actionName = ((LinkNamed *)action)->getName(); + if (!actionName->cmp("NextPage")) { + gotoNextPage(1, gTrue); + } else if (!actionName->cmp("PrevPage")) { + gotoPrevPage(1, gTrue, gFalse); + } else if (!actionName->cmp("FirstPage")) { + if (page != 1) { + displayPage(1, zoom, rotate, gTrue); + } + } else if (!actionName->cmp("LastPage")) { + if (page != doc->getNumPages()) { + displayPage(doc->getNumPages(), zoom, rotate, gTrue); + } + } else if (!actionName->cmp("GoBack")) { + backCbk(NULL, 0, gTrue); + } else if (!actionName->cmp("GoForward")) { + forwardCbk(NULL, 0, gTrue); + } else if (!actionName->cmp("Quit")) { + quitCbk(NULL, 0, gTrue); + } else { + error(-1, "Unknown named action: '%s'", actionName->getCString()); } break; @@ -1223,34 +1644,42 @@ static void mouseMoveCbk(LTKWidget *widget, int widgetNum, int mx, int my) { out->cvtDevToUser(mx, my, &x, &y); if ((action = doc->findLink(x, y))) { if (action != linkAction) { - if (!linkAction) + if (!linkAction) { win->setCursor(XC_hand2); + } linkAction = action; - s = NULL; - switch (linkAction->getKind()) { - case actionGoTo: - s = "[internal link]"; - break; - case actionGoToR: - s = ((LinkGoToR *)linkAction)->getFileName()->getCString(); - break; - case actionLaunch: - s = ((LinkLaunch *)linkAction)->getFileName()->getCString(); - break; - case actionURI: - s = ((LinkURI *)action)->getURI()->getCString(); - break; - case actionUnknown: - s = "[unknown link]"; - break; + if (!fullScreen) { + s = NULL; + switch (linkAction->getKind()) { + case actionGoTo: + s = "[internal link]"; + break; + case actionGoToR: + s = ((LinkGoToR *)linkAction)->getFileName()->getCString(); + break; + case actionLaunch: + s = ((LinkLaunch *)linkAction)->getFileName()->getCString(); + break; + case actionURI: + s = ((LinkURI *)action)->getURI()->getCString(); + break; + case actionNamed: + s = ((LinkNamed *)linkAction)->getName()->getCString(); + break; + case actionUnknown: + s = "[unknown link]"; + break; + } + linkLabel->setText(s); } - linkLabel->setText(s); } } else { if (linkAction) { linkAction = NULL; win->setDefaultCursor(); - linkLabel->setText(NULL); + if (!fullScreen) { + linkLabel->setText(NULL); + } } } } @@ -1319,7 +1748,7 @@ static void mouseDragCbk(LTKWidget *widget, int widgetNum, setSelection(xMin, yMin, xMax, yMax); // button 2: pan - } else if (button == 2) { + } else if (!fullScreen && button == 2) { mx -= hScrollbar->getPos(); my -= vScrollbar->getPos(); hScrollbar->setPos(hScrollbar->getPos() - (mx - panMX), @@ -1337,27 +1766,27 @@ static void mouseDragCbk(LTKWidget *widget, int widgetNum, //------------------------------------------------------------------------ static void nextPageCbk(LTKWidget *button, int n, GBool on) { - if (!doc || doc->getNumPages() == 0) - return; - if (page < doc->getNumPages()) { - vScrollbar->setPos(0, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - displayPage(page + 1, zoom, rotate, gTrue); - } else { - XBell(display, 0); - } + gotoNextPage(1, gTrue); } static void nextTenPageCbk(LTKWidget *button, int n, GBool on) { + gotoNextPage(10, gTrue); +} + +static void gotoNextPage(int inc, GBool top) { int pg; - if (!doc || doc->getNumPages() == 0) + if (!doc || doc->getNumPages() == 0) { return; + } if (page < doc->getNumPages()) { - vScrollbar->setPos(0, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - if ((pg = page + 10) > doc->getNumPages()) + if (top && !fullScreen) { + vScrollbar->setPos(0, canvas->getHeight()); + canvas->setScrollPos(hScrollbar->getPos(), vScrollbar->getPos()); + } + if ((pg = page + inc) > doc->getNumPages()) { pg = doc->getNumPages(); + } displayPage(pg, zoom, rotate, gTrue); } else { XBell(display, 0); @@ -1365,27 +1794,31 @@ static void nextTenPageCbk(LTKWidget *button, int n, GBool on) { } static void prevPageCbk(LTKWidget *button, int n, GBool on) { - if (!doc || doc->getNumPages() == 0) - return; - if (page > 1) { - vScrollbar->setPos(0, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - displayPage(page - 1, zoom, rotate, gTrue); - } else { - XBell(display, 0); - } + gotoPrevPage(1, gTrue, gFalse); } static void prevTenPageCbk(LTKWidget *button, int n, GBool on) { + gotoPrevPage(10, gTrue, gFalse); +} + +static void gotoPrevPage(int dec, GBool top, GBool bottom) { int pg; - if (!doc || doc->getNumPages() == 0) + if (!doc || doc->getNumPages() == 0) { return; + } if (page > 1) { - vScrollbar->setPos(0, canvas->getHeight()); - canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); - if ((pg = page - 10) < 1) + if (top && !fullScreen) { + vScrollbar->setPos(0, canvas->getHeight()); + canvas->setScrollPos(hScrollbar->getPos(), vScrollbar->getPos()); + } else if (bottom && !fullScreen) { + vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(), + canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + } + if ((pg = page - dec) < 1) { pg = 1; + } displayPage(pg, zoom, rotate, gTrue); } else { XBell(display, 0); @@ -1498,6 +1931,9 @@ static void layoutCbk(LTKWindow *win1) { } static void updateScrollbars() { + if (fullScreen) { + return; + } hScrollbar->setLimits(0, canvas->getRealWidth() - 1); hScrollbar->setPos(hScrollbar->getPos(), canvas->getWidth()); hScrollbar->setScrollDelta(16); @@ -1513,19 +1949,23 @@ static void propChangeCbk(LTKWindow *win1, Atom atom) { Atom type; int format; Gulong size, remain; - char *p; + char *p, *q; GString *newFileName; int newPage; + GString *destName; + LinkDest *dest; // get command xwin = win1->getXWindow(); if (XGetWindowProperty(display, xwin, remoteAtom, 0, remoteCmdLength/4, True, remoteAtom, &type, &format, &size, &remain, - (Guchar **)&cmd) != Success) + (Guchar **)&cmd) != Success) { return; - if (size == 0) + } + if (size == 0) { return; + } // raise window if (cmd[0] == 'D' || cmd[0] == 'r'){ @@ -1536,10 +1976,22 @@ static void propChangeCbk(LTKWindow *win1, Atom atom) { // display file / page if (cmd[0] == 'd' || cmd[0] == 'D') { p = cmd + 2; - newPage = atoi(p); - if (!(p = strchr(p, ' '))) + q = strchr(p, ' '); + if (!q) { + return; + } + *q++ = '\0'; + newPage = 1; + destName = NULL; + if (*p == '+') { + destName = new GString(p + 1); + } else { + newPage = atoi(p); + } + if (!q) { return; - newFileName = new GString(p + 1); + } + newFileName = new GString(q); XFree((XPointer)cmd); if (!doc || newFileName->cmp(doc->getFileName())) { if (!loadFile(newFileName)) @@ -1547,8 +1999,16 @@ static void propChangeCbk(LTKWindow *win1, Atom atom) { } else { delete newFileName; } - if (newPage != page && newPage >= 1 && newPage <= doc->getNumPages()) + if (destName) { + if ((dest = doc->findDest(destName))) { + displayDest(dest, zoom, rotate, gTrue); + delete dest; + } + delete destName; + } else if (newPage != page && + newPage >= 1 && newPage <= doc->getNumPages()) { displayPage(newPage, zoom, rotate, gTrue); + } // quit } else if (cmd[0] == 'q') { @@ -1623,6 +2083,9 @@ static void setSelection(int newXMin, int newYMin, int newXMax, int newYMax) { selectYMax = newYMax; // scroll canvas if necessary + if (fullScreen) { + return; + } needScroll = gFalse; w = canvas->getWidth(); h = canvas->getHeight(); @@ -1679,10 +2142,10 @@ static void openButtonCbk(LTKWidget *button, int n, GBool on) { sel = NULL; if (n == 1) { fileReq = (LTKFileReq *)openDialog->findWidget("fileReq"); - if ((sel = fileReq->getSelection())) - openSelectCbk(fileReq, 0, sel); - else - XBell(display, 0); + if (!(sel = fileReq->getSelection())) { + return; + } + openSelectCbk(fileReq, 0, sel); } if (openDialog) { if (sel) { @@ -1704,8 +2167,32 @@ static void openSelectCbk(LTKWidget *widget, int n, GString *name) { delete openDialog; openDialog = NULL; } - if (loadFile(name1)) + if (loadFile(name1)) { + if (!fullScreen) { + vScrollbar->setPos(0, canvas->getHeight()); + canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos()); + } displayPage(1, zoom, rotate, gTrue); + } +} + +//------------------------------------------------------------------------ +// "Reload" +//------------------------------------------------------------------------ + +static void reloadCbk() { + int pg; + + if (!doc) { + return; + } + pg = page; + if (loadFile(doc->getFileName()->copy())) { + if (pg > doc->getNumPages()) { + pg = doc->getNumPages(); + } + displayPage(pg, zoom, rotate, gFalse); + } } //------------------------------------------------------------------------ @@ -1728,10 +2215,10 @@ static void saveButtonCbk(LTKWidget *button, int n, GBool on) { sel = NULL; if (n == 1) { fileReq = (LTKFileReq *)saveDialog->findWidget("fileReq"); - if ((sel = fileReq->getSelection())) - saveSelectCbk(fileReq, 0, sel); - else - XBell(display, 0); + if (!(sel = fileReq->getSelection())) { + return; + } + saveSelectCbk(fileReq, 0, sel); } if (saveDialog) { if (sel) { @@ -1812,10 +2299,11 @@ static void psButtonCbk(LTKWidget *button, int n, GBool on) { psDialog->setBusyCursor(gTrue); win->setBusyCursor(gTrue); if (doc->okToPrint()) { - psOut = new PSOutputDev(psFileName->getCString(), doc->getCatalog(), - psFirstPage, psLastPage, gTrue, gFalse); + psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(), + doc->getCatalog(), psFirstPage, psLastPage, + psModePS); if (psOut->isOk()) { - doc->displayPages(psOut, psFirstPage, psLastPage, 72, 0); + doc->displayPages(psOut, psFirstPage, psLastPage, 72, 0, gFalse); } delete psOut; } else { @@ -1836,10 +2324,19 @@ static void psButtonCbk(LTKWidget *button, int n, GBool on) { //------------------------------------------------------------------------ static void mapAboutWin() { + int i; + if (aboutWin) { aboutWin->raise(); } else { aboutWin = makeAboutWindow(app); + aboutWin->setLayoutCbk(&aboutLayoutCbk); + aboutList = (LTKList *)aboutWin->findWidget("list"); + aboutHScrollbar = (LTKScrollbar *)aboutWin->findWidget("hScrollbar"); + aboutVScrollbar = (LTKScrollbar *)aboutWin->findWidget("vScrollbar"); + for (i = 0; aboutWinText[i]; ++i) { + aboutList->addLine(aboutWinText[i]); + } aboutWin->layout(-1, -1, -1, -1); aboutWin->map(); } @@ -1850,6 +2347,24 @@ static void closeAboutCbk(LTKWidget *button, int n, GBool on) { aboutWin = NULL; } +static void aboutLayoutCbk(LTKWindow *winA) { + aboutHScrollbar->setLimits(0, aboutList->getMaxWidth() - 1); + aboutHScrollbar->setPos(aboutHScrollbar->getPos(), aboutList->getWidth()); + aboutVScrollbar->setLimits(0, aboutList->getNumLines() - 1); + aboutVScrollbar->setPos(aboutVScrollbar->getPos(), + aboutList->getDisplayedLines()); +} + +static void aboutScrollVertCbk(LTKWidget *scrollbar, int n, int val) { + aboutList->scrollTo(val, aboutHScrollbar->getPos()); + XSync(display, False); +} + +static void aboutScrollHorizCbk(LTKWidget *scrollbar, int n, int val) { + aboutList->scrollTo(aboutVScrollbar->getPos(), val); + XSync(display, False); +} + //------------------------------------------------------------------------ // "Find" window //------------------------------------------------------------------------ @@ -1867,17 +2382,16 @@ static void mapFindWin() { findWin = makeFindWindow(app); findWin->layout(-1, -1, -1, -1); findWin->map(); + findTextIn = (LTKTextIn *)findWin->findWidget("text"); } + findTextIn->activate(gTrue); } static void findButtonCbk(LTKWidget *button, int n, GBool on) { - LTKTextIn *textIn; - if (!doc || doc->getNumPages() == 0) return; if (n == 1) { - textIn = (LTKTextIn *)findWin->findWidget("text"); - doFind(textIn->getText()->getCString()); + doFind(findTextIn->getText()->getCString()); } else { delete findWin; findWin = NULL; @@ -1885,12 +2399,14 @@ static void findButtonCbk(LTKWidget *button, int n, GBool on) { } static void doFind(char *s) { + Unicode *u; TextOutputDev *textOut; int xMin, yMin, xMax, yMax; double xMin1, yMin1, xMax1, yMax1; int pg; GBool top; GString *s1; + int len, i; // check for zero-length string if (!s[0]) { @@ -1902,6 +2418,15 @@ static void doFind(char *s) { win->setBusyCursor(gTrue); findWin->setBusyCursor(gTrue); + // convert to Unicode +#if 1 //~ should do something more intelligent here + len = strlen(s); + u = (Unicode *)gmalloc(len * sizeof(Unicode)); + for (i = 0; i < len; ++i) { + u[i] = (Unicode)(s[i] & 0xff); + } +#endif + // search current page starting at current selection or top of page xMin = yMin = xMax = yMax = 0; if (selectXMin < selectXMax && selectYMin < selectYMax) { @@ -1911,26 +2436,31 @@ static void doFind(char *s) { } else { top = gTrue; } - if (out->findText(s, top, gTrue, &xMin, &yMin, &xMax, &yMax)) + if (out->findText(u, len, top, gTrue, &xMin, &yMin, &xMax, &yMax)) { goto found; + } // search following pages - textOut = new TextOutputDev(NULL, useEUCJP, gFalse); + textOut = new TextOutputDev(NULL, gFalse, gFalse); if (!textOut->isOk()) { delete textOut; goto done; } for (pg = page+1; pg <= doc->getNumPages(); ++pg) { doc->displayPage(textOut, pg, 72, 0, gFalse); - if (textOut->findText(s, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1)) + if (textOut->findText(u, len, gTrue, gTrue, + &xMin1, &yMin1, &xMax1, &yMax1)) { goto foundPage; + } } // search previous pages for (pg = 1; pg < page; ++pg) { doc->displayPage(textOut, pg, 72, 0, gFalse); - if (textOut->findText(s, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1)) + if (textOut->findText(u, len, gTrue, gTrue, + &xMin1, &yMin1, &xMax1, &yMax1)) { goto foundPage; + } } delete textOut; @@ -1938,8 +2468,9 @@ static void doFind(char *s) { if (selectXMin < selectXMax && selectYMin < selectYMax) { xMax = selectXMin; yMax = (selectYMin + selectYMax) / 2; - if (out->findText(s, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) + if (out->findText(u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) { goto found; + } } // not found @@ -1950,8 +2481,10 @@ static void doFind(char *s) { foundPage: delete textOut; displayPage(pg, zoom, rotate, gTrue); - if (!out->findText(s, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) - goto done; // this can happen if coalescing is bad + if (!out->findText(u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) { + // this can happen if coalescing is bad + goto done; + } // found: change the selection found: @@ -1964,6 +2497,8 @@ static void doFind(char *s) { #endif done: + gfree(u); + // reset cursors to normal win->setBusyCursor(gFalse); findWin->setBusyCursor(gFalse);