00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <aconf.h>
00010
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014
00015 #include "GString.h"
00016 #include "GList.h"
00017 #include "Error.h"
00018 #include "XPDFViewer.h"
00019 #include "XPDFApp.h"
00020 #include "config.h"
00021
00022
00023 #ifdef LESSTIF_VERSION
00024 #undef XtDisplay
00025 #undef XtScreen
00026 #undef XtWindow
00027 #undef XtParent
00028 #undef XtIsRealized
00029 #endif
00030
00031
00032
00033 #define remoteCmdSize 512
00034
00035
00036
00037 static String fallbackResources[] = {
00038 "*XmTextField.fontList: -*-courier-medium-r-normal--12-*-*-*-*-*-iso8859-1",
00039 "*.fontList: -*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
00040 "*XmTextField.translations: #override\\n"
00041 " Ctrl<Key>a:beginning-of-line()\\n"
00042 " Ctrl<Key>b:backward-character()\\n"
00043 " Ctrl<Key>d:delete-next-character()\\n"
00044 " Ctrl<Key>e:end-of-line()\\n"
00045 " Ctrl<Key>f:forward-character()\\n"
00046 " Ctrl<Key>u:beginning-of-line()delete-to-end-of-line()\\n"
00047 " Ctrl<Key>k:delete-to-end-of-line()\\n",
00048 NULL
00049 };
00050
00051 static XrmOptionDescRec xOpts[] = {
00052 {"-display", ".display", XrmoptionSepArg, NULL},
00053 {"-foreground", "*Foreground", XrmoptionSepArg, NULL},
00054 {"-fg", "*Foreground", XrmoptionSepArg, NULL},
00055 {"-background", "*Background", XrmoptionSepArg, NULL},
00056 {"-bg", "*Background", XrmoptionSepArg, NULL},
00057 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
00058 {"-g", ".geometry", XrmoptionSepArg, NULL},
00059 {"-font", "*.fontList", XrmoptionSepArg, NULL},
00060 {"-fn", "*.fontList", XrmoptionSepArg, NULL},
00061 {"-title", ".title", XrmoptionSepArg, NULL},
00062 {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"},
00063 {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL},
00064 {"-rv", ".reverseVideo", XrmoptionNoArg, (XPointer)"true"},
00065 {"-papercolor", ".paperColor", XrmoptionSepArg, NULL},
00066 {"-z", ".initialZoom", XrmoptionSepArg, NULL}
00067 };
00068
00069 #define nXOpts (sizeof(xOpts) / sizeof(XrmOptionDescRec))
00070
00071 struct XPDFAppResources {
00072 String geometry;
00073 String title;
00074 Bool installCmap;
00075 int rgbCubeSize;
00076 Bool reverseVideo;
00077 String paperColor;
00078 String initialZoom;
00079 Bool viKeys;
00080 };
00081
00082 static Bool defInstallCmap = False;
00083 static int defRGBCubeSize = defaultRGBCube;
00084 static Bool defReverseVideo = False;
00085 static Bool defViKeys = False;
00086
00087 static XtResource xResources[] = {
00088 { "geometry", "Geometry", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, geometry), XtRString, (XtPointer)NULL },
00089 { "title", "Title", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, title), XtRString, (XtPointer)NULL },
00090 { "installCmap", "InstallCmap", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, installCmap), XtRBool, (XtPointer)&defInstallCmap },
00091 { "rgbCubeSize", "RgbCubeSize", XtRInt, sizeof(int), XtOffsetOf(XPDFAppResources, rgbCubeSize), XtRInt, (XtPointer)&defRGBCubeSize },
00092 { "reverseVideo", "ReverseVideo", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, reverseVideo), XtRBool, (XtPointer)&defReverseVideo },
00093 { "paperColor", "PaperColor", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, paperColor), XtRString, (XtPointer)NULL },
00094 { "initialZoom", "InitialZoom", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, initialZoom), XtRString, (XtPointer)NULL },
00095 { "viKeys", "ViKeys", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, viKeys), XtRBool, (XtPointer)&defViKeys }
00096 };
00097
00098 #define nXResources (sizeof(xResources) / sizeof(XtResource))
00099
00100
00101
00102
00103
00104 #if 0 //~ for debugging
00105 static int xErrorHandler(Display *display, XErrorEvent *ev) {
00106 printf("X error:\n");
00107 printf(" resource ID = %08lx\n", ev->resourceid);
00108 printf(" serial = %lu\n", ev->serial);
00109 printf(" error_code = %d\n", ev->error_code);
00110 printf(" request_code = %d\n", ev->request_code);
00111 printf(" minor_code = %d\n", ev->minor_code);
00112 fflush(stdout);
00113 abort();
00114 }
00115 #endif
00116
00117 XPDFApp::XPDFApp(int *argc, char *argv[]) {
00118 appShell = XtAppInitialize(&appContext, xpdfAppName, xOpts, nXOpts,
00119 argc, argv, fallbackResources, NULL, 0);
00120 display = XtDisplay(appShell);
00121 screenNum = XScreenNumberOfScreen(XtScreen(appShell));
00122 #if XmVERSION > 1
00123 XtVaSetValues(XmGetXmDisplay(XtDisplay(appShell)),
00124 XmNenableButtonTab, True, NULL);
00125 #endif
00126 #if XmVERSION > 1
00127
00128
00129
00130 XtVaSetValues(XmGetXmDisplay(XtDisplay(appShell)),
00131 XmNdragInitiatorProtocolStyle, XmDRAG_NONE,
00132 XmNdragReceiverProtocolStyle, XmDRAG_NONE,
00133 NULL);
00134 #endif
00135
00136 #if 0 //~ for debugging
00137 XSynchronize(display, True);
00138 XSetErrorHandler(&xErrorHandler);
00139 #endif
00140
00141 fullScreen = gFalse;
00142 remoteAtom = None;
00143 remoteViewer = NULL;
00144 remoteWin = None;
00145
00146 getResources();
00147
00148 viewers = new GList();
00149
00150 }
00151
00152 void XPDFApp::getResources() {
00153 XPDFAppResources resources;
00154 XColor xcol, xcol2;
00155 Colormap colormap;
00156
00157 XtGetApplicationResources(appShell, &resources, xResources, nXResources,
00158 NULL, 0);
00159 geometry = resources.geometry ? new GString(resources.geometry)
00160 : (GString *)NULL;
00161 title = resources.title ? new GString(resources.title) : (GString *)NULL;
00162 installCmap = (GBool)resources.installCmap;
00163 rgbCubeSize = resources.rgbCubeSize;
00164 reverseVideo = (GBool)resources.reverseVideo;
00165 paperColor = reverseVideo ? BlackPixel(display, screenNum) :
00166 WhitePixel(display, screenNum);
00167 if (resources.paperColor) {
00168 XtVaGetValues(appShell, XmNcolormap, &colormap, NULL);
00169 if (XAllocNamedColor(display, colormap, resources.paperColor,
00170 &xcol, &xcol2)) {
00171 paperColor = xcol.pixel;
00172 } else {
00173 error(-1, "Couldn't allocate color '%s'", resources.paperColor);
00174 }
00175 }
00176 initialZoom = resources.initialZoom ? new GString(resources.initialZoom)
00177 : (GString *)NULL;
00178 viKeys = (GBool)resources.viKeys;
00179 }
00180
00181 XPDFApp::~XPDFApp() {
00182 deleteGList(viewers, XPDFViewer);
00183 if (geometry) {
00184 delete geometry;
00185 }
00186 if (title) {
00187 delete title;
00188 }
00189 if (initialZoom) {
00190 delete initialZoom;
00191 }
00192 }
00193
00194 XPDFViewer *XPDFApp::open(GString *fileName, int page,
00195 GString *ownerPassword, GString *userPassword) {
00196 XPDFViewer *viewer;
00197
00198 viewer = new XPDFViewer(this, fileName, page, NULL,
00199 ownerPassword, userPassword);
00200 if (!viewer->isOk()) {
00201 delete viewer;
00202 return NULL;
00203 }
00204 if (remoteAtom != None) {
00205 remoteViewer = viewer;
00206 remoteWin = viewer->getWindow();
00207 XtAddEventHandler(remoteWin, PropertyChangeMask, False,
00208 &remoteMsgCbk, this);
00209 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime);
00210 }
00211 viewers->append(viewer);
00212 return viewer;
00213 }
00214
00215 XPDFViewer *XPDFApp::openAtDest(GString *fileName, GString *dest,
00216 GString *ownerPassword,
00217 GString *userPassword) {
00218 XPDFViewer *viewer;
00219
00220 viewer = new XPDFViewer(this, fileName, 1, dest,
00221 ownerPassword, userPassword);
00222 if (!viewer->isOk()) {
00223 delete viewer;
00224 return NULL;
00225 }
00226 if (remoteAtom != None) {
00227 remoteViewer = viewer;
00228 remoteWin = viewer->getWindow();
00229 XtAddEventHandler(remoteWin, PropertyChangeMask, False,
00230 &remoteMsgCbk, this);
00231 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime);
00232 }
00233 viewers->append(viewer);
00234 return viewer;
00235 }
00236
00237 void XPDFApp::close(XPDFViewer *viewer, GBool closeLast) {
00238 int i;
00239
00240 if (viewers->getLength() == 1) {
00241 if (viewer != (XPDFViewer *)viewers->get(0)) {
00242 return;
00243 }
00244 if (closeLast) {
00245 quit();
00246 } else {
00247 viewer->clear();
00248 }
00249 } else {
00250 for (i = 0; i < viewers->getLength(); ++i) {
00251 if (((XPDFViewer *)viewers->get(i)) == viewer) {
00252 viewers->del(i);
00253 if (remoteAtom != None && remoteViewer == viewer) {
00254 remoteViewer = (XPDFViewer *)viewers->get(viewers->getLength() - 1);
00255 remoteWin = remoteViewer->getWindow();
00256 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin),
00257 CurrentTime);
00258 }
00259 delete viewer;
00260 return;
00261 }
00262 }
00263 }
00264 }
00265
00266 void XPDFApp::quit() {
00267 if (remoteAtom != None) {
00268 XSetSelectionOwner(display, remoteAtom, None, CurrentTime);
00269 }
00270 while (viewers->getLength() > 0) {
00271 delete (XPDFViewer *)viewers->del(0);
00272 }
00273 XtAppSetExitFlag(appContext);
00274 }
00275
00276 void XPDFApp::run() {
00277 XtAppMainLoop(appContext);
00278 }
00279
00280 void XPDFApp::setRemoteName(char *remoteName) {
00281 remoteAtom = XInternAtom(display, remoteName, False);
00282 remoteXWin = XGetSelectionOwner(display, remoteAtom);
00283 }
00284
00285 GBool XPDFApp::remoteServerRunning() {
00286 return remoteXWin != None;
00287 }
00288
00289 void XPDFApp::remoteOpen(GString *fileName, int page, GBool raise) {
00290 char cmd[remoteCmdSize];
00291
00292 sprintf(cmd, "%c %d %.200s",
00293 raise ? 'D' : 'd', page, fileName->getCString());
00294 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
00295 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
00296 XFlush(display);
00297 }
00298
00299 void XPDFApp::remoteOpenAtDest(GString *fileName, GString *dest, GBool raise) {
00300 char cmd[remoteCmdSize];
00301
00302 sprintf(cmd, "%c +%.256s %.200s",
00303 raise ? 'D' : 'd', dest->getCString(), fileName->getCString());
00304 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
00305 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
00306 XFlush(display);
00307 }
00308
00309 void XPDFApp::remoteRaise() {
00310 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
00311 PropModeReplace, (Guchar *)"r", 2);
00312 XFlush(display);
00313 }
00314
00315 void XPDFApp::remoteQuit() {
00316 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
00317 PropModeReplace, (Guchar *)"q", 2);
00318 XFlush(display);
00319 }
00320
00321 void XPDFApp::remoteMsgCbk(Widget widget, XtPointer ptr,
00322 XEvent *event, Boolean *cont) {
00323 XPDFApp *app = (XPDFApp *)ptr;
00324 char *cmd;
00325 Atom type;
00326 int format;
00327 Gulong size, remain;
00328 char *p, *q;
00329 GString *fileName;
00330 int page;
00331 GString *destName;
00332
00333 if (event->xproperty.atom != app->remoteAtom) {
00334 *cont = True;
00335 return;
00336 }
00337 *cont = False;
00338
00339
00340 if (XGetWindowProperty(app->display, XtWindow(app->remoteWin),
00341 app->remoteAtom, 0, remoteCmdSize/4,
00342 True, app->remoteAtom,
00343 &type, &format, &size, &remain,
00344 (Guchar **)&cmd) != Success) {
00345 return;
00346 }
00347 if (size == 0) {
00348 return;
00349 }
00350
00351
00352 if (cmd[0] == 'D' || cmd[0] == 'r'){
00353 XMapRaised(app->display, XtWindow(app->remoteWin));
00354 XFlush(app->display);
00355 }
00356
00357
00358 if (cmd[0] == 'd' || cmd[0] == 'D') {
00359 p = cmd + 2;
00360 q = strchr(p, ' ');
00361 if (!q) {
00362 return;
00363 }
00364 *q++ = '\0';
00365 page = 1;
00366 destName = NULL;
00367 if (*p == '+') {
00368 destName = new GString(p + 1);
00369 } else {
00370 page = atoi(p);
00371 }
00372 if (q) {
00373 fileName = new GString(q);
00374 app->remoteViewer->open(fileName, page, destName);
00375 delete fileName;
00376 }
00377 XFree((XPointer)cmd);
00378 if (destName) {
00379 delete destName;
00380 }
00381
00382
00383 } else if (cmd[0] == 'q') {
00384 app->quit();
00385 }
00386 }