/* HMDoc.c -- HyperMedia Document base class */ /* implements ... */ #include "HMDoc.h" /* uses ... */ #include "HTMLdtd.h" #include "SGML.h" #include "object.h" static HMFileWriterProc fileWriter; static HMWriterProc writer; static HMDeleteProc delete; static HMStartTagProc startTag; static HMEndTagProc endTag; static HMDataProc data; HMDoc_Class InCore = {fileWriter, writer, delete, startTag, endTag, data, html_entity_text}; typedef struct{ char* gi; int content; int nattrs; HMBinding* attrs; }Tag; typedef struct _cell{ struct _cell *first, *rest, *up; }Cons; struct _HMDoc{ Cons* root; Cons* here; }; /* constructors */ static HMDoc* fileWriter(fp) FILE* fp; { return 0; /* this class doesn't write to files */ } static HMDoc* writer(out, write) HMStream out; HMWriteProc* write; { return 0; /* this class doesn't write to streams */ } HMDoc* InCore_new() { HMDoc* this = NEW(HMDoc, 1); this->root = 0; this->here = 0; return this; } /* destructors */ static VOID Tag_free PARAMS((Tag* it)); static VOID element_free(this) Cons* this; { Cons* c; if(this->first){ Cons* next; Tag_free((Tag*)this->first); for(c = this->rest; c; c = next){ element_free(c->first); next = c->rest; FREE(c); } }else{ FREE(this->rest); /* data */ } FREE(this); } static VOID delete(this) HMDoc* this; { if(this->root) element_free(this->root); } /* building routines */ static Tag* Tag_new(gi, content, attrs, nattrs) CONST char* gi; CONST HMBinding attrs[]; int nattrs; { Tag* this = NEW(Tag, 1); int total = strlen(gi) + 1; int i; char* p; for(i = 0; igi = NEW(char, total); this->content = content; this->attrs = NEW(HMBinding, nattrs); this->nattrs = nattrs; strcpy(this->gi, gi); p = this->gi; while(*p++); for(i=0; iattrs[i].name = p, attrs[i].name); while(*p++); strcpy(this->attrs[i].value = p, attrs[i].value); while(*p++); } return this; } static VOID Tag_free(this) Tag* this; { FREE(this->gi); FREE(this->attrs); } static Cons* cons(car, cdr, parent) VOIDPTR car; VOIDPTR cdr; Cons* parent; { Cons* this = NEW(Cons, 1); this->first = (Cons*)car; this->rest = (Cons*)cdr; this->up = parent; return this; } static VOID attach(this, element, data) HMDoc* this; Tag* element; CONST char* data; { Cons* it = cons(element, data); if(this->here){ Cons* cell = cons(it, 0, this->here->up); this->here->rest = cell; this->here = cell; }else{ this->root = this->here = it; } } static int startTag(this, gi, attributes, nattrs) HMDoc* this; CONST char* gi; CONST HMBinding attributes[]; int nattrs; { int c = HTML_content(gi); Tag* nt = Tag_new(gi, c, attributes, nattrs); /* content? @@*/ attach(this, nt, 0); return c; } static VOID endTag(this, gi) HMDoc* this; CONST char* gi; { if(this->here && this->here->up) this->here = this->here->up; } static VOID data(this, data, qty) HMDoc* this; CONST char* data; int qty; { if(this->here){ char* nd = NEW(char, qty+sizeof(int)); *((int*)nd) = qty; memcpy(nd + sizeof(int), data, qty); attach(this, 0, nd); } } /* traverse the document */ static VOID element_traverse(this, dest, docclass) Cons* this; HMDoc* dest; HMDoc_Class* docclass; { Cons* c; if(this->first){ Tag* t = (Tag*)(this->first); (docclass->startTag)(dest, t->gi, t->attrs, t->nattrs); if(t->content != SGML_EMPTY){ for(c = this->rest; c; c = c->rest) element_traverse(c->first, dest, docclass); (docclass->endTag)(dest, t->gi); } }else{ int q = *((int*)(this->rest)); char* d = ((char*)(this->rest)) + sizeof(int); (docclass->data)(dest, d, q); } } VOID InCore_traverse(this, that, c) HMDoc* this; HMDoc* that; HMDoc_Class* c; { element_traverse(this->root, that, c); }