NetBSD/gnu/usr.bin/groff/xditview/Dvi.c

545 lines
14 KiB
C

#ifndef SABER
#ifndef lint
static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $";
#endif /* lint */
#endif /* SABER */
/*
* Dvi.c - Dvi display widget
*
*/
#define XtStrlen(s) ((s) ? strlen(s) : 0)
/* The following are defined for the reader's convenience. Any
Xt..Field macro in this code just refers to some field in
one of the substructures of the WidgetRec. */
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Converters.h>
#include <stdio.h>
#include <ctype.h>
#include "DviP.h"
/****************************************************************
*
* Full class record constant
*
****************************************************************/
/* Private Data */
static char default_font_map[] = "\
TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
";
#define offset(field) XtOffset(DviWidget, field)
#define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5))
#define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5))
static XtResource resources[] = {
{XtNfontMap, XtCFontMap, XtRString, sizeof (char *),
offset(dvi.font_map_string), XtRString, default_font_map},
{XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long),
offset(dvi.foreground), XtRString, "black"},
{XtNbackground, XtCBackground, XtRPixel, sizeof (unsigned long),
offset(dvi.background), XtRString, "white"},
{XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int),
offset(dvi.requested_page), XtRString, "1"},
{XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int),
offset (dvi.last_page), XtRString, "0"},
{XtNfile, XtCFile, XtRFile, sizeof (FILE *),
offset (dvi.file), XtRFile, (char *) 0},
{XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean),
offset(dvi.seek), XtRString, "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), XtRString, "false"},
{XtNresolution, XtCResolution, XtRInt, sizeof(int),
offset(dvi.default_resolution), XtRString, "75"},
};
#undef offset
static void ClassInitialize ();
static void ClassPartInitialize();
static void Initialize(), Realize (), Destroy (), Redisplay ();
static Boolean SetValues (), SetValuesHook ();
static XtGeometryResult QueryGeometry ();
static void ShowDvi ();
static void CloseFile (), OpenFile ();
static void FindPage ();
static void SaveToFile ();
DviClassRec dviClassRec = {
{
&widgetClassRec, /* superclass */
"Dvi", /* class_name */
sizeof(DviRec), /* size */
ClassInitialize, /* class_initialize */
ClassPartInitialize, /* class_part_initialize */
FALSE, /* class_inited */
Initialize, /* initialize */
NULL, /* initialize_hook */
Realize, /* realize */
NULL, /* actions */
0, /* num_actions */
resources, /* resources */
XtNumber(resources), /* resource_count */
NULLQUARK, /* xrm_class */
FALSE, /* compress_motion */
TRUE, /* compress_exposure */
TRUE, /* compress_enterleave */
FALSE, /* visible_interest */
Destroy, /* destroy */
NULL, /* resize */
Redisplay, /* expose */
SetValues, /* set_values */
SetValuesHook, /* set_values_hook */
NULL, /* set_values_almost */
NULL, /* get_values_hook */
NULL, /* accept_focus */
XtVersion, /* version */
NULL, /* callback_private */
0, /* tm_table */
QueryGeometry, /* query_geometry */
NULL, /* display_accelerator */
NULL /* extension */
},{
SaveToFile, /* save */
},
};
WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
static void ClassInitialize ()
{
XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
NULL, 0 );
}
/****************************************************************
*
* Private Procedures
*
****************************************************************/
/* ARGSUSED */
static void Initialize(request, new)
Widget request, new;
{
DviWidget dw = (DviWidget) new;
dw->dvi.current_page = 0;
dw->dvi.font_map = 0;
dw->dvi.cache.index = 0;
dw->dvi.text_x_width = 0;
dw->dvi.text_device_width = 0;
dw->dvi.word_flag = 0;
dw->dvi.file = 0;
dw->dvi.tmpFile = 0;
dw->dvi.state = 0;
dw->dvi.readingTmp = 0;
dw->dvi.cache.char_index = 0;
dw->dvi.cache.font_size = -1;
dw->dvi.cache.font_number = -1;
dw->dvi.cache.adjustable[0] = 0;
dw->dvi.file_map = 0;
dw->dvi.fonts = 0;
dw->dvi.seek = False;
dw->dvi.device_resolution = dw->dvi.default_resolution;
dw->dvi.display_resolution = dw->dvi.default_resolution;
dw->dvi.paperlength = dw->dvi.default_resolution*11;
dw->dvi.paperwidth = (dw->dvi.default_resolution*8
+ dw->dvi.default_resolution/2);
dw->dvi.scale_factor = 1.0;
dw->dvi.sizescale = 1;
dw->dvi.line_thickness = -1;
dw->dvi.line_width = 1;
dw->dvi.fill = DVI_FILL_MAX;
dw->dvi.device_font = 0;
dw->dvi.device_font_number = -1;
dw->dvi.device = 0;
dw->dvi.native = 0;
}
#include <X11/bitmaps/gray>
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;
values.cap_style = CapRound;
values.join_style = JoinRound;
values.line_width = dw->dvi.line_width;
dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
GCForeground|GCCapStyle|GCJoinStyle
|GCLineWidth,
&values);
dw->dvi.gray = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
gray_bits,
gray_width, gray_height);
values.background = dw->dvi.background;
values.stipple = dw->dvi.gray;
dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
GCForeground|GCBackground|GCStipple,
&values);
dw->dvi.fill_type = DVI_FILL_BLACK;
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);
XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
XFreePixmap (XtDisplay (w), dw->dvi.gray);
DestroyFontMap (dw->dvi.font_map);
DestroyFileMap (dw->dvi.file_map);
device_destroy (dw->dvi.device);
}
/*
* Repaint the widget window
*/
/* ARGSUSED */
static void
Redisplay(w, event, region)
Widget w;
XEvent *event;
Region region;
{
DviWidget dw = (DviWidget) w;
XRectangle extents;
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;
ShowDvi (dw);
}
/*
* Set specified arguments into widget
*/
/* ARGSUSED */
static Boolean
SetValues (current, request, new)
DviWidget current, request, new;
{
Boolean redisplay = FALSE;
char *new_map;
int cur, 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);
}
}
req = request->dvi.requested_page;
cur = current->dvi.requested_page;
if (cur != req) {
if (!request->dvi.file)
req = 0;
else {
if (req < 1)
req = 1;
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.last_page == 0 && req > cur)
FindPage (new);
}
return redisplay;
}
/*
* use the set_values_hook entry to check when
* the file is set
*/
static Boolean
SetValuesHook (dw, args, num_argsp)
DviWidget dw;
ArgList args;
Cardinal *num_argsp;
{
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")];
dw->dvi.tmpFile = 0;
if (!dw->dvi.seek) {
strcpy (tmpName, "/tmp/dviXXXXXX");
mktemp (tmpName);
dw->dvi.tmpFile = fopen (tmpName, "w+");
unlink (tmpName);
}
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 (((request->request_mode & CWWidth)
&& request->width < MY_WIDTH(dw))
|| ((request->request_mode & CWHeight)
&& request->height < MY_HEIGHT(dw)))
ret = XtGeometryAlmost;
geometry_return->width = MY_WIDTH(dw);
geometry_return->height = MY_HEIGHT(dw);
geometry_return->request_mode = CWWidth|CWHeight;
return ret;
}
SetDevice (dw, name)
DviWidget dw;
char *name;
{
XtWidgetGeometry request, reply;
XtGeometryResult ret;
ForgetFonts (dw);
dw->dvi.device = device_load (name);
if (!dw->dvi.device)
return;
dw->dvi.sizescale = dw->dvi.device->sizescale;
dw->dvi.device_resolution = dw->dvi.device->res;
dw->dvi.native = dw->dvi.device->X11;
dw->dvi.paperlength = dw->dvi.device->paperlength;
dw->dvi.paperwidth = dw->dvi.device->paperwidth;
if (dw->dvi.native) {
dw->dvi.display_resolution = dw->dvi.device_resolution;
dw->dvi.scale_factor = 1.0;
}
else {
dw->dvi.display_resolution = dw->dvi.default_resolution;
dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
/ dw->dvi.device_resolution);
}
request.request_mode = CWWidth|CWHeight;
request.width = MY_WIDTH(dw);
request.height = MY_HEIGHT(dw);
ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
if (ret == XtGeometryAlmost
&& reply.height >= request.height
&& reply.width >= request.width) {
request.width = reply.width;
request.height = reply.height;
XtMakeGeometryRequest ((Widget)dw, &request, &reply);
}
}
static void
ShowDvi (dw)
DviWidget dw;
{
if (!dw->dvi.file) {
static char Error[] = "No file selected";
XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
dw->dvi.default_font->fid);
XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
20, 20, Error, strlen (Error));
return;
}
FindPage (dw);
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;
}
static void
FindPage (dw)
DviWidget dw;
{
int i;
long file_position;
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);
/*
* at EOF, seek back to the begining of this page.
*/
if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
file_position = SearchPagePosition (dw,
dw->dvi.current_page);
if (file_position != -1)
FileSeek (dw, file_position);
dw->dvi.requested_page = dw->dvi.current_page;
break;
}
}
}
}
void DviSaveToFile(w, fp)
Widget w;
FILE *fp;
{
XtCheckSubclass(w, dviWidgetClass, NULL);
(*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
}
static
void SaveToFile(w, fp)
Widget w;
FILE *fp;
{
DviWidget dw = (DviWidget)w;
long pos;
int c;
if (dw->dvi.tmpFile) {
pos = ftell(dw->dvi.tmpFile);
if (dw->dvi.ungot) {
pos--;
dw->dvi.ungot = 0;
/* The ungot character is in the tmpFile, so we don't
want to read it from file. */
(void)getc(dw->dvi.file);
}
}
else
pos = ftell(dw->dvi.file);
FileSeek(dw, 0L);
while (DviGetC(dw, &c) != EOF)
if (putc(c, fp) == EOF) {
/* XXX print error message */
break;
}
FileSeek(dw, pos);
}
static
void ClassPartInitialize(widget_class)
WidgetClass widget_class;
{
DviWidgetClass wc = (DviWidgetClass)widget_class;
DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
if (wc->command_class.save == InheritSaveToFile)
wc->command_class.save = super->command_class.save;
}
/*
Local Variables:
c-indent-level: 8
c-continued-statement-offset: 8
c-brace-offset: -8
c-argdecl-indent: 8
c-label-offset: -8
c-tab-always-indent: nil
End:
*/