/* Copyright (c) Xerox Corporation 1993. All rights reserved. */ /* tiogatxt.c -- Text subclass that can read Tioga files. David Nichols December, 1990 */ #include #include #include #include #include #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. */ }