1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
18 #include "XPDFViewer.h"
20 #include "xpdfconfig.h"
22 // these macro defns conflict with xpdf's Object class
23 #ifdef LESSTIF_VERSION
31 //------------------------------------------------------------------------
33 #define remoteCmdSize 512
35 //------------------------------------------------------------------------
37 static String fallbackResources[] = {
38 "*.zoomComboBox*fontList: -*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
39 "*XmTextField.fontList: -*-courier-medium-r-normal--12-*-*-*-*-*-iso8859-1",
40 "*.fontList: -*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
41 "*XmTextField.translations: #override\\n"
42 " Ctrl<Key>a:beginning-of-line()\\n"
43 " Ctrl<Key>b:backward-character()\\n"
44 " Ctrl<Key>d:delete-next-character()\\n"
45 " Ctrl<Key>e:end-of-line()\\n"
46 " Ctrl<Key>f:forward-character()\\n"
47 " Ctrl<Key>u:beginning-of-line()delete-to-end-of-line()\\n"
48 " Ctrl<Key>k:delete-to-end-of-line()\\n",
52 static XrmOptionDescRec xOpts[] = {
53 {"-display", ".display", XrmoptionSepArg, NULL},
54 {"-foreground", "*Foreground", XrmoptionSepArg, NULL},
55 {"-fg", "*Foreground", XrmoptionSepArg, NULL},
56 {"-background", "*Background", XrmoptionSepArg, NULL},
57 {"-bg", "*Background", XrmoptionSepArg, NULL},
58 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
59 {"-g", ".geometry", XrmoptionSepArg, NULL},
60 {"-font", "*.fontList", XrmoptionSepArg, NULL},
61 {"-fn", "*.fontList", XrmoptionSepArg, NULL},
62 {"-title", ".title", XrmoptionSepArg, NULL},
63 {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"},
64 {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL},
65 {"-rv", ".reverseVideo", XrmoptionNoArg, (XPointer)"true"},
66 {"-papercolor", ".paperColor", XrmoptionSepArg, NULL},
67 {"-z", ".initialZoom", XrmoptionSepArg, NULL}
70 #define nXOpts (sizeof(xOpts) / sizeof(XrmOptionDescRec))
72 struct XPDFAppResources {
83 static Bool defInstallCmap = False;
84 static int defRGBCubeSize = defaultRGBCube;
85 static Bool defReverseVideo = False;
86 static Bool defViKeys = False;
88 static XtResource xResources[] = {
89 { "geometry", "Geometry", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, geometry), XtRString, (XtPointer)NULL },
90 { "title", "Title", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, title), XtRString, (XtPointer)NULL },
91 { "installCmap", "InstallCmap", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, installCmap), XtRBool, (XtPointer)&defInstallCmap },
92 { "rgbCubeSize", "RgbCubeSize", XtRInt, sizeof(int), XtOffsetOf(XPDFAppResources, rgbCubeSize), XtRInt, (XtPointer)&defRGBCubeSize },
93 { "reverseVideo", "ReverseVideo", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, reverseVideo), XtRBool, (XtPointer)&defReverseVideo },
94 { "paperColor", "PaperColor", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, paperColor), XtRString, (XtPointer)NULL },
95 { "initialZoom", "InitialZoom", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, initialZoom), XtRString, (XtPointer)NULL },
96 { "viKeys", "ViKeys", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, viKeys), XtRBool, (XtPointer)&defViKeys }
99 #define nXResources (sizeof(xResources) / sizeof(XtResource))
101 //------------------------------------------------------------------------
103 //------------------------------------------------------------------------
105 #if 0 //~ for debugging
106 static int xErrorHandler(Display *display, XErrorEvent *ev) {
107 printf("X error:\n");
108 printf(" resource ID = %08lx\n", ev->resourceid);
109 printf(" serial = %lu\n", ev->serial);
110 printf(" error_code = %d\n", ev->error_code);
111 printf(" request_code = %d\n", ev->request_code);
112 printf(" minor_code = %d\n", ev->minor_code);
118 XPDFApp::XPDFApp(int *argc, char *argv[]) {
119 appShell = XtAppInitialize(&appContext, xpdfAppName, xOpts, nXOpts,
120 argc, argv, fallbackResources, NULL, 0);
121 display = XtDisplay(appShell);
122 screenNum = XScreenNumberOfScreen(XtScreen(appShell));
124 XtVaSetValues(XmGetXmDisplay(XtDisplay(appShell)),
125 XmNenableButtonTab, True, NULL);
128 // Drag-and-drop appears to be buggy -- I'm seeing weird crashes
129 // deep in the Motif code when I destroy widgets in the XpdfForms
130 // code. Xpdf doesn't use it, so just turn it off.
131 XtVaSetValues(XmGetXmDisplay(XtDisplay(appShell)),
132 XmNdragInitiatorProtocolStyle, XmDRAG_NONE,
133 XmNdragReceiverProtocolStyle, XmDRAG_NONE,
137 #if 0 //~ for debugging
138 XSynchronize(display, True);
139 XSetErrorHandler(&xErrorHandler);
149 viewers = new GList();
153 void XPDFApp::getResources() {
154 XPDFAppResources resources;
158 XtGetApplicationResources(appShell, &resources, xResources, nXResources,
160 geometry = resources.geometry ? new GString(resources.geometry)
162 title = resources.title ? new GString(resources.title) : (GString *)NULL;
163 installCmap = (GBool)resources.installCmap;
164 rgbCubeSize = resources.rgbCubeSize;
165 reverseVideo = (GBool)resources.reverseVideo;
167 paperRGB = splashMakeRGB8(0x00, 0x00, 0x00);
168 paperColor = BlackPixel(display, screenNum);
170 paperRGB = splashMakeRGB8(0xff, 0xff, 0xff);
171 paperColor = WhitePixel(display, screenNum);
173 if (resources.paperColor) {
174 XtVaGetValues(appShell, XmNcolormap, &colormap, NULL);
175 if (XAllocNamedColor(display, colormap, resources.paperColor,
177 paperRGB = splashMakeRGB8(xcol.red >> 8,
180 paperColor = xcol.pixel;
182 error(-1, "Couldn't allocate color '%s'", resources.paperColor);
185 initialZoom = resources.initialZoom ? new GString(resources.initialZoom)
187 viKeys = (GBool)resources.viKeys;
190 XPDFApp::~XPDFApp() {
191 deleteGList(viewers, XPDFViewer);
203 XPDFViewer *XPDFApp::open(GString *fileName, int page,
204 GString *ownerPassword, GString *userPassword) {
207 viewer = new XPDFViewer(this, fileName, page, NULL,
208 ownerPassword, userPassword);
209 if (!viewer->isOk()) {
213 if (remoteAtom != None) {
214 remoteViewer = viewer;
215 remoteWin = viewer->getWindow();
216 XtAddEventHandler(remoteWin, PropertyChangeMask, False,
217 &remoteMsgCbk, this);
218 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime);
220 viewers->append(viewer);
224 XPDFViewer *XPDFApp::openAtDest(GString *fileName, GString *dest,
225 GString *ownerPassword,
226 GString *userPassword) {
229 viewer = new XPDFViewer(this, fileName, 1, dest,
230 ownerPassword, userPassword);
231 if (!viewer->isOk()) {
235 if (remoteAtom != None) {
236 remoteViewer = viewer;
237 remoteWin = viewer->getWindow();
238 XtAddEventHandler(remoteWin, PropertyChangeMask, False,
239 &remoteMsgCbk, this);
240 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime);
242 viewers->append(viewer);
246 void XPDFApp::close(XPDFViewer *viewer, GBool closeLast) {
249 if (viewers->getLength() == 1) {
250 if (viewer != (XPDFViewer *)viewers->get(0)) {
259 for (i = 0; i < viewers->getLength(); ++i) {
260 if (((XPDFViewer *)viewers->get(i)) == viewer) {
262 if (remoteAtom != None && remoteViewer == viewer) {
263 remoteViewer = (XPDFViewer *)viewers->get(viewers->getLength() - 1);
264 remoteWin = remoteViewer->getWindow();
265 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin),
275 void XPDFApp::quit() {
276 if (remoteAtom != None) {
277 XSetSelectionOwner(display, remoteAtom, None, CurrentTime);
279 while (viewers->getLength() > 0) {
280 delete (XPDFViewer *)viewers->del(0);
282 #if HAVE_XTAPPSETEXITFLAG
283 XtAppSetExitFlag(appContext);
289 void XPDFApp::run() {
290 XtAppMainLoop(appContext);
293 void XPDFApp::setRemoteName(char *remoteName) {
294 remoteAtom = XInternAtom(display, remoteName, False);
295 remoteXWin = XGetSelectionOwner(display, remoteAtom);
298 GBool XPDFApp::remoteServerRunning() {
299 return remoteXWin != None;
302 void XPDFApp::remoteOpen(GString *fileName, int page, GBool raise) {
303 char cmd[remoteCmdSize];
305 sprintf(cmd, "%c %d %.200s",
306 raise ? 'D' : 'd', page, fileName->getCString());
307 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
308 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
312 void XPDFApp::remoteOpenAtDest(GString *fileName, GString *dest, GBool raise) {
313 char cmd[remoteCmdSize];
315 sprintf(cmd, "%c +%.256s %.200s",
316 raise ? 'D' : 'd', dest->getCString(), fileName->getCString());
317 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
318 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
322 void XPDFApp::remoteReload(GBool raise) {
323 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
324 PropModeReplace, raise ? (Guchar *)"L" : (Guchar *)"l", 2);
328 void XPDFApp::remoteRaise() {
329 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
330 PropModeReplace, (Guchar *)"r", 2);
334 void XPDFApp::remoteQuit() {
335 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
336 PropModeReplace, (Guchar *)"q", 2);
340 void XPDFApp::remoteMsgCbk(Widget widget, XtPointer ptr,
341 XEvent *event, Boolean *cont) {
342 XPDFApp *app = (XPDFApp *)ptr;
352 if (event->xproperty.atom != app->remoteAtom) {
359 if (XGetWindowProperty(app->display, XtWindow(app->remoteWin),
360 app->remoteAtom, 0, remoteCmdSize/4,
361 True, app->remoteAtom,
362 &type, &format, &size, &remain,
363 (Guchar **)&cmd) != Success) {
370 // display file / page
371 if (cmd[0] == 'd' || cmd[0] == 'D') {
381 destName = new GString(p + 1);
386 fileName = new GString(q);
387 app->remoteViewer->open(fileName, page, destName);
395 } else if (cmd[0] == 'l' || cmd[0] == 'L') {
396 app->remoteViewer->reloadFile();
399 } else if (cmd[0] == 'q') {
404 if (cmd[0] == 'D' || cmd[0] == 'L' || cmd[0] == 'r'){
405 XMapRaised(app->display, XtWindow(app->remoteWin));
406 XFlush(app->display);
409 XFree((XPointer)cmd);