1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
18 #include "XPDFViewer.h"
22 //------------------------------------------------------------------------
24 #define remoteCmdSize 512
26 //------------------------------------------------------------------------
28 static String fallbackResources
[] = {
29 "*.zoomComboBox*fontList: -*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
30 "*XmTextField.fontList: -*-courier-medium-r-normal--12-*-*-*-*-*-iso8859-1",
31 "*.fontList: -*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
32 "*XmTextField.translations: #override\\n"
33 " Ctrl<Key>a:beginning-of-line()\\n"
34 " Ctrl<Key>b:backward-character()\\n"
35 " Ctrl<Key>d:delete-next-character()\\n"
36 " Ctrl<Key>e:end-of-line()\\n"
37 " Ctrl<Key>f:forward-character()\\n"
38 " Ctrl<Key>u:beginning-of-line()delete-to-end-of-line()\\n"
39 " Ctrl<Key>k:delete-to-end-of-line()\\n",
40 "*.toolTipEnable: True",
41 "*.toolTipPostDelay: 1500",
42 "*.toolTipPostDuration: 0",
43 "*.TipLabel.foreground: black",
44 "*.TipLabel.background: LightYellow",
45 "*.TipShell.borderWidth: 1",
46 "*.TipShell.borderColor: black",
50 static XrmOptionDescRec xOpts
[] = {
51 {"-display", ".display", XrmoptionSepArg
, NULL
},
52 {"-foreground", "*Foreground", XrmoptionSepArg
, NULL
},
53 {"-fg", "*Foreground", XrmoptionSepArg
, NULL
},
54 {"-background", "*Background", XrmoptionSepArg
, NULL
},
55 {"-bg", "*Background", XrmoptionSepArg
, NULL
},
56 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
57 {"-g", ".geometry", XrmoptionSepArg
, NULL
},
58 {"-font", "*.fontList", XrmoptionSepArg
, NULL
},
59 {"-fn", "*.fontList", XrmoptionSepArg
, NULL
},
60 {"-title", ".title", XrmoptionSepArg
, NULL
},
61 {"-cmap", ".installCmap", XrmoptionNoArg
, (XPointer
)"on"},
62 {"-rgb", ".rgbCubeSize", XrmoptionSepArg
, NULL
},
63 {"-rv", ".reverseVideo", XrmoptionNoArg
, (XPointer
)"true"},
64 {"-papercolor", ".paperColor", XrmoptionSepArg
, NULL
},
65 {"-mattecolor", ".matteColor", XrmoptionSepArg
, NULL
},
66 {"-z", ".initialZoom", XrmoptionSepArg
, NULL
}
69 #define nXOpts (sizeof(xOpts) / sizeof(XrmOptionDescRec))
71 struct XPDFAppResources
{
79 String fullScreenMatteColor
;
83 static Bool defInstallCmap
= False
;
84 static int defRGBCubeSize
= defaultRGBCube
;
85 static Bool defReverseVideo
= False
;
87 static XtResource xResources
[] = {
88 { "geometry", "Geometry", XtRString
, sizeof(String
), XtOffsetOf(XPDFAppResources
, geometry
), XtRString
, (XtPointer
)NULL
},
89 { "title", "Title", XtRString
, sizeof(String
), XtOffsetOf(XPDFAppResources
, title
), XtRString
, (XtPointer
)NULL
},
90 { "installCmap", "InstallCmap", XtRBool
, sizeof(Bool
), XtOffsetOf(XPDFAppResources
, installCmap
), XtRBool
, (XtPointer
)&defInstallCmap
},
91 { "rgbCubeSize", "RgbCubeSize", XtRInt
, sizeof(int), XtOffsetOf(XPDFAppResources
, rgbCubeSize
), XtRInt
, (XtPointer
)&defRGBCubeSize
},
92 { "reverseVideo", "ReverseVideo", XtRBool
, sizeof(Bool
), XtOffsetOf(XPDFAppResources
, reverseVideo
), XtRBool
, (XtPointer
)&defReverseVideo
},
93 { "paperColor", "PaperColor", XtRString
, sizeof(String
), XtOffsetOf(XPDFAppResources
, paperColor
), XtRString
, (XtPointer
)NULL
},
94 { "matteColor", "MatteColor", XtRString
, sizeof(String
), XtOffsetOf(XPDFAppResources
, matteColor
), XtRString
, (XtPointer
)"gray50" },
95 { "fullScreenMatteColor", "FullScreenMatteColor", XtRString
, sizeof(String
), XtOffsetOf(XPDFAppResources
, fullScreenMatteColor
), XtRString
, (XtPointer
)"black" },
96 { "initialZoom", "InitialZoom", XtRString
, sizeof(String
), XtOffsetOf(XPDFAppResources
, initialZoom
), XtRString
, (XtPointer
)NULL
}
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
[0] = paperRGB
[1] = paperRGB
[2] = 0;
168 paperPixel
= BlackPixel(display
, screenNum
);
170 paperRGB
[0] = paperRGB
[1] = paperRGB
[2] = 0xff;
171 paperPixel
= WhitePixel(display
, screenNum
);
173 XtVaGetValues(appShell
, XmNcolormap
, &colormap
, NULL
);
174 if (resources
.paperColor
) {
175 if (XAllocNamedColor(display
, colormap
, resources
.paperColor
,
177 paperRGB
[0] = xcol
.red
>> 8;
178 paperRGB
[1] = xcol
.green
>> 8;
179 paperRGB
[2] = xcol
.blue
>> 8;
180 paperPixel
= xcol
.pixel
;
182 error(-1, "Couldn't allocate color '%s'", resources
.paperColor
);
185 if (XAllocNamedColor(display
, colormap
, resources
.matteColor
,
187 mattePixel
= xcol
.pixel
;
189 mattePixel
= paperPixel
;
191 if (XAllocNamedColor(display
, colormap
, resources
.fullScreenMatteColor
,
193 fullScreenMattePixel
= xcol
.pixel
;
195 fullScreenMattePixel
= paperPixel
;
197 initialZoom
= resources
.initialZoom
? new GString(resources
.initialZoom
)
201 XPDFApp::~XPDFApp() {
202 deleteGList(viewers
, XPDFViewer
);
214 XPDFViewer
*XPDFApp::open(GString
*fileName
, int page
,
215 GString
*ownerPassword
, GString
*userPassword
) {
218 viewer
= new XPDFViewer(this, fileName
, page
, NULL
, fullScreen
,
219 ownerPassword
, userPassword
);
220 if (!viewer
->isOk()) {
224 if (remoteAtom
!= None
) {
225 remoteViewer
= viewer
;
226 remoteWin
= viewer
->getWindow();
227 XtAddEventHandler(remoteWin
, PropertyChangeMask
, False
,
228 &remoteMsgCbk
, this);
229 XSetSelectionOwner(display
, remoteAtom
, XtWindow(remoteWin
), CurrentTime
);
231 viewers
->append(viewer
);
235 XPDFViewer
*XPDFApp::openAtDest(GString
*fileName
, GString
*dest
,
236 GString
*ownerPassword
,
237 GString
*userPassword
) {
240 viewer
= new XPDFViewer(this, fileName
, 1, dest
, fullScreen
,
241 ownerPassword
, userPassword
);
242 if (!viewer
->isOk()) {
246 if (remoteAtom
!= None
) {
247 remoteViewer
= viewer
;
248 remoteWin
= viewer
->getWindow();
249 XtAddEventHandler(remoteWin
, PropertyChangeMask
, False
,
250 &remoteMsgCbk
, this);
251 XSetSelectionOwner(display
, remoteAtom
, XtWindow(remoteWin
), CurrentTime
);
253 viewers
->append(viewer
);
257 XPDFViewer
*XPDFApp::reopen(XPDFViewer
*viewer
, PDFDoc
*doc
, int page
,
261 for (i
= 0; i
< viewers
->getLength(); ++i
) {
262 if (((XPDFViewer
*)viewers
->get(i
)) == viewer
) {
267 viewer
= new XPDFViewer(this, doc
, page
, NULL
, fullScreenA
);
268 if (!viewer
->isOk()) {
272 if (remoteAtom
!= None
) {
273 remoteViewer
= viewer
;
274 remoteWin
= viewer
->getWindow();
275 XtAddEventHandler(remoteWin
, PropertyChangeMask
, False
,
276 &remoteMsgCbk
, this);
277 XSetSelectionOwner(display
, remoteAtom
, XtWindow(remoteWin
), CurrentTime
);
279 viewers
->append(viewer
);
283 void XPDFApp::close(XPDFViewer
*viewer
, GBool closeLast
) {
286 if (viewers
->getLength() == 1) {
287 if (viewer
!= (XPDFViewer
*)viewers
->get(0)) {
296 for (i
= 0; i
< viewers
->getLength(); ++i
) {
297 if (((XPDFViewer
*)viewers
->get(i
)) == viewer
) {
299 if (remoteAtom
!= None
&& remoteViewer
== viewer
) {
300 remoteViewer
= (XPDFViewer
*)viewers
->get(viewers
->getLength() - 1);
301 remoteWin
= remoteViewer
->getWindow();
302 XSetSelectionOwner(display
, remoteAtom
, XtWindow(remoteWin
),
312 void XPDFApp::quit() {
313 if (remoteAtom
!= None
) {
314 XSetSelectionOwner(display
, remoteAtom
, None
, CurrentTime
);
316 while (viewers
->getLength() > 0) {
317 delete (XPDFViewer
*)viewers
->del(0);
319 #if HAVE_XTAPPSETEXITFLAG
320 XtAppSetExitFlag(appContext
);
326 void XPDFApp::run() {
327 XtAppMainLoop(appContext
);
330 void XPDFApp::setRemoteName(char *remoteName
) {
331 remoteAtom
= XInternAtom(display
, remoteName
, False
);
332 remoteXWin
= XGetSelectionOwner(display
, remoteAtom
);
335 GBool
XPDFApp::remoteServerRunning() {
336 return remoteXWin
!= None
;
339 void XPDFApp::remoteExec(char *cmd
) {
340 char cmd2
[remoteCmdSize
];
344 if (n
> remoteCmdSize
- 2) {
345 n
= remoteCmdSize
- 2;
347 memcpy(cmd2
, cmd
, n
);
350 XChangeProperty(display
, remoteXWin
, remoteAtom
, remoteAtom
, 8,
351 PropModeReplace
, (Guchar
*)cmd2
, n
+ 2);
355 void XPDFApp::remoteOpen(GString
*fileName
, int page
, GBool raise
) {
356 char cmd
[remoteCmdSize
];
358 sprintf(cmd
, "openFileAtPage(%.200s,%d)\n",
359 fileName
->getCString(), page
);
361 strcat(cmd
, "raise\n");
363 XChangeProperty(display
, remoteXWin
, remoteAtom
, remoteAtom
, 8,
364 PropModeReplace
, (Guchar
*)cmd
, strlen(cmd
) + 1);
368 void XPDFApp::remoteOpenAtDest(GString
*fileName
, GString
*dest
, GBool raise
) {
369 char cmd
[remoteCmdSize
];
371 sprintf(cmd
, "openFileAtDest(%.200s,%.256s)\n",
372 fileName
->getCString(), dest
->getCString());
374 strcat(cmd
, "raise\n");
376 XChangeProperty(display
, remoteXWin
, remoteAtom
, remoteAtom
, 8,
377 PropModeReplace
, (Guchar
*)cmd
, strlen(cmd
) + 1);
381 void XPDFApp::remoteReload(GBool raise
) {
382 char cmd
[remoteCmdSize
];
384 strcpy(cmd
, "reload\n");
386 strcat(cmd
, "raise\n");
388 XChangeProperty(display
, remoteXWin
, remoteAtom
, remoteAtom
, 8,
389 PropModeReplace
, (Guchar
*)cmd
, strlen(cmd
) + 1);
393 void XPDFApp::remoteRaise() {
394 XChangeProperty(display
, remoteXWin
, remoteAtom
, remoteAtom
, 8,
395 PropModeReplace
, (Guchar
*)"raise\n", 7);
399 void XPDFApp::remoteQuit() {
400 XChangeProperty(display
, remoteXWin
, remoteAtom
, remoteAtom
, 8,
401 PropModeReplace
, (Guchar
*)"quit\n", 6);
405 void XPDFApp::remoteMsgCbk(Widget widget
, XtPointer ptr
,
406 XEvent
*event
, Boolean
*cont
) {
407 XPDFApp
*app
= (XPDFApp
*)ptr
;
414 if (event
->xproperty
.atom
!= app
->remoteAtom
) {
420 if (XGetWindowProperty(app
->display
, XtWindow(app
->remoteWin
),
421 app
->remoteAtom
, 0, remoteCmdSize
/4,
422 True
, app
->remoteAtom
,
423 &type
, &format
, &size
, &remain
,
424 (Guchar
**)&cmd
) != Success
) {
431 while (*p0
&& (p1
= strchr(p0
, '\n'))) {
432 cmdStr
= new GString(p0
, p1
- p0
);
433 app
->remoteViewer
->execCmd(cmdStr
, NULL
);
437 XFree((XPointer
)cmd
);