//
// xpdf.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
+#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
+#include <time.h>
#include <X11/X.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include "parseargs.h"
#include "gfile.h"
#include "gmem.h"
+#include "GlobalParams.h"
#include "LTKAll.h"
#include "Object.h"
#include "Stream.h"
#include "LTKOutputDev.h"
#include "PSOutputDev.h"
#include "TextOutputDev.h"
-#include "Params.h"
#include "Error.h"
#include "config.h"
#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
};
// loadFile / displayPage
static GBool loadFile(GString *fileName);
-static void displayPage(int page1, int zoom1, int rotate1);
+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,
// 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);
-static void zoomInCbk(LTKWidget *button, int n, GBool on);
-static void zoomOutCbk(LTKWidget *button, int n, GBool on);
+static void zoomMenuCbk(LTKMenuItem *item);
static void postScriptCbk(LTKWidget *button, int n, GBool on);
static void aboutCbk(LTKWidget *button, int n, GBool on);
static void quitCbk(LTKWidget *button, int n, GBool on);
// misc callbacks
static void layoutCbk(LTKWindow *win1);
+static void updateScrollbars();
static void propChangeCbk(LTKWindow *win1, Atom atom);
// selection
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);
// "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);
static void killCbk(LTKWindow *win1);
//------------------------------------------------------------------------
-// GUI includes
+// "About" window text
//------------------------------------------------------------------------
-#include "xpdfIcon.xpm"
-#include "leftArrow.xbm"
-#include "dblLeftArrow.xbm"
-#include "rightArrow.xbm"
-#include "dblRightArrow.xbm"
-#include "zoomIn.xbm"
-#include "zoomOut.xbm"
-#include "find.xbm"
-#include "postscript.xbm"
-#include "about.xbm"
-#include "xpdf-ltk.h"
+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 = <PgDn> = next page",
+ " p = <PgUp> = previous page",
+ " <space> = scroll down",
+ " <backspace> = <delete> = 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",
+ " <home> / <end> = top / bottom of page",
+ " <arrows> = scroll",
+ "",
+ "For more information, please read the xpdf(1) man page.",
+ NULL
+};
//------------------------------------------------------------------------
// command line options
//------------------------------------------------------------------------
-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},
- {"-z", ".initialZoom", XrmoptionSepArg, NULL},
- {"-ps", ".psFile", XrmoptionSepArg, NULL},
- {"-paperw", ".psPaperWidth", XrmoptionSepArg, NULL},
- {"-paperh", ".psPaperHeight", XrmoptionSepArg, NULL},
- {"-level1", ".psLevel1", XrmoptionNoArg, (XPointer)"false"},
- {NULL}
-};
-
-GBool printCommands = gFalse;
-static GBool printHelp = gFalse;
+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", argIntDummy, NULL, 0,
- "initial zoom level (-5..5)"},
{"-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"},
- {"-ps", argStringDummy, NULL, 0,
- "default PostScript file/command name"},
- {"-paperw", argIntDummy, NULL, 0,
+ {"-z", argString, initialZoomStr, sizeof(initialZoomStr),
+ "initial zoom level (-5..5, page, width)"},
+#if HAVE_T1LIB_H
+ {"-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", 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, &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}
};
//------------------------------------------------------------------------
// zoom factor is 1.2 (similar to DVI magsteps)
-#define minZoom -5
-#define maxZoom 5
+#define minZoom -5
+#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
static PDFDoc *doc;
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
static GBool lastDragTop; // last dragged selection edge was top/bottom
static int panMX, panMY; // last mouse position for pan
-static GString *defPSFileName;
+struct History {
+ GString *fileName;
+ int page;
+};
+#define historySize 50
+static History // page history queue
+ history[historySize];
+static int historyCur; // currently displayed page
+static int historyBLen; // number of valid entries backward from
+ // current entry
+static int historyFLen; // number of valid entries forward from
+ // current entry
+
static GString *psFileName;
static int psFirstPage, psLastPage;
static GString *urlCommand; // command to execute for URI links
+static GString *windowTitle; // window title string
+
static LTKApp *app;
static Display *display;
static LTKWindow *win;
+static LTKMenu *zoomMenu;
static LTKScrollingCanvas *canvas;
static LTKScrollbar *hScrollbar, *vScrollbar;
static LTKTextIn *pageNumText;
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;
+//------------------------------------------------------------------------
+// GUI includes
+//------------------------------------------------------------------------
+
+#include "xpdfIcon.xpm"
+#include "leftArrow.xbm"
+#include "dblLeftArrow.xbm"
+#include "rightArrow.xbm"
+#include "dblRightArrow.xbm"
+#include "backArrow.xbm"
+#include "forwardArrow.xbm"
+#include "find.xbm"
+#include "postscript.xbm"
+#include "about.xbm"
+#include "xpdf-ltk.h"
+
//------------------------------------------------------------------------
// main program
//------------------------------------------------------------------------
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;
+ double width1, height1;
GBool ok;
char s[20];
+ int i;
int ret;
// initialize
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();
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", "[<PDF-file> [<page>]]", argDesc);
+ if (!printVersion) {
+ printUsage("xpdf", "[<PDF-file> [<page> | +<dest>]]", 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]) {
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;
}
goto done2;
}
- if (doRemoteQuit)
+ if (doRemoteQuit) {
+ if (destName) {
+ delete destName;
+ }
goto done2;
+ }
}
- // print banner
- fprintf(errFile, "xpdf version %s\n", xpdfVersion);
- fprintf(errFile, "%s\n", xpdfCopyright);
+ // no history yet
+ historyCur = historySize - 1;
+ historyBLen = historyFLen = 0;
+ for (i = 0; i < historySize; ++i)
+ history[i].fileName = NULL;
// open PDF file
- defPSFileName = app->getStringResource("psFile", NULL);
if (name) {
if (!loadFile(name)) {
ret = 1;
}
// check for legal page number
- if (doc && (pg < 1 || pg > doc->getNumPages()))
+ if (doc && (pg < 1 || pg > doc->getNumPages())) {
pg = 1;
+ }
// create window
- win = makeWindow(app);
menu = makeMenu();
+ 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");
pageNumText = (LTKTextIn *)win->findWidget("pageNum");
numPagesLabel = (LTKLabel *)win->findWidget("numPages");
linkLabel = (LTKLabel *)win->findWidget("link");
+ zoomMenuBtn = (LTKMenuButton *)win->findWidget("zoom");
win->setKeyCbk(&keyPressCbk);
win->setLayoutCbk(&layoutCbk);
canvas->setButtonPressCbk(&buttonPressCbk);
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);
- zoom = app->getIntResource("initialZoom", defZoom);
- if (zoom < minZoom)
- zoom = minZoom;
- else if (zoom > maxZoom)
- zoom = maxZoom;
+ 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;
+ } else {
+ 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 = -1;
- y = -1;
- if (!doc) {
- 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);
+ if (fullScreen) {
+ x = y = 0;
+ width = app->getDisplayWidth();
+ height = app->getDisplayHeight();
} else {
- width = (int)(doc->getPageWidth(pg) + 0.5);
- height = (int)(doc->getPageHeight(pg) + 0.5);
+ 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;
+ }
+ }
}
- width = (width * zoomDPI[zoom - minZoom]) / 72 + 28;
- if (width > (Guint)app->getDisplayWidth() - 100)
- width = app->getDisplayWidth() - 100;
- height = (height * zoomDPI[zoom - minZoom]) / 72 + 56;
- if (height > (Guint)app->getDisplayHeight() - 100)
- height = app->getDisplayHeight() - 100;
- app->getGeometryResource("geometry", &x, &y, &width, &height);
// 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 {
}
// create output device
- out = new LTKOutputDev(win, paperColor);
+ out = new LTKOutputDev(win, reverseVideo, paperColor,
+ installCmap, rgbCubeSize, !fullScreen);
+ out->startDoc(doc ? doc->getXRef() : (XRef *)NULL);
// display first page
- displayPage(pg, zoom, 0);
+ 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;
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;
- freeParams();
+ }
+ if (windowTitle) {
+ delete windowTitle;
+ }
+ for (i = 0; i < historySize; ++i) {
+ if (history[i].fileName) {
+ delete history[i].fileName;
+ }
+ }
+ delete globalParams;
// check for memory leaks
- Object::memCheck(errFile);
- gMemReport(errFile);
+ 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;
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)
if (doc)
delete doc;
doc = newDoc;
+ 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"))
// 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);
}
return gTrue;
}
-static void displayPage(int page1, int zoom1, int rotate1) {
+static void displayPage(int pageA, int zoomA, int rotateA, GBool addToHist) {
+ time_t modTime1;
+ double hDPI, vDPI, dpi;
+ int rot;
char s[20];
+ History *h;
// check for document
- if (!doc)
+ 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;
// draw the page
- doc->displayPage(out, page, zoomDPI[zoom - minZoom], rotate, gTrue);
- layoutCbk(win);
+ rot = rotate + doc->getPageRotate(page);
+ if (rot >= 360)
+ rot -= 360;
+ else if (rotate < 0)
+ rot += 360;
+ if (fullScreen) {
+ if (rot == 90 || rot == 270) {
+ hDPI = (win->getWidth() / doc->getPageHeight(page)) * 72;
+ vDPI = (win->getHeight() / doc->getPageWidth(page)) * 72;
+ } else {
+ 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 = (canvas->getWidth() / doc->getPageHeight(page)) * 72;
+ } else {
+ dpi = (canvas->getWidth() / doc->getPageWidth(page)) * 72;
+ }
+ } else {
+ dpi = zoomDPI[zoom - minZoom];
+ }
+ 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) {
+ if (++historyCur == historySize)
+ historyCur = 0;
+ h = &history[historyCur];
+ if (h->fileName)
+ delete h->fileName;
+ h->fileName = doc->getFileName()->copy();
+ h->page = page;
+ if (historyBLen < historySize)
+ ++historyBLen;
+ historyFLen = 0;
+ }
// back to regular cursor
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
//------------------------------------------------------------------------
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());
break;
case '\b': // bs
case '\177': // del
- if (vScrollbar->getPos() == 0) {
- prevPageCbk(NULL, 0, gTrue);
+ 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);
+ displayPage(page, zoom, rotate, gFalse);
break;
case 'Q':
case 'q':
} else {
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(),
canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
break;
case XK_Page_Up:
- if (vScrollbar->getPos() == 0) {
- prevPageCbk(NULL, 0, gTrue);
+ case XK_KP_Page_Up:
+ if (fullScreen) {
+ gotoPrevPage(1, gTrue, gFalse);
+ } else if (vScrollbar->getPos() == 0) {
+ gotoPrevPage(1, gFalse, gTrue);
} else {
vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(),
canvas->getHeight());
}
break;
case XK_Page_Down:
- if (vScrollbar->getPos() >=
- canvas->getRealHeight() - canvas->getHeight()) {
- nextPageCbk(NULL, 0, gTrue);
+ case XK_KP_Page_Down:
+ if (fullScreen ||
+ vScrollbar->getPos() >=
+ canvas->getRealHeight() - canvas->getHeight()) {
+ gotoNextPage(1, gTrue);
} else {
vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(),
canvas->getHeight());
}
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;
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);
+ displayPage(page, zoom, r, gFalse);
}
break;
- case menuRotateRight:
+ case menuRotateCW:
if (doc) {
r = (rotate == 270) ? 0 : rotate + 90;
- displayPage(page, zoom, r);
+ displayPage(page, zoom, r, gFalse);
}
break;
case menuQuit:
static void buttonPressCbk(LTKWidget *canvas1, int n,
int mx, int my, int button, GBool dblClick) {
- if (!doc)
+ 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;
}
}
int mx, int my, int button, GBool click) {
GString *s;
- if (!doc)
+ if (!doc || doc->getNumPages() == 0)
return;
if (button == 1) {
if (doc->okToCopy()) {
s = out->getText(selectXMin, selectYMin, selectXMax, selectYMax);
win->setSelection(NULL, s);
+ } else {
+ error(-1, "Copying of text from this document is not allowed.");
}
#endif
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);
dest = doc->findDest(namedDest);
delete namedDest;
}
- if (!dest) {
- if (kind == actionGoToR)
- displayPage(1, zoom, 0);
+ 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 (kind == actionGoToR) {
+ displayPage(1, zoom, 0, gTrue);
}
- if (pg > 0 && pg != page)
- displayPage(pg, zoom, rotate);
- else if (pg <= 0)
- displayPage(1, zoom, rotate);
- 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;
- }
- delete dest;
}
break;
grabPath(doc->getFileName()->getCString()), s);
if (!loadFile(fileName))
return;
- displayPage(1, zoom, rotate);
+ displayPage(1, zoom, rotate, gTrue);
} else {
fileName = fileName->copy();
if (((LinkLaunch *)action)->getParams()) {
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();
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;
LinkAction *action;
char *s;
- if (!doc)
+ if (!doc || doc->getNumPages() == 0)
return;
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);
+ }
}
}
}
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),
//------------------------------------------------------------------------
static void nextPageCbk(LTKWidget *button, int n, GBool on) {
- if (!doc)
- return;
- if (page < doc->getNumPages()) {
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- displayPage(page + 1, zoom, rotate);
- } 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)
+ 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);
+ }
+ displayPage(pg, zoom, rotate, gTrue);
} else {
XBell(display, 0);
}
}
static void prevPageCbk(LTKWidget *button, int n, GBool on) {
- if (!doc)
- return;
- if (page > 1) {
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- displayPage(page - 1, zoom, rotate);
- } 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)
+ 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);
+ }
+ displayPage(pg, zoom, rotate, gTrue);
} else {
XBell(display, 0);
}
}
+static void backCbk(LTKWidget *button, int n, GBool on) {
+ if (historyBLen <= 1) {
+ XBell(display, 0);
+ return;
+ }
+ if (--historyCur < 0)
+ historyCur = historySize - 1;
+ --historyBLen;
+ ++historyFLen;
+ if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
+ if (!loadFile(history[historyCur].fileName->copy())) {
+ XBell(display, 0);
+ return;
+ }
+ }
+ displayPage(history[historyCur].page, zoom, rotate, gFalse);
+}
+
+static void forwardCbk(LTKWidget *button, int n, GBool on) {
+ if (historyFLen == 0) {
+ XBell(display, 0);
+ return;
+ }
+ if (++historyCur == historySize)
+ historyCur = 0;
+ --historyFLen;
+ ++historyBLen;
+ if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
+ if (!loadFile(history[historyCur].fileName->copy())) {
+ XBell(display, 0);
+ return;
+ }
+ }
+ displayPage(history[historyCur].page, zoom, rotate, gFalse);
+}
+
static void pageNumCbk(LTKWidget *textIn, int n, GString *text) {
int page1;
char s[20];
- if (!doc)
+ if (!doc || doc->getNumPages() == 0)
return;
page1 = atoi(text->getCString());
if (page1 >= 1 && page1 <= doc->getNumPages()) {
if (page1 != page)
- displayPage(page1, zoom, rotate);
+ displayPage(page1, zoom, rotate, gTrue);
} else {
XBell(display, 0);
sprintf(s, "%d", page);
}
}
-static void zoomInCbk(LTKWidget *button, int n, GBool on) {
- if (!doc)
- return;
- if (zoom < maxZoom)
- displayPage(page, zoom + 1, rotate);
- else
- XBell(display, 0);
-}
+static void zoomMenuCbk(LTKMenuItem *item) {
+ int z;
-static void zoomOutCbk(LTKWidget *button, int n, GBool on) {
- if (!doc)
+ if (!doc || doc->getNumPages() == 0) {
return;
- if (zoom > minZoom)
- displayPage(page, zoom - 1, rotate);
- else
- XBell(display, 0);
+ }
+ z = item->getItemNum();
+ if (z != zoom) {
+ displayPage(page, z, rotate, gFalse);
+ }
}
static void postScriptCbk(LTKWidget *button, int n, GBool on) {
//------------------------------------------------------------------------
static void layoutCbk(LTKWindow *win1) {
+ if (page >= 0 && (zoom == zoomPage || zoom == zoomWidth)) {
+ displayPage(page, zoom, rotate, gFalse);
+ } else {
+ updateScrollbars();
+ }
+}
+
+static void updateScrollbars() {
+ if (fullScreen) {
+ return;
+ }
hScrollbar->setLimits(0, canvas->getRealWidth() - 1);
hScrollbar->setPos(hScrollbar->getPos(), canvas->getWidth());
hScrollbar->setScrollDelta(16);
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'){
// 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;
- newFileName = new GString(p + 1);
+ }
+ *q++ = '\0';
+ newPage = 1;
+ destName = NULL;
+ if (*p == '+') {
+ destName = new GString(p + 1);
+ } else {
+ newPage = atoi(p);
+ }
+ if (!q) {
+ return;
+ }
+ newFileName = new GString(q);
XFree((XPointer)cmd);
if (!doc || newFileName->cmp(doc->getFileName())) {
if (!loadFile(newFileName))
} else {
delete newFileName;
}
- if (newPage != page && newPage >= 1 && newPage <= doc->getNumPages())
- displayPage(newPage, zoom, rotate);
+ 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') {
selectYMax = newYMax;
// scroll canvas if necessary
+ if (fullScreen) {
+ return;
+ }
needScroll = gFalse;
w = canvas->getWidth();
h = canvas->getHeight();
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) {
delete openDialog;
openDialog = NULL;
}
- if (loadFile(name1))
- displayPage(1, zoom, rotate);
+ 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);
+ }
}
//------------------------------------------------------------------------
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) {
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,
- zoomDPI[zoom - minZoom], rotate);
+ doc->displayPages(psOut, psFirstPage, psLastPage, 72, 0, gFalse);
}
delete psOut;
+ } else {
+ error(-1, "Printing this document is not allowed.");
}
delete psDialog;
//------------------------------------------------------------------------
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();
}
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
//------------------------------------------------------------------------
static void findCbk(LTKWidget *button, int n, GBool on) {
- if (!doc)
+ if (!doc || doc->getNumPages() == 0)
return;
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)
+ 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;
}
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]) {
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) {
} 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, 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;
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
// found on a different page
foundPage:
delete textOut;
- displayPage(pg, zoom, rotate);
- if (!out->findText(s, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax))
- goto done; // this can happen if coalescing is bad
+ displayPage(pg, zoom, rotate, gTrue);
+ 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:
#endif
done:
+ gfree(u);
+
// reset cursors to normal
win->setBusyCursor(gFalse);
findWin->setBusyCursor(gFalse);