#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define XtStrlen(s) ((s) ? strlen(s) : 0)
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Converters.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include "DviP.h"
static char default_font_map_1[] = "\
R -*-times-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\
I -*-times-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\
B -*-times-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\
F -*-times-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\
TR -*-times-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\
TI -*-times-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\
TB -*-times-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\
TF -*-times-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\
BI -*-times-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\
C -*-courier-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\
CO -*-courier-medium-o-normal--*-*-*-*-*-*-iso8859-1\n\
CB -*-courier-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\
CF -*-courier-bold-o-normal--*-*-*-*-*-*-iso8859-1\n\
H -*-helvetica-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\
HO -*-helvetica-medium-o-normal--*-*-*-*-*-*-iso8859-1\n\
HB -*-helvetica-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\
HF -*-helvetica-bold-o-normal--*-*-*-*-*-*-iso8859-1\n\
";
static char default_font_map_2[] = "\
N -*-new century schoolbook-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\
NI -*-new century schoolbook-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\
NB -*-new century schoolbook-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\
NF -*-new century schoolbook-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\
A -*-charter-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\
AI -*-charter-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\
AB -*-charter-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\
AF -*-charter-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\
S -*-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific\n\
S2 -*-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific\n\
";
#define offset(field) XtOffsetOf(DviRec, field)
static XtResource resources[] = {
{XtNfontMap, XtCFontMap, XtRString, sizeof (char *),
offset(dvi.font_map_string), XtRString, NULL },
{XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long),
offset(dvi.foreground), XtRString, XtDefaultForeground},
{XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int),
offset(dvi.requested_page), XtRImmediate, (XtPointer) 1},
{XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int),
offset (dvi.last_page), XtRImmediate, (XtPointer) 0},
{XtNfile, XtCFile, XtRFile, sizeof (FILE *),
offset (dvi.file), XtRFile, (char *) 0},
{XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean),
offset(dvi.seek), XtRImmediate, (XtPointer) False},
{XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
offset(dvi.default_font), XtRString, XtDefaultFont},
{XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
offset(dvi.backing_store), XtRString, "default"},
{XtNnoPolyText, XtCNoPolyText, XtRBoolean, sizeof (Boolean),
offset(dvi.noPolyText), XtRImmediate, (XtPointer) False},
{XtNscreenResolution, XtCScreenResolution, XtRInt, sizeof (int),
offset(dvi.screen_resolution), XtRImmediate, (XtPointer) 75},
{XtNpageWidth, XtCPageWidth, XtRFloat, sizeof (float),
offset(dvi.page_width), XtRString, "8.5"},
{XtNpageHeight, XtCPageHeight, XtRFloat, sizeof (float),
offset(dvi.page_height), XtRString, "11"},
{XtNsizeScale, XtCSizeScale, XtRInt, sizeof (int),
offset(dvi.size_scale_set), XtRImmediate, (XtPointer) 0},
};
#undef offset
static void ClassInitialize(void);
static void Initialize(Widget, Widget, ArgList, Cardinal *);
static void Realize(Widget, XtValueMask *, XSetWindowAttributes *);
static void Destroy(Widget);
static void Redisplay(Widget, XEvent *, Region);
static Boolean SetValues(Widget, Widget, Widget, ArgList , Cardinal *);
static Boolean SetValuesHook(Widget, ArgList, Cardinal *);
static XtGeometryResult QueryGeometry(Widget,
XtWidgetGeometry *, XtWidgetGeometry *);
static void RequestDesiredSize(DviWidget);
static void ShowDvi(DviWidget);
static void CloseFile(DviWidget);
static void OpenFile(DviWidget);
#define SuperClass ((SimpleWidgetClass)&simpleClassRec)
DviClassRec dviClassRec = {
{
(WidgetClass) SuperClass,
"Dvi",
sizeof(DviRec),
ClassInitialize,
NULL,
FALSE,
Initialize,
NULL,
Realize,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
FALSE,
XtExposeCompressMaximal,
TRUE,
FALSE,
Destroy,
NULL,
Redisplay,
SetValues,
SetValuesHook,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
0,
QueryGeometry,
XtInheritDisplayAccelerator,
NULL,
},
{
XtInheritChangeSensitive
},
{
0,
},
};
WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
static void
ClassInitialize (void)
{
int len1 = strlen(default_font_map_1);
int len2 = strlen(default_font_map_2);
char *dfm = XtMalloc(len1 + len2 + 1);
char *ptr = dfm;
strcpy(ptr, default_font_map_1); ptr += len1;
strcpy(ptr, default_font_map_2);
resources[0].default_addr = dfm;
XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
NULL, 0 );
}
static void
Initialize(request, new, args, num_args)
Widget request, new;
ArgList args;
Cardinal *num_args;
{
DviWidget dw = (DviWidget) new;
dw->dvi.tmpFile = 0;
dw->dvi.readingTmp = 0;
dw->dvi.ungot = 0;
dw->dvi.normal_GC = 0;
dw->dvi.file_map = 0;
dw->dvi.fonts = 0;
dw->dvi.font_map = 0;
dw->dvi.current_page = 0;
dw->dvi.font_size = 0;
dw->dvi.font_number = 0;
dw->dvi.device_resolution = 0;
dw->dvi.line_width = 0;
dw->dvi.line_style = 0;
dw->dvi.font = 0;
dw->dvi.display_enable = 0;
dw->dvi.scale = 0.0;
dw->dvi.state = 0;
dw->dvi.cache.index = 0;
dw->dvi.cache.font = 0;
dw->dvi.size_scale = 0;
dw->dvi.size_scale_set = 0;
RequestDesiredSize (dw);
}
static void
Realize(w, valueMask, attrs)
Widget w;
XtValueMask *valueMask;
XSetWindowAttributes *attrs;
{
DviWidget dw = (DviWidget) w;
XGCValues values;
if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
attrs->backing_store = dw->dvi.backing_store;
*valueMask |= CWBackingStore;
}
XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
*valueMask, attrs);
values.foreground = dw->dvi.foreground;
dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
GCForeground, &values);
#ifdef USE_XFT
{
int scr;
Visual *visual;
Colormap cmap;
XRenderColor black;
scr = XScreenNumberOfScreen (dw->core.screen);
visual = DefaultVisual (XtDisplay (w), scr);
cmap = DefaultColormap (XtDisplay (w), scr);
dw->dvi.draw = XftDrawCreate (XtDisplay (w), XtWindow (w),
visual, cmap);
black.red = black.green = black.blue = 0;
black.alpha = 0xffff;
XftColorAllocValue (XtDisplay (w), visual, cmap,
&black, &dw->dvi.black);
dw->dvi.default_font = XftFontOpenName (XtDisplay (w),
scr,
"serif-12");
}
#endif
if (dw->dvi.file)
OpenFile (dw);
ParseFontMap (dw);
}
static void
Destroy(w)
Widget w;
{
DviWidget dw = (DviWidget) w;
XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
DestroyFontMap (dw->dvi.font_map);
DestroyFileMap (dw->dvi.file_map);
}
static void
Redisplay(w, event, region)
Widget w;
XEvent *event;
Region region;
{
DviWidget dw = (DviWidget) w;
#ifndef USE_XFT
XRectangle extents;
#endif
#ifdef USE_XFT
XClearArea (XtDisplay (dw),
XtWindow (dw),
0, 0, 0, 0, False);
dw->dvi.extents.x1 = 0;
dw->dvi.extents.y1 = 0;
dw->dvi.extents.x2 = dw->core.width;
dw->dvi.extents.y2 = dw->core.height;
#else
XClipBox (region, &extents);
dw->dvi.extents.x1 = extents.x;
dw->dvi.extents.y1 = extents.y;
dw->dvi.extents.x2 = extents.x + extents.width;
dw->dvi.extents.y2 = extents.y + extents.height;
#endif
ShowDvi (dw);
}
static void
RequestDesiredSize (dw)
DviWidget dw;
{
XtWidgetGeometry req, rep;
dw->dvi.desired_width = dw->dvi.page_width *
dw->dvi.screen_resolution;
dw->dvi.desired_height = dw->dvi.page_height *
dw->dvi.screen_resolution;
req.request_mode = CWWidth|CWHeight;
req.width = dw->dvi.desired_width;
req.height = dw->dvi.desired_height;
XtMakeGeometryRequest ((Widget) dw, &req, &rep);
}
static Boolean
SetValues (wcurrent, wrequest, wnew, args, num_args)
Widget wcurrent, wrequest, wnew;
ArgList args;
Cardinal *num_args;
{
DviWidget current = (DviWidget) wcurrent;
DviWidget request = (DviWidget) wrequest;
DviWidget new = (DviWidget) wnew;
Boolean redisplay = FALSE;
char *new_map;
int cur, req;
req = request->dvi.requested_page;
cur = current->dvi.requested_page;
if (cur != req) {
if (req < 1)
req = 1;
if (request->dvi.file)
{
if (current->dvi.last_page != 0 &&
req > current->dvi.last_page)
req = current->dvi.last_page;
}
if (cur != req)
redisplay = TRUE;
new->dvi.requested_page = req;
}
if (current->dvi.font_map_string != request->dvi.font_map_string) {
new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
if (new_map) {
redisplay = TRUE;
strcpy (new_map, request->dvi.font_map_string);
new->dvi.font_map_string = new_map;
if (current->dvi.font_map_string)
XtFree (current->dvi.font_map_string);
current->dvi.font_map_string = 0;
ParseFontMap (new);
}
}
if (current->dvi.screen_resolution != request->dvi.screen_resolution)
{
ResetFonts (new);
new->dvi.line_width = -1;
}
if (request->dvi.device_resolution)
new->dvi.scale = ((double) request->dvi.screen_resolution) /
((double) request->dvi.device_resolution);
if (current->dvi.page_width != request->dvi.page_width ||
current->dvi.page_height != request->dvi.page_height ||
current->dvi.screen_resolution != request->dvi.screen_resolution)
{
RequestDesiredSize (new);
redisplay = TRUE;
}
return redisplay;
}
static Boolean
SetValuesHook (widget, args, num_argsp)
Widget widget;
ArgList args;
Cardinal *num_argsp;
{
DviWidget dw = (DviWidget) widget;
Cardinal i;
for (i = 0; i < *num_argsp; i++) {
if (!strcmp (args[i].name, XtNfile)) {
CloseFile (dw);
OpenFile (dw);
return TRUE;
}
}
return FALSE;
}
static void
CloseFile (dw)
DviWidget dw;
{
if (dw->dvi.tmpFile)
fclose (dw->dvi.tmpFile);
ForgetPagePositions (dw);
}
static void
OpenFile (dw)
DviWidget dw;
{
char tmpName[sizeof ("/tmp/dviXXXXXX")];
#ifdef HAS_MKSTEMP
int fd;
#endif
dw->dvi.tmpFile = 0;
if (!dw->dvi.seek) {
strcpy (tmpName, "/tmp/dviXXXXXX");
#ifndef HAS_MKSTEMP
mktemp (tmpName);
dw->dvi.tmpFile = fopen (tmpName, "w+");
#else
fd = mkstemp(tmpName);
dw->dvi.tmpFile = fdopen(fd, "w+");
#endif
unlink (tmpName);
}
if (dw->dvi.requested_page < 1)
dw->dvi.requested_page = 1;
dw->dvi.last_page = 0;
}
static XtGeometryResult
QueryGeometry (w, request, geometry_return)
Widget w;
XtWidgetGeometry *request, *geometry_return;
{
XtGeometryResult ret;
DviWidget dw = (DviWidget) w;
ret = XtGeometryYes;
if ((int)request->width < dw->dvi.desired_width
|| (int)request->height < dw->dvi.desired_height)
ret = XtGeometryAlmost;
geometry_return->width = dw->dvi.desired_width;
geometry_return->height = dw->dvi.desired_height;
geometry_return->request_mode = CWWidth|CWHeight;
return ret;
}
void
SetDeviceResolution (dw, resolution)
DviWidget dw;
int resolution;
{
if (resolution != dw->dvi.device_resolution) {
dw->dvi.device_resolution = resolution;
dw->dvi.scale = ((double) dw->dvi.screen_resolution) /
((double) resolution);
}
}
static void
ShowDvi (dw)
DviWidget dw;
{
int i;
long file_position;
if (!dw->dvi.file)
return;
if (dw->dvi.requested_page < 1)
dw->dvi.requested_page = 1;
if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
dw->dvi.requested_page = dw->dvi.last_page;
file_position = SearchPagePosition (dw, dw->dvi.requested_page);
if (file_position != -1) {
FileSeek(dw, file_position);
dw->dvi.current_page = dw->dvi.requested_page;
} else {
for (i=dw->dvi.requested_page; i > 0; i--) {
file_position = SearchPagePosition (dw, i);
if (file_position != -1)
break;
}
if (file_position == -1)
file_position = 0;
FileSeek (dw, file_position);
dw->dvi.current_page = i;
dw->dvi.display_enable = 0;
while (dw->dvi.current_page != dw->dvi.requested_page) {
dw->dvi.current_page = ParseInput (dw);
if (feof (dw->dvi.file)) {
file_position = SearchPagePosition (dw,
dw->dvi.current_page);
if (file_position != -1)
FileSeek (dw, file_position);
break;
}
}
}
dw->dvi.display_enable = 1;
ParseInput (dw);
if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
dw->dvi.requested_page = dw->dvi.last_page;
}