development-curl is a virtual target
[AROS-Contrib.git] / arospdf / xpdf / XPDFApp.cc
blob498c4b46eecb674d7a04d0ef797fc26e21c8bc11
1 //========================================================================
2 //
3 // XPDFApp.cc
4 //
5 // Copyright 2002-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 #include <aconf.h>
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
15 #include "GString.h"
16 #include "GList.h"
17 #include "Error.h"
18 #include "XPDFViewer.h"
19 #include "XPDFApp.h"
20 #include "config.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",
47 NULL
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 {
72 String geometry;
73 String title;
74 Bool installCmap;
75 int rgbCubeSize;
76 Bool reverseVideo;
77 String paperColor;
78 String matteColor;
79 String fullScreenMatteColor;
80 String initialZoom;
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 //------------------------------------------------------------------------
102 // XPDFApp
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);
113 fflush(stdout);
114 abort();
116 #endif
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));
123 #if XmVERSION > 1
124 XtVaSetValues(XmGetXmDisplay(XtDisplay(appShell)),
125 XmNenableButtonTab, True, NULL);
126 #endif
127 #if XmVERSION > 1
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,
134 NULL);
135 #endif
137 #if 0 //~ for debugging
138 XSynchronize(display, True);
139 XSetErrorHandler(&xErrorHandler);
140 #endif
142 fullScreen = gFalse;
143 remoteAtom = None;
144 remoteViewer = NULL;
145 remoteWin = None;
147 getResources();
149 viewers = new GList();
153 void XPDFApp::getResources() {
154 XPDFAppResources resources;
155 XColor xcol, xcol2;
156 Colormap colormap;
158 XtGetApplicationResources(appShell, &resources, xResources, nXResources,
159 NULL, 0);
160 geometry = resources.geometry ? new GString(resources.geometry)
161 : (GString *)NULL;
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 if (reverseVideo) {
167 paperRGB[0] = paperRGB[1] = paperRGB[2] = 0;
168 paperPixel = BlackPixel(display, screenNum);
169 } else {
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,
176 &xcol, &xcol2)) {
177 paperRGB[0] = xcol.red >> 8;
178 paperRGB[1] = xcol.green >> 8;
179 paperRGB[2] = xcol.blue >> 8;
180 paperPixel = xcol.pixel;
181 } else {
182 error(-1, "Couldn't allocate color '%s'", resources.paperColor);
185 if (XAllocNamedColor(display, colormap, resources.matteColor,
186 &xcol, &xcol2)) {
187 mattePixel = xcol.pixel;
188 } else {
189 mattePixel = paperPixel;
191 if (XAllocNamedColor(display, colormap, resources.fullScreenMatteColor,
192 &xcol, &xcol2)) {
193 fullScreenMattePixel = xcol.pixel;
194 } else {
195 fullScreenMattePixel = paperPixel;
197 initialZoom = resources.initialZoom ? new GString(resources.initialZoom)
198 : (GString *)NULL;
201 XPDFApp::~XPDFApp() {
202 deleteGList(viewers, XPDFViewer);
203 if (geometry) {
204 delete geometry;
206 if (title) {
207 delete title;
209 if (initialZoom) {
210 delete initialZoom;
214 XPDFViewer *XPDFApp::open(GString *fileName, int page,
215 GString *ownerPassword, GString *userPassword) {
216 XPDFViewer *viewer;
218 viewer = new XPDFViewer(this, fileName, page, NULL, fullScreen,
219 ownerPassword, userPassword);
220 if (!viewer->isOk()) {
221 delete viewer;
222 return NULL;
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);
232 return viewer;
235 XPDFViewer *XPDFApp::openAtDest(GString *fileName, GString *dest,
236 GString *ownerPassword,
237 GString *userPassword) {
238 XPDFViewer *viewer;
240 viewer = new XPDFViewer(this, fileName, 1, dest, fullScreen,
241 ownerPassword, userPassword);
242 if (!viewer->isOk()) {
243 delete viewer;
244 return NULL;
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);
254 return viewer;
257 XPDFViewer *XPDFApp::reopen(XPDFViewer *viewer, PDFDoc *doc, int page,
258 GBool fullScreenA) {
259 int i;
261 for (i = 0; i < viewers->getLength(); ++i) {
262 if (((XPDFViewer *)viewers->get(i)) == viewer) {
263 viewers->del(i);
264 delete viewer;
267 viewer = new XPDFViewer(this, doc, page, NULL, fullScreenA);
268 if (!viewer->isOk()) {
269 delete viewer;
270 return NULL;
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);
280 return viewer;
283 void XPDFApp::close(XPDFViewer *viewer, GBool closeLast) {
284 int i;
286 if (viewers->getLength() == 1) {
287 if (viewer != (XPDFViewer *)viewers->get(0)) {
288 return;
290 if (closeLast) {
291 quit();
292 } else {
293 viewer->clear();
295 } else {
296 for (i = 0; i < viewers->getLength(); ++i) {
297 if (((XPDFViewer *)viewers->get(i)) == viewer) {
298 viewers->del(i);
299 if (remoteAtom != None && remoteViewer == viewer) {
300 remoteViewer = (XPDFViewer *)viewers->get(viewers->getLength() - 1);
301 remoteWin = remoteViewer->getWindow();
302 XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin),
303 CurrentTime);
305 delete viewer;
306 return;
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);
321 #else
322 exit(0);
323 #endif
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];
341 int n;
343 n = strlen(cmd);
344 if (n > remoteCmdSize - 2) {
345 n = remoteCmdSize - 2;
347 memcpy(cmd2, cmd, n);
348 cmd2[n] = '\n';
349 cmd2[n+1] = '\0';
350 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
351 PropModeReplace, (Guchar *)cmd2, n + 2);
352 XFlush(display);
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);
360 if (raise) {
361 strcat(cmd, "raise\n");
363 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
364 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
365 XFlush(display);
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());
373 if (raise) {
374 strcat(cmd, "raise\n");
376 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
377 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
378 XFlush(display);
381 void XPDFApp::remoteReload(GBool raise) {
382 char cmd[remoteCmdSize];
384 strcpy(cmd, "reload\n");
385 if (raise) {
386 strcat(cmd, "raise\n");
388 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
389 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
390 XFlush(display);
393 void XPDFApp::remoteRaise() {
394 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
395 PropModeReplace, (Guchar *)"raise\n", 7);
396 XFlush(display);
399 void XPDFApp::remoteQuit() {
400 XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8,
401 PropModeReplace, (Guchar *)"quit\n", 6);
402 XFlush(display);
405 void XPDFApp::remoteMsgCbk(Widget widget, XtPointer ptr,
406 XEvent *event, Boolean *cont) {
407 XPDFApp *app = (XPDFApp *)ptr;
408 char *cmd, *p0, *p1;
409 Atom type;
410 int format;
411 Gulong size, remain;
412 GString *cmdStr;
414 if (event->xproperty.atom != app->remoteAtom) {
415 *cont = True;
416 return;
418 *cont = False;
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) {
425 return;
427 if (!cmd) {
428 return;
430 p0 = cmd;
431 while (*p0 && (p1 = strchr(p0, '\n'))) {
432 cmdStr = new GString(p0, p1 - p0);
433 app->remoteViewer->execCmd(cmdStr, NULL);
434 delete cmdStr;
435 p0 = p1 + 1;
437 XFree((XPointer)cmd);