
new design:


make a document structure for each type of document. then, provide backends
for them in a generic way. this provides the seperation between the 
content generator and the document preparer. i.e. you don't need to re-compile
any code when you change the layout of the document. it should also be easy 
to insert custom marked-up text into the final document.

items in a document:

1- fields that always exist. A title is a good example
2- fields that optionally exist. A check mark is an example
3- fields that are list items.
4- fields that are choose-one. 

so, a document template is just how the final document will look with
the styles also embedded in. there will be another 'declaration file' which
will determine how they are to be programmed.


sample html document template:

<html> <body> <h2> {Title} </h2> <p> 
Here are the items in your basket:
<ul> <li> {Instock-item} </li> <li> {Undetermined-item} </li> </ul>

<p> <a href="/addbonus-custid={bonus-custid}"> Click here to add bonus points
to your balance </a> </p>
</body> </html>


the declaration file may be:

<document name="checkout_1">
<string name=title html.cut=parent(h2,Title)/>
<list name=basket html.cut=parent(ul,instock_item)>
	<struct name=instock_item html.cut=parent(li,instock_item)>
		<string name=name html.cut=cdata(name)>
		<integer name=value html.cut=cdata(value)>
	</struct>
	<struct name=undetermind_item html.cut=parent(li,undetermined_item)>
		<string name=name html.cut=cdata(name)>
	</struct>
</list>
<string name=bonus html.cut=parent(p,bonus_custid)/>
</document>

the document will be:


struct document {
	char *title;
	struct document_basket_elem {
		struct document_basket_elem *prev, *next;
		enum { instock_item, undetermined_item } type;
		union { 
			struct instock_item {
				char *name;
				int value;
			} instock_item;
			struct undetermined_item {
				char *name;
			} undetermined_item;
		} data;
	} * basket;
	char *bonus;
};



<html><body>
<form name="setfilter" action="/filter" method="get">
<table> 
<tr>
	<td> <b> Filter:</b></td>
	<td> <input type="text" name="query" value="{query}"> </td>
	<td> <input type="submit" name="filter" value="filter"> </td>
</tr></table>
</form>
<p> <a href="/filterhelp">help on filters</a> </p>
<br>
<table cellspacing=5 cellpadding=5>
<tr>
	<td><b> Date</b></td>
	<td><b>Description</b></td>
</tr>
<tr> <td colspan=2>
		<b>{record:(tr}Tags: </b> {tag*}
		<a href=/addtag-recno={recno}><b>new tag</b></a>
</td> </tr>
<tr> <td> {date}</td> <td>{description} </td></tr>
</table>
</body>
</html>

{todo:parent(query,html)}
{records:parent(date,table)}
{record:parent(tag,tr),parent(date,tr)}
{entry:parent(date,tr)}


-->
	todo:
		query
		records
			record
				tag
				recno
				entry
					date
					description

todo.query.set something

x= todo.records.record.dup
x.tag.dup.set(done)
x.tag.dup.set(features)
x.tag.dup.set(whatever)
y= x.entry.dup
y.date.set(somedate)
y.description.set(somedescription)

struct {
	Node data;
	Node query;
	struct {
		Node data;
		struct  {
			Node data;
			Node tag;
			Node recno;
			struct {
				Node data;
				Node date;
				Node description;
			} entry
		} record;
	} records;
} todo;

dup will:
	find the beginning and end of the dup()'d element.
	find the closest ancestor
	make a copy of the data and the nodes
	insert the copy as the last child of the ancestor

dupat will:
	find the beginning and end of the dup()'d element.
	make a copy of the data and the nodes
	find the position named
	insert the copy at the position

set will:
	change the value of the string at the given node

new design.. the very last, ok?

rather than manipulating a tree structure which requires a lot of blocks
and similar things

1- make a seperate 'content only' document,
2- based on the XML template, output the document contents. with the order in
   the XML document and the structure in the structure description.
3- where to put the structure?
	the data structure in a seperate file, which will be used to create 
	the C data structure.
	the xml structure inside the related xml template. this way, the general
	structure description does not include anything specific to a file format.


so, for the todo document:

{todo:parent(query,html)}
{records:parent(date,table)}
{record:parent(tag,tr),parent(date,tr)}
{entry:parent(date,tr)}

STRUCT(todo)
	STRING(query)
	LIST(records)  /* any of the following */
		STRUCT(record)
			LIST(tags)
				STRING(tag)
			END
			LIST(entries)
				STRUCT(entry)
					STRING(date)
					STRING(descr)
				END
			END
		END
	END
END

this shall translate into:

order fields

print until query..
if z.query then 
	print(z.query)
end
if z.records and getn(z.records)!=0 then
	print header of list
	a= z.records
	if a.type=="abc" then
		print abc
	elsif a.type=="def" then
		print def
	end
end

we want code like:

x.y = z  -- without allocation neither x or z
k= new_item(x.y,"abc") -- add a new item to x.y -- alternative is an abc
k.uu= v

STRUCT(todo)
	STRING(query)
	LIST(records)  /* any of the following */
		STRUCT(record)
			LIST(tags)
				STRING(tag)
			END
			LIST(entries)
				STRUCT(entry)
					STRING(date)
					STRING(descr)
				END
			END
		END
	END
END


void lua_getfield( lua_State *lua, int index, char *name) {
	lua_pushstring(lua,name);
	lua_gettable(lua,index-1);
}

void lua_iterate(lua_State *lua) { /* iterates the topmost list */
	lua_getfield(lua,-1,"next");
	lua_remove(-2);
}

x_to_html( lua_State *lua ) {
	FSTREAM *f;
	f= lua_getptr(lua,-2);
	lua_getfield(lua,-1,"query");
	{ char *c= lua_tostring(-1); swrite(f,c); lua_pop(1); }
	lua_getfield(lua,-1,"records");
	while(!lua_table_empty_nil(lua)) { /* pops it automatically if so */
		lua_getfield(lua,-1,"record");
		if (!lua_table_empty_nil(lua)) {
			lua_getfield(lua,-1,"tags");
			while(!lua_table_empty_nil(lua)) {
				lua_getfield(lua,-1,"tag");
				if (!lua_isnilp(lua,-1))
					out_str(lua_tostringp(lua,-1));
				lua_iterate(lua);
			}
			lua_pop(1);
		}
	}
}

struct:
	if (!nilp) {
--		for each field:
			getfield(name)
			if (!nilp) {
				format(field)
				popfield
			}
		pop1
	}

list:
	while(!nilp) {
--		for each alternative
			getfield(name)
			if(!nilp) {
				format(field)
				popfield
				goto end_x
			}
			getfield(name2)
			if (!nilp) {
				..
			}

		end_x:
			lua_getfield(next)
			lua_remove(-2)
	}

string:
	output_string
integer:
	output_integer

each variable has a stack depth: the number of the containing struct on stack
when an alias is found, it uses the stack depth of the aliased element.

stack:

[ table stream ] [ top_struct list_or_struct list_or_struct ... ]

so, numbers will start from 2 and increase..
	elements of top_struct will have stack=2
		elements of elements of top_struct will have stack=3 etc.

