/* Copyright (c) Xerox Corporation 1993. All rights reserved. */
/* tiogatxt.c -- Text subclass that can read Tioga files.
David Nichols
December, 1990 */
#include <stdio.h>
#include <class.h>
#include <style.ih>
#include <envrment.ih>
#include <stylesht.ih>
#include "tiogatxt.eh"
#include "tioga.h"
#include "tread.h"
static int StartNode();
static int EndNode();
static int Look();
static int Insert();
static int Prop();
static struct tread←Procs procs = {
StartNode,
EndNode,
Look,
Insert,
Prop
};
char *defaultStyle = "cedar";
char *tiogatxt←←ViewName()
{
return "textview";
}
boolean tiogatxt←←InitializeObject(classID, self)
struct classheader *classID;
struct tiogatxt *self;
{
self->nRuns = 0;
self->nAllocedRuns = 10;
self->runs = (struct tiogatxt←Run *) malloc(self->nAllocedRuns *
sizeof(struct tiogatxt←Run));
self->nEnvs = 0;
self->nAllocedEnvs = 10;
self->envs = (struct tiogatxt←Env *) malloc(self->nAllocedEnvs *
sizeof(struct tiogatxt←Env));
return TRUE;
}
void tiogatxt←←SetAttributes(self,atts)
struct tiogatxt *self;
struct attributes *atts;
{
}
long tiogatxt←←Read(self, file, id)
struct tiogatxt *self;
FILE *file;
long id;
{
struct tread←Reader *r;
int result = dataobject←NOREADERROR;
char lookName[10];
int i;
super←Clear(self);
/* Should get this from document, but we'll code it up later. */
tiogatxt←ReadTemplate(self, defaultStyle, FALSE);
/* Set up the lookTable */
for (i = 0; i < tiogatxt←NUMLOOKS; ++i) {
sprintf(lookName, "look←%c", i + 'a');
self->lookTable[i] = stylesheet←Find(self->header.text.styleSheet,
lookName);
}
self->topStyle = stylesheet←Find(self->header.text.styleSheet, "top");
self->nEnvs = 0;
/* Now we're ready to go */
r = (struct tread←Reader *) malloc(sizeof (*r));
self->reader = (char *)r;
if (tioga←FromFile(r, file, procs, (char *) self) < 0) {
/* Not a tioga file, read normally. */
free(r);
self->reader = NULL;
rewind(file);
result = super←Read(self, file, id);
}
/* Set it read only so we don't accidentally smash the original. */
tiogatxt←SetReadOnly(self, TRUE);
return result;
}
long tiogatxt←←Write(self, file, writeID, level)
struct tiogatxt *self;
FILE *file;
long writeID;
int level;
{
struct tread←Reader *r;
if (level != 0 || self->reader == NULL)
return super←Write(self, file, writeID, level);
r = (struct tread←Reader *)self->reader;
fwrite(r->buf, 1, r->totalLen, file);
fflush(file);
return self->header.dataobject.id;
}
char *FixupFormat(format, level)
char *format;
int level;
{
/* Should return if style isn't cedar, but we don't yet. */
if (strcmp(format, "head") != 0)
return format;
switch (level) {
case 1:
return "head1";
case 2:
return "head2";
case 3:
return "head3";
default:
return "head4";
}
}
/* Start a new node at the current position. */
static int StartNode(r, format)
struct tread←Reader *r;
char *format; /* format or NULL */
{
struct tiogatxt *self = (struct tiogatxt *) r->data;
struct style *style;
struct environment *e;
int level;
self->nRuns = 0;
/* Special case for top level. */
if (self->nEnvs == 0) {
self->envs[0].env = environment←GetEnclosing(
self->header.text.rootEnvironment, 0);
self->envs[0].env2 = NULL;
self->envs[0].pos = 0;
self->envs[0].comment = FALSE;
++self->nEnvs;
return;
}
/* Make sure we have enough space in the stack. */
if (self->nEnvs >= self->nAllocedEnvs) {
self->nAllocedEnvs *= 2;
self->envs = (struct tiogatxt←Env *) realloc(self->envs,
self->nAllocedEnvs * sizeof(struct tiogatxt←Env));
}
/* Put self on it. */
if (format == NULL)
format = "default";
format = FixupFormat(format, self->nEnvs);
style = stylesheet←Find(self->header.text.styleSheet, format);
if (style == NULL) {
style = style←New();
style←SetName(style, format);
stylesheet←Add(self->header.text.styleSheet, style);
}
level = self->nEnvs;
self->envs[level].pos = tiogatxt←GetLength(self);
e = environment←InsertStyle(self->envs[level - 1].env,
self->envs[level].pos - self->envs[level - 1].pos,
style, TRUE);
self->envs[level].env = e;
if (self->nEnvs == 1) {
/* Horrible hack for top level stuff. */
self->envs[level].env2 = e;
self->envs[level].env = environment←InsertStyle(e, 0,
self->topStyle, TRUE);
}
else
self->envs[level].env2 = NULL;
self->envs[level].comment = FALSE;
++self->nEnvs;
}
/* End current node. */
static int EndNode(r)
struct tread←Reader *r;
{
struct tiogatxt *self = (struct tiogatxt *) r->data;
char *format;
struct environment *e;
int level;
long len;
/* Wrap text and decrement level. */
--self->nEnvs;
level = self->nEnvs;
if (level == 0)
return; /* top level is special */
e = self->envs[level].env;
len = tiogatxt←GetLength(self) - self->envs[level].pos;
if (len > 0) {
if (self->envs[level].env2 != NULL)
environment←SetLength(self->envs[level].env2, len);
environment←SetLength(e, len);
}
else {
if (self->envs[level].env2 != NULL)
environment←Delete(self->envs[level].env2);
environment←Delete(e);
}
}
/* Add looks for a run, relative to current node. */
static int Look(r, looks, start, len)
struct tread←Reader *r;
long looks;
long start, len;
{
struct tiogatxt *self = (struct tiogatxt *) r->data;
if (looks == 0)
return;
if (self->nRuns >= self->nAllocedRuns) {
self->nAllocedRuns *= 2;
self->runs = (struct tiogatxt←Run *) realloc(self->runs,
self->nAllocedRuns * sizeof(struct tiogatxt←Run));
}
self->runs[self->nRuns].looks = looks;
self->runs[self->nRuns].start = start;
self->runs[self->nRuns].len = len;
++self->nRuns;
}
/* Insert some text. */
static int Insert(r, t, len, comment)
struct tread←Reader *r;
char *t;
long len;
int comment; /* comment node? */
{
struct tiogatxt *self = (struct tiogatxt *) r->data;
struct environment *e;
int i, b;
long pos;
long startPos; /* start of text passed to us */
int nlAdjust; /* adjustment due to adding newline */
if (self->nEnvs == 1 && comment && len == 1)
return; /* top level is special */
startPos = pos = tiogatxt←GetLength(self);
/* Add a newline except for the first piece of text. */
if (startPos == 0)
nlAdjust = 0;
else {
nlAdjust = 1;
tiogatxt←AddInCharacter(self, pos++, '\n');
startPos += nlAdjust;
}
for (i = len; i > 0; ++pos, ++t, --i)
tiogatxt←AddInCharacter(self, pos, *t);
/* Now do the looks. */
e = self->envs[self->nEnvs - 1].env;
/* Wrap look.c if this is a comment node. */
if (comment && self->lookTable['c' - 'a'] != NULL)
e = environment←WrapStyle(e, startPos - nlAdjust, len + nlAdjust,
self->lookTable['c' - 'a']);
/* Add looks from saved runs. */
for (i = 0; i < self->nRuns; ++i) {
for (b = 0; b < tiogatxt←NUMLOOKS; ++b) {
if (self->runs[i].looks & (1 << (31 - b))
&& self->lookTable[b] != NULL)
environment←WrapStyle(e, self->runs[i].start + startPos,
self->runs[i].len, self->lookTable[b]);
}
}
}
static int Prop(r, propName, prop, len)
struct tread←Reader *r;
char *propName;
char *prop;
long len;
{
/* Ignore for now. */
}