1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
18 #include "XPDFViewer.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;
166 paperColor = reverseVideo ? BlackPixel(display, screenNum) :
167 WhitePixel(display, screenNum);
168 if (resources.paperColor) {
169 XtVaGetValues(appShell, XmNcolormap, &colormap, NULL);
170 if (XAllocNamedColor(display, colormap, resources.paperColor,
172 paperColor = xcol.pixel;
174 error(-1, "Couldn't allocate color '%s'", resources.paperColor);
177 initialZoom = resources.initialZoom ? new GString(resources.initialZoom)
179 viKeys = (GBool)resources.viKeys;
182 XPDFApp::~XPDFApp() {
183 deleteGList(viewers, XPDFViewer);
195 XPDFViewer *XPDFApp::open(GString *fileName, int page,
196 GString *ownerPassword, GString *userPassword) {
199 viewer = new XPDFViewer(this, fileName, page, NULL,
200 ownerPassword, userPassword);
201 if (!viewer->isOk()) {
205 if (remoteAtom != None) {
206 remoteViewer = viewer;
207 remoteWin = viewer->getWindow();
208 XtAddEventHandler(remoteWin, PropertyChangeMask, False,
209 &remoteMsgCbk, this);
210 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime);
212 viewers->append(viewer);
216 XPDFViewer *XPDFApp::openAtDest(GString *fileName, GString *dest,
217 GString *ownerPassword,
218 GString *userPassword) {
221 viewer = new XPDFViewer(this, fileName, 1, dest,
222 ownerPassword, userPassword);
223 if (!viewer->isOk()) {
227 if (remoteAtom != None) {
228 remoteViewer = viewer;
229 remoteWin = viewer->getWindow();
230 XtAddEventHandler(remoteWin, PropertyChangeMask, False,
231 &remoteMsgCbk, this);
232 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime);
234 viewers->append(viewer);
238 void XPDFApp::close(XPDFViewer *viewer, GBool closeLast) {
241 if (viewers->getLength() == 1) {
242 if (viewer != (XPDFViewer *)viewers->get(0)) {
251 for (i = 0; i < viewers->getLength(); ++i) {
252 if (((XPDFViewer *)viewers->get(i)) == viewer) {
254 if (remoteAtom != None && remoteViewer == viewer) {
255 remoteViewer = (XPDFViewer *)viewers->get(viewers->getLength() - 1);
256 remoteWin = remoteViewer->getWindow();
257 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin),
267 void XPDFApp::quit() {
268 if (remoteAtom != None) {
269 XSetSelectionOwner(display, remoteAtom, None, CurrentTime);
271 while (viewers->getLength() > 0) {
272 delete (XPDFViewer *)viewers->del(0);
274 #if HAVE_XTAPPSETEXITFLAG
275 XtAppSetExitFlag(appContext);
281 void XPDFApp::run() {
282 XtAppMainLoop(appContext);
285 void XPDFApp::setRemoteName(char *remoteName) {
286 remoteAtom = XInternAtom(display, remoteName, False);
287 remoteXWin = XGetSelectionOwner(display, remoteAtom);
290 GBool XPDFApp::remoteServerRunning() {
291 return remoteXWin != None;
294 void XPDFApp::remoteOpen(GString *fileName, int page, GBool raise) {
295 char cmd[remoteCmdSize];
297 sprintf(cmd, "%c %d %.200s",
298 raise ? 'D' : 'd', page, fileName->getCString());
299 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
300 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
304 void XPDFApp::remoteOpenAtDest(GString *fileName, GString *dest, GBool raise) {
305 char cmd[remoteCmdSize];
307 sprintf(cmd, "%c +%.256s %.200s",
308 raise ? 'D' : 'd', dest->getCString(), fileName->getCString());
309 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
310 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
314 void XPDFApp::remoteReload(GBool raise) {
315 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
316 PropModeReplace, raise ? (Guchar *)"L" : (Guchar *)"l", 2);
320 void XPDFApp::remoteRaise() {
321 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
322 PropModeReplace, (Guchar *)"r", 2);
326 void XPDFApp::remoteQuit() {
327 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
328 PropModeReplace, (Guchar *)"q", 2);
332 void XPDFApp::remoteMsgCbk(Widget widget, XtPointer ptr,
333 XEvent *event, Boolean *cont) {
334 XPDFApp *app = (XPDFApp *)ptr;
344 if (event->xproperty.atom != app->remoteAtom) {
351 if (XGetWindowProperty(app->display, XtWindow(app->remoteWin),
352 app->remoteAtom, 0, remoteCmdSize/4,
353 True, app->remoteAtom,
354 &type, &format, &size, &remain,
355 (Guchar **)&cmd) != Success) {
362 // display file / page
363 if (cmd[0] == 'd' || cmd[0] == 'D') {
373 destName = new GString(p + 1);
378 fileName = new GString(q);
379 app->remoteViewer->open(fileName, page, destName);
387 } else if (cmd[0] == 'l' || cmd[0] == 'L') {
388 app->remoteViewer->reloadFile();
391 } else if (cmd[0] == 'q') {
396 if (cmd[0] == 'D' || cmd[0] == 'L' || cmd[0] == 'r'){
397 XMapRaised(app->display, XtWindow(app->remoteWin));
398 XFlush(app->display);
401 XFree((XPointer)cmd);