//
// XPDFCore.cc
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
#include <X11/keysym.h>
#include <X11/cursorfont.h>
+#include <string.h>
#include "gmem.h"
#include "GString.h"
#include "GList.h"
#include "GfxState.h"
#include "PSOutputDev.h"
#include "TextOutputDev.h"
-#include "XPixmapOutputDev.h"
+#include "SplashPattern.h"
+#include "XSplashOutputDev.h"
#include "XPDFCore.h"
// these macro defns conflict with xpdf's Object class
//------------------------------------------------------------------------
-static int zoomDPI[maxZoom - minZoom + 1] = {
- 29, 35, 42, 50, 60,
- 72,
- 86, 104, 124, 149, 179
-};
-
-//------------------------------------------------------------------------
-
GString *XPDFCore::currentSelection = NULL;
XPDFCore *XPDFCore::currentSelectionOwner = NULL;
+Atom XPDFCore::targetsAtom;
//------------------------------------------------------------------------
// XPDFCore
//------------------------------------------------------------------------
XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA,
- Gulong paperColorA, GBool fullScreenA, GBool reverseVideo,
- GBool installCmap, int rgbCubeSize) {
+ SplashRGB8 paperColorA, GBool fullScreenA,
+ GBool reverseVideo, GBool installCmap, int rgbCubeSize) {
GString *initialZoom;
+ SplashColor paperColor2;
int i;
shell = shellA;
parentWidget = parentWidgetA;
display = XtDisplay(parentWidget);
screenNum = XScreenNumberOfScreen(XtScreen(parentWidget));
+ targetsAtom = XInternAtom(display, "TARGETS", False);
paperColor = paperColorA;
fullScreen = fullScreenA;
zoom = zoomWidth;
} else {
zoom = atoi(initialZoom->getCString());
- if (zoom < minZoom) {
- zoom = minZoom;
- } else if (zoom > maxZoom) {
- zoom = maxZoom;
+ if (zoom <= 0) {
+ zoom = defZoom;
}
}
delete initialZoom;
initWindow();
// create the OutputDev
- out = new XPixmapOutputDev(display, screenNum, visual, colormap,
- reverseVideo, paperColor,
+ paperColor2.rgb8 = paperColor;
+ out = new XSplashOutputDev(display, screenNum, visual, colormap,
+ reverseVideo, paperColor2,
installCmap, rgbCubeSize, gTrue,
&outputDevRedrawCbk, this);
out->startDoc(NULL);
delete history[i].fileName;
}
}
- if (selectGC) {
- XFreeGC(display, selectGC);
- XFreeGC(display, highlightGC);
- }
if (drawAreaGC) {
XFreeGC(display, drawAreaGC);
}
- if (drawArea) {
- XtDestroyWidget(drawArea);
- }
- if (drawAreaFrame) {
- XtDestroyWidget(drawAreaFrame);
- }
- if (vScrollBar) {
- XtDestroyWidget(vScrollBar);
- }
- if (hScrollBar) {
- XtDestroyWidget(hScrollBar);
- }
if (scrolledWin) {
XtDestroyWidget(scrolledWin);
}
return errNone;
}
+int XPDFCore::loadFile(BaseStream *stream, GString *ownerPassword,
+ GString *userPassword) {
+ PDFDoc *newDoc;
+ GString *password;
+ GBool again;
+ int err;
+
+ // busy cursor
+ setCursor(busyCursor);
+
+ // open the PDF file
+ newDoc = new PDFDoc(stream, ownerPassword, userPassword);
+ if (!newDoc->isOk()) {
+ err = newDoc->getErrorCode();
+ delete newDoc;
+ if (err != errEncrypted || !reqPasswordCbk) {
+ setCursor(None);
+ return err;
+ }
+
+ // try requesting a password
+ again = ownerPassword != NULL || userPassword != NULL;
+ while (1) {
+ if (!(password = (*reqPasswordCbk)(reqPasswordCbkData, again))) {
+ setCursor(None);
+ return errEncrypted;
+ }
+ newDoc = new PDFDoc(stream, password, password);
+ if (newDoc->isOk()) {
+ break;
+ }
+ err = newDoc->getErrorCode();
+ delete newDoc;
+ if (err != errEncrypted) {
+ setCursor(None);
+ return err;
+ }
+ again = gTrue;
+ }
+ }
+
+ // replace old document
+ if (doc) {
+ delete doc;
+ }
+ doc = newDoc;
+ if (out) {
+ out->startDoc(doc->getXRef());
+ }
+
+ // nothing displayed yet
+ page = -99;
+
+ // save the modification time
+ modTime = getModTime(doc->getFileName()->getCString());
+
+ // update the parent window
+ if (updateCbk) {
+ (*updateCbk)(updateCbkData, doc->getFileName(), -1,
+ doc->getNumPages(), NULL);
+ }
+
+ // back to regular cursor
+ setCursor(None);
+
+ return errNone;
+}
+
void XPDFCore::resizeToPage(int pg) {
Dimension width, height;
double width1, height1;
height1 = doc->getPageHeight(pg);
}
if (zoom == zoomPage || zoom == zoomWidth) {
- width = (Dimension)((width1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
- height = (Dimension)((height1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
+ width = (Dimension)(width1 * 0.01 * defZoom + 0.5);
+ height = (Dimension)(height1 * 0.01 * defZoom + 0.5);
} else {
- width = (Dimension)((width1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
- height = (Dimension)((height1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
+ width = (Dimension)(width1 * 0.01 * zoom + 0.5);
+ height = (Dimension)(height1 * 0.01 * zoom + 0.5);
}
if (width > displayW - 100) {
width = displayW - 100;
redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
}
-void XPDFCore::displayPage(int pageA, int zoomA, int rotateA,
+void XPDFCore::displayPage(int pageA, double zoomA, int rotateA,
GBool scrollToTop, GBool addToHist) {
double hDPI, vDPI;
int rot;
XPDFHistory *h;
GBool newZoom;
- XGCValues gcValues;
time_t newModTime;
int oldScrollX, oldScrollY;
modTime = newModTime;
}
- // free the old GCs
- if (selectGC) {
- XFreeGC(display, selectGC);
- XFreeGC(display, highlightGC);
- }
-
// new page number
page = pageA;
dpi = (drawAreaWidth / doc->getPageWidth(page)) * 72;
}
} else {
- dpi = zoomDPI[zoom - minZoom];
+ dpi = 0.01 * zoom * 72;
}
- out->setWindow(XtWindow(drawArea));
- doc->displayPage(out, page, dpi, rotate, gTrue);
+ doc->displayPage(out, page, dpi, dpi, rotate, gTrue, gTrue);
oldScrollX = scrollX;
oldScrollY = scrollY;
updateScrollBars();
if (h->fileName) {
delete h->fileName;
}
- h->fileName = doc->getFileName()->copy();
+ if (doc->getFileName()) {
+ h->fileName = doc->getFileName()->copy();
+ } else {
+ h->fileName = NULL;
+ }
h->page = page;
if (historyBLen < xpdfHistorySize) {
++historyBLen;
(*updateCbk)(updateCbkData, NULL, page, -1, "");
}
- // allocate new GCs
- gcValues.foreground = BlackPixel(display, screenNum) ^
- WhitePixel(display, screenNum);
- gcValues.function = GXxor;
- selectGC = XCreateGC(display, out->getPixmap(),
- GCForeground | GCFunction, &gcValues);
- highlightGC = XCreateGC(display, out->getPixmap(),
- GCForeground | GCFunction, &gcValues);
-
// back to regular cursor
setCursor(None);
}
-void XPDFCore::displayDest(LinkDest *dest, int zoomA, int rotateA,
+void XPDFCore::displayDest(LinkDest *dest, double zoomA, int rotateA,
GBool addToHist) {
Ref pageRef;
int pg;
}
if (page > 1) {
if (!fullScreen && bottom) {
- scrollY = out->getPixmapHeight() - drawAreaHeight;
+ scrollY = out->getBitmapHeight() - drawAreaHeight;
if (scrollY < 0) {
scrollY = 0;
}
}
--historyFLen;
++historyBLen;
- if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
+ if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
if (loadFile(history[historyCur].fileName) != errNone) {
XBell(display, 0);
return;
}
--historyBLen;
++historyFLen;
- if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
+ if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
if (loadFile(history[historyCur].fileName) != errNone) {
XBell(display, 0);
return;
}
void XPDFCore::scrollPageDown() {
- if (scrollY >= out->getPixmapHeight() - drawAreaHeight) {
+ if (scrollY >= out->getBitmapHeight() - drawAreaHeight) {
gotoNextPage(1, gTrue);
} else {
scrollTo(scrollX, scrollY + drawAreaHeight);
needRedraw = gFalse;
- maxPos = out ? out->getPixmapWidth() : 1;
+ maxPos = out ? out->getBitmapWidth() : 1;
if (maxPos < drawAreaWidth) {
maxPos = drawAreaWidth;
}
needRedraw = gTrue;
}
- maxPos = out ? out->getPixmapHeight() : 1;
+ maxPos = out ? out->getBitmapHeight() : 1;
if (maxPos < drawAreaHeight) {
maxPos = drawAreaHeight;
}
void XPDFCore::setSelection(int newXMin, int newYMin,
int newXMax, int newYMax) {
- Pixmap pixmap;
int x, y;
GBool needRedraw, needScroll;
GBool moveLeft, moveRight, moveTop, moveBottom;
-
- pixmap = out->getPixmap();
+ SplashColor xorColor;
// erase old selection on off-screen bitmap
needRedraw = gFalse;
if (selectXMin < selectXMax && selectYMin < selectYMax) {
- XFillRectangle(display, pixmap,
- selectGC, selectXMin, selectYMin,
- selectXMax - selectXMin, selectYMax - selectYMin);
+ xorColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff);
+ out->xorRectangle(selectXMin, selectYMin, selectXMax, selectYMax,
+ new SplashSolidColor(xorColor));
needRedraw = gTrue;
}
// draw new selection on off-screen bitmap
if (newXMin < newXMax && newYMin < newYMax) {
- XFillRectangle(display, pixmap,
- selectGC, newXMin, newYMin,
- newXMax - newXMin, newYMax - newYMin);
+ xorColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff);
+ out->xorRectangle(newXMin, newYMin, newXMax, newYMax,
+ new SplashSolidColor(xorColor));
needRedraw = gTrue;
}
// clip mouse coords
if (mx < 0) {
mx = 0;
- } else if (mx >= out->getPixmapWidth()) {
- mx = out->getPixmapWidth() - 1;
+ } else if (mx >= out->getBitmapWidth()) {
+ mx = out->getBitmapWidth() - 1;
}
if (my < 0) {
my = 0;
- } else if (my >= out->getPixmapHeight()) {
- my = out->getPixmapHeight() - 1;
+ } else if (my >= out->getBitmapHeight()) {
+ my = out->getBitmapHeight() - 1;
}
// move appropriate edges of selection
Atom *target, Atom *type,
XtPointer *value, unsigned long *length,
int *format) {
- if (*target != XA_STRING) {
- return False;
- }
- //~ for multithreading: need a mutex here
- *value = XtNewString(currentSelection->getCString());
- *length = currentSelection->getLength();
- *type = XA_STRING;
- *format = 8; // 8-bit elements
- return True;
+ Atom *array;
+
+ // send back a list of supported conversion targets
+ if (*target == targetsAtom) {
+ if (!(array = (Atom *)XtMalloc(sizeof(Atom)))) {
+ return False;
+ }
+ array[0] = XA_STRING;
+ *value = (XtPointer)array;
+ *type = XA_ATOM;
+ *format = 32;
+ *length = 1;
+ return True;
+
+ // send the selected text
+ } else if (*target == XA_STRING) {
+ //~ for multithreading: need a mutex here
+ *value = XtNewString(currentSelection->getCString());
+ *length = currentSelection->getLength();
+ *type = XA_STRING;
+ *format = 8; // 8-bit elements
+ return True;
+ }
+
+ return False;
}
GBool XPDFCore::getSelection(int *xMin, int *yMin, int *xMax, int *yMax) {
if (!doc->okToCopy()) {
return NULL;
}
- textOut = new TextOutputDev(NULL, gFalse, gFalse, gFalse);
+ textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
if (!textOut->isOk()) {
delete textOut;
return NULL;
}
- doc->displayPage(textOut, pageNum, dpi, rotate, gFalse);
+ doc->displayPage(textOut, pageNum, dpi, dpi, rotate, gTrue, gFalse);
s = textOut->getText(xMin, yMin, xMax, yMax);
delete textOut;
return s;
// hyperlinks
//------------------------------------------------------------------------
-void XPDFCore::doLink(int mx, int my) {
+GBool XPDFCore::doLink(int mx, int my) {
double x, y;
LinkAction *action;
out->cvtDevToUser(mx, my, &x, &y);
if ((action = doc->findLink(x, y))) {
doAction(action);
+ return gTrue;
}
+ return gFalse;
}
void XPDFCore::doAction(LinkAction *action) {
void XPDFCore::runCommand(GString *cmdFmt, GString *arg) {
GString *cmd;
char *s;
- int i;
if ((s = strstr(cmdFmt->getCString(), "%s"))) {
- cmd = arg->copy();
- // filter out any quote marks (' or ") to avoid a potential
- // security hole
- i = 0;
- while (i < cmd->getLength()) {
- if (cmd->getChar(i) == '"') {
- cmd->del(i);
- cmd->insert(i, "%22");
- i += 3;
- } else if (cmd->getChar(i) == '\'') {
- cmd->del(i);
- cmd->insert(i, "%27");
- i += 3;
- } else {
- ++i;
- }
- }
+ cmd = mungeURL(arg);
cmd->insert(0, cmdFmt->getCString(),
s - cmdFmt->getCString());
cmd->append(s + 2);
delete cmd;
}
+// Escape any characters in a URL which might cause problems when
+// calling system().
+GString *XPDFCore::mungeURL(GString *url) {
+ static char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-_.~/?:@&=+,#%";
+ GString *newURL;
+ char c;
+ char buf[4];
+ int i;
+
+ newURL = new GString();
+ for (i = 0; i < url->getLength(); ++i) {
+ c = url->getChar(i);
+ if (strchr(allowed, c)) {
+ newURL->append(c);
+ } else {
+ sprintf(buf, "%%%02x", c & 0xff);
+ newURL->append(buf);
+ }
+ }
+ return newURL;
+}
+
//------------------------------------------------------------------------
// find
//------------------------------------------------------------------------
-void XPDFCore::find(char *s) {
+void XPDFCore::find(char *s, GBool next) {
Unicode *u;
TextOutputDev *textOut;
int xMin, yMin, xMax, yMax;
double xMin1, yMin1, xMax1, yMax1;
int pg;
- GBool top;
+ GBool startAtTop;
int len, i;
// check for zero-length string
#endif
// search current page starting at current selection or top of page
- xMin = yMin = xMax = yMax = 0;
- if (selectXMin < selectXMax && selectYMin < selectYMax) {
- xMin = selectXMax;
- yMin = (selectYMin + selectYMax) / 2;
- top = gFalse;
- } else {
- top = gTrue;
- }
- if (out->findText(u, len, top, gTrue, &xMin, &yMin, &xMax, &yMax)) {
+ startAtTop = !next && !(selectXMin < selectXMax && selectYMin < selectYMax);
+ xMin = selectXMin + 1;
+ yMin = selectYMin + 1;
+ xMax = yMax = 0;
+ if (out->findText(u, len, startAtTop, gTrue, next, gFalse,
+ &xMin, &yMin, &xMax, &yMax)) {
goto found;
}
// search following pages
- textOut = new TextOutputDev(NULL, gFalse, gFalse, gFalse);
+ textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
if (!textOut->isOk()) {
delete textOut;
goto done;
}
for (pg = page+1; pg <= doc->getNumPages(); ++pg) {
- doc->displayPage(textOut, pg, 72, 0, gFalse);
- if (textOut->findText(u, len, gTrue, gTrue,
+ doc->displayPage(textOut, pg, 72, 72, 0, gTrue, gFalse);
+ if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
&xMin1, &yMin1, &xMax1, &yMax1)) {
goto foundPage;
}
// search previous pages
for (pg = 1; pg < page; ++pg) {
- doc->displayPage(textOut, pg, 72, 0, gFalse);
- if (textOut->findText(u, len, gTrue, gTrue,
+ doc->displayPage(textOut, pg, 72, 72, 0, gTrue, gFalse);
+ if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
&xMin1, &yMin1, &xMax1, &yMax1)) {
goto foundPage;
}
delete textOut;
// search current page ending at current selection
- if (selectXMin < selectXMax && selectYMin < selectYMax) {
+ if (!startAtTop) {
+ xMin = yMin = 0;
xMax = selectXMin;
- yMax = (selectYMin + selectYMax) / 2;
- if (out->findText(u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) {
+ yMax = selectYMin;
+ if (out->findText(u, len, gTrue, gFalse, gFalse, next,
+ &xMin, &yMin, &xMax, &yMax)) {
goto found;
}
}
foundPage:
delete textOut;
displayPage(pg, zoom, rotate, gTrue, gTrue);
- if (!out->findText(u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) {
+ if (!out->findText(u, len, gTrue, gTrue, gFalse, gFalse,
+ &xMin, &yMin, &xMax, &yMax)) {
// this can happen if coalescing is bad
goto done;
}
XtManageChild(drawAreaFrame);
n = 0;
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); ++n;
- XtSetArg(args[n], XmNbackground, paperColor); ++n;
XtSetArg(args[n], XmNwidth, 700); ++n;
XtSetArg(args[n], XmNheight, 500); ++n;
drawArea = XmCreateDrawingArea(drawAreaFrame, "drawArea", args, n);
// can't create a GC until the window gets mapped
drawAreaGC = NULL;
- selectGC = NULL;
- highlightGC = NULL;
}
void XPDFCore::hScrollChangeCbk(Widget widget, XtPointer ptr,
Arg args[2];
int n;
Dimension w, h;
+ int oldScrollX, oldScrollY;
n = 0;
XtSetArg(args[n], XmNwidth, &w); ++n;
core->displayPage(core->page, core->zoom, core->rotate,
gFalse, gFalse);
} else {
+ oldScrollX = core->scrollX;
+ oldScrollY = core->scrollY;
core->updateScrollBars();
+ if (core->scrollX != oldScrollX || core->scrollY != oldScrollY) {
+ core->redrawRectangle(core->scrollX, core->scrollY,
+ core->drawAreaWidth, core->drawAreaHeight);
+ }
}
}
} else if (data->event->xbutton.button == 5) { // mouse wheel down
if (core->fullScreen ||
core->scrollY >=
- core->out->getPixmapHeight() - core->drawAreaHeight) {
+ core->out->getBitmapHeight() - core->drawAreaHeight) {
core->gotoNextPage(1, gTrue);
} else {
core->scrollDown(1);
}
- } else if (data->event->xbutton.button == 6) { // second mouse wheel right
+ } else if (data->event->xbutton.button == 6) { // second mouse wheel left
if (!core->fullScreen) {
- core->scrollRight(1);
+ core->scrollLeft(1);
}
- } else if (data->event->xbutton.button == 7) { // second mouse wheel left
+ } else if (data->event->xbutton.button == 7) { // second mouse wheel right
if (!core->fullScreen) {
- core->scrollLeft(1);
+ core->scrollRight(1);
}
} else {
if (*core->mouseCbk) {
if (modifiers & ControlMask) {
displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue);
} else if (!fullScreen) {
- scrollTo(out->getPixmapWidth() - drawAreaWidth,
- out->getPixmapHeight() - drawAreaHeight);
+ scrollTo(out->getBitmapWidth() - drawAreaWidth,
+ out->getBitmapHeight() - drawAreaHeight);
}
return;
case XK_Page_Up:
}
// draw white background past the edges of the document
- if (x + w > out->getPixmapWidth()) {
+ if (x + w > out->getBitmapWidth()) {
XFillRectangle(display, drawAreaWin, drawAreaGC,
- out->getPixmapWidth() - scrollX, y - scrollY,
- x + w - out->getPixmapWidth(), h);
- w = out->getPixmapWidth() - x;
+ out->getBitmapWidth() - scrollX, y - scrollY,
+ x + w - out->getBitmapWidth(), h);
+ w = out->getBitmapWidth() - x;
}
- if (y + h > out->getPixmapHeight()) {
+ if (y + h > out->getBitmapHeight()) {
XFillRectangle(display, drawAreaWin, drawAreaGC,
- x - scrollX, out->getPixmapHeight() - scrollY,
- w, y + h - out->getPixmapHeight());
- h = out->getPixmapHeight() - y;
+ x - scrollX, out->getBitmapHeight() - scrollY,
+ w, y + h - out->getBitmapHeight());
+ h = out->getBitmapHeight() - y;
}
- // redraw (checking to see if pixmap has been allocated yet)
- if (out->getPixmapWidth() > 0) {
- XCopyArea(display, out->getPixmap(), drawAreaWin, drawAreaGC,
- x, y, w, h, x - scrollX, y - scrollY);
+ // redraw
+ if (w >= 0 && h >= 0) {
+ out->redraw(x, y, drawAreaWin, drawAreaGC, x - scrollX, y - scrollY, w, h);
}
}
int n;
int maxPos;
- maxPos = out ? out->getPixmapWidth() : 1;
+ maxPos = out ? out->getBitmapWidth() : 1;
if (maxPos < drawAreaWidth) {
maxPos = drawAreaWidth;
}
XtSetArg(args[n], XmNpageIncrement, drawAreaWidth); ++n;
XtSetValues(hScrollBar, args, n);
- maxPos = out ? out->getPixmapHeight() : 1;
+ maxPos = out ? out->getBitmapHeight() : 1;
if (maxPos < drawAreaHeight) {
maxPos = drawAreaHeight;
}
GBool XPDFCore::doDialog(int type, GBool hasCancel,
char *title, GString *msg) {
- Widget dialog;
+ Widget dialog, scroll, text;
XtAppContext appContext;
Arg args[20];
int n;
XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
s1 = XmStringCreateLocalized(title);
XtSetArg(args[n], XmNdialogTitle, s1); ++n;
- s2 = XmStringCreateLocalized(msg->getCString());
- XtSetArg(args[n], XmNmessageString, s2); ++n;
+ s2 = NULL; // make gcc happy
+ if (msg->getLength() <= 80) {
+ s2 = XmStringCreateLocalized(msg->getCString());
+ XtSetArg(args[n], XmNmessageString, s2); ++n;
+ }
dialog = XmCreateMessageDialog(drawArea, "questionDialog", args, n);
XmStringFree(s1);
- XmStringFree(s2);
+ if (msg->getLength() <= 80) {
+ XmStringFree(s2);
+ } else {
+ n = 0;
+ XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n;
+ if (drawAreaWidth > 300) {
+ XtSetArg(args[n], XmNwidth, drawAreaWidth - 100); ++n;
+ }
+ scroll = XmCreateScrolledWindow(dialog, "scroll", args, n);
+ XtManageChild(scroll);
+ n = 0;
+ XtSetArg(args[n], XmNeditable, False); ++n;
+ XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); ++n;
+ XtSetArg(args[n], XmNvalue, msg->getCString()); ++n;
+ XtSetArg(args[n], XmNshadowThickness, 0); ++n;
+ text = XmCreateText(scroll, "text", args, n);
+ XtManageChild(text);
+ }
XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
XtAddCallback(dialog, XmNokCallback,
&dialogOkCbk, (XtPointer)this);