19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <String.h>
59a747e4fSDavid du Colombier #include <thread.h>
69a747e4fSDavid du Colombier #include "wiki.h"
79a747e4fSDavid du Colombier
89a747e4fSDavid du Colombier /*
99a747e4fSDavid du Colombier * Get HTML and text templates from underlying file system.
106b6b9ac8SDavid du Colombier * Caches them, which means changes don't take effect for
119a747e4fSDavid du Colombier * up to Tcache seconds after they are made.
129a747e4fSDavid du Colombier *
139a747e4fSDavid du Colombier * If the files are deleted, we keep returning the last
149a747e4fSDavid du Colombier * known copy.
159a747e4fSDavid du Colombier */
169a747e4fSDavid du Colombier enum {
179a747e4fSDavid du Colombier WAIT = 60
189a747e4fSDavid du Colombier };
199a747e4fSDavid du Colombier
209a747e4fSDavid du Colombier static char *name[2*Ntemplate] = {
219a747e4fSDavid du Colombier [Tpage] "page.html",
229a747e4fSDavid du Colombier [Tedit] "edit.html",
239a747e4fSDavid du Colombier [Tdiff] "diff.html",
249a747e4fSDavid du Colombier [Thistory] "history.html",
259a747e4fSDavid du Colombier [Tnew] "new.html",
269a747e4fSDavid du Colombier [Toldpage] "oldpage.html",
279a747e4fSDavid du Colombier [Twerror] "werror.html",
289a747e4fSDavid du Colombier [Ntemplate+Tpage] "page.txt",
299a747e4fSDavid du Colombier [Ntemplate+Tdiff] "diff.txt",
309a747e4fSDavid du Colombier [Ntemplate+Thistory] "history.txt",
319a747e4fSDavid du Colombier [Ntemplate+Toldpage] "oldpage.txt",
329a747e4fSDavid du Colombier [Ntemplate+Twerror] "werror.txt",
339a747e4fSDavid du Colombier };
349a747e4fSDavid du Colombier
359a747e4fSDavid du Colombier static struct {
369a747e4fSDavid du Colombier RWLock;
379a747e4fSDavid du Colombier String *s;
389a747e4fSDavid du Colombier ulong t;
399a747e4fSDavid du Colombier Qid qid;
409a747e4fSDavid du Colombier } cache[2*Ntemplate];
419a747e4fSDavid du Colombier
429a747e4fSDavid du Colombier static void
cacheinit(void)439a747e4fSDavid du Colombier cacheinit(void)
449a747e4fSDavid du Colombier {
459a747e4fSDavid du Colombier int i;
469a747e4fSDavid du Colombier static int x;
479a747e4fSDavid du Colombier static Lock l;
489a747e4fSDavid du Colombier
499a747e4fSDavid du Colombier if(x)
509a747e4fSDavid du Colombier return;
519a747e4fSDavid du Colombier lock(&l);
529a747e4fSDavid du Colombier if(x){
539a747e4fSDavid du Colombier unlock(&l);
549a747e4fSDavid du Colombier return;
559a747e4fSDavid du Colombier }
569a747e4fSDavid du Colombier
579a747e4fSDavid du Colombier for(i=0; i<2*Ntemplate; i++)
589a747e4fSDavid du Colombier if(name[i])
599a747e4fSDavid du Colombier cache[i].s = s_copy("");
609a747e4fSDavid du Colombier x = 1;
619a747e4fSDavid du Colombier unlock(&l);
629a747e4fSDavid du Colombier }
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier static String*
gettemplate(int type)659a747e4fSDavid du Colombier gettemplate(int type)
669a747e4fSDavid du Colombier {
679a747e4fSDavid du Colombier int n;
689a747e4fSDavid du Colombier Biobuf *b;
699a747e4fSDavid du Colombier Dir *d;
709a747e4fSDavid du Colombier String *s, *ns;
719a747e4fSDavid du Colombier
729a747e4fSDavid du Colombier if(name[type]==nil)
739a747e4fSDavid du Colombier return nil;
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier cacheinit();
769a747e4fSDavid du Colombier
779a747e4fSDavid du Colombier rlock(&cache[type]);
789a747e4fSDavid du Colombier if(0 && cache[type].t+Tcache >= time(0)){
799a747e4fSDavid du Colombier s = s_incref(cache[type].s);
809a747e4fSDavid du Colombier runlock(&cache[type]);
819a747e4fSDavid du Colombier return s;
829a747e4fSDavid du Colombier }
839a747e4fSDavid du Colombier runlock(&cache[type]);
849a747e4fSDavid du Colombier
859a747e4fSDavid du Colombier // d = nil;
869a747e4fSDavid du Colombier wlock(&cache[type]);
879a747e4fSDavid du Colombier if(0 && cache[type].t+Tcache >= time(0) || (d = wdirstat(name[type])) == nil)
889a747e4fSDavid du Colombier goto Return;
899a747e4fSDavid du Colombier
909a747e4fSDavid du Colombier if(0 && d->qid.vers == cache[type].qid.vers && d->qid.path == cache[type].qid.path){
919a747e4fSDavid du Colombier cache[type].t = time(0);
929a747e4fSDavid du Colombier goto Return;
939a747e4fSDavid du Colombier }
949a747e4fSDavid du Colombier
959a747e4fSDavid du Colombier if((b = wBopen(name[type], OREAD)) == nil)
969a747e4fSDavid du Colombier goto Return;
979a747e4fSDavid du Colombier
989a747e4fSDavid du Colombier ns = s_reset(nil);
99b7327ca2SDavid du Colombier do
100b7327ca2SDavid du Colombier n = s_read(b, ns, Bsize);
101b7327ca2SDavid du Colombier while(n > 0);
1029a747e4fSDavid du Colombier Bterm(b);
103*1052a86aSDavid du Colombier if(n < 0) {
104*1052a86aSDavid du Colombier s_free(ns);
1059a747e4fSDavid du Colombier goto Return;
106*1052a86aSDavid du Colombier }
1079a747e4fSDavid du Colombier
1089a747e4fSDavid du Colombier s_free(cache[type].s);
1099a747e4fSDavid du Colombier cache[type].s = ns;
1109a747e4fSDavid du Colombier cache[type].qid = d->qid;
1119a747e4fSDavid du Colombier cache[type].t = time(0);
1129a747e4fSDavid du Colombier
1139a747e4fSDavid du Colombier Return:
1149a747e4fSDavid du Colombier free(d);
1159a747e4fSDavid du Colombier s = s_incref(cache[type].s);
1169a747e4fSDavid du Colombier wunlock(&cache[type]);
1179a747e4fSDavid du Colombier return s;
1189a747e4fSDavid du Colombier }
1199a747e4fSDavid du Colombier
1209a747e4fSDavid du Colombier
1219a747e4fSDavid du Colombier /*
1229a747e4fSDavid du Colombier * Write wiki document in HTML.
1239a747e4fSDavid du Colombier */
1249a747e4fSDavid du Colombier static String*
s_escappend(String * s,char * p,int pre)1259a747e4fSDavid du Colombier s_escappend(String *s, char *p, int pre)
1269a747e4fSDavid du Colombier {
1279a747e4fSDavid du Colombier char *q;
1289a747e4fSDavid du Colombier
1299a747e4fSDavid du Colombier while(q = strpbrk(p, pre ? "<>&" : " <>&")){
1309a747e4fSDavid du Colombier s = s_nappend(s, p, q-p);
1319a747e4fSDavid du Colombier switch(*q){
1329a747e4fSDavid du Colombier case '<':
1339a747e4fSDavid du Colombier s = s_append(s, "<");
1349a747e4fSDavid du Colombier break;
1359a747e4fSDavid du Colombier case '>':
1369a747e4fSDavid du Colombier s = s_append(s, ">");
1379a747e4fSDavid du Colombier break;
1389a747e4fSDavid du Colombier case '&':
1399a747e4fSDavid du Colombier s = s_append(s, "&");
1409a747e4fSDavid du Colombier break;
1419a747e4fSDavid du Colombier case ' ':
1429a747e4fSDavid du Colombier s = s_append(s, "\n");
1439a747e4fSDavid du Colombier }
1449a747e4fSDavid du Colombier p = q+1;
1459a747e4fSDavid du Colombier }
1469a747e4fSDavid du Colombier s = s_append(s, p);
1479a747e4fSDavid du Colombier return s;
1489a747e4fSDavid du Colombier }
1499a747e4fSDavid du Colombier
1509a747e4fSDavid du Colombier static char*
mkurl(char * s,int ty)1519a747e4fSDavid du Colombier mkurl(char *s, int ty)
1529a747e4fSDavid du Colombier {
1539a747e4fSDavid du Colombier char *p, *q;
1549a747e4fSDavid du Colombier
1559a747e4fSDavid du Colombier if(strncmp(s, "http:", 5)==0
15613ec2712SDavid du Colombier || strncmp(s, "https:", 6)==0
15713ec2712SDavid du Colombier || strncmp(s, "#", 1)==0
1589a747e4fSDavid du Colombier || strncmp(s, "ftp:", 4)==0
1599a747e4fSDavid du Colombier || strncmp(s, "mailto:", 7)==0
1609a747e4fSDavid du Colombier || strncmp(s, "telnet:", 7)==0
1619a747e4fSDavid du Colombier || strncmp(s, "file:", 5)==0)
1629a747e4fSDavid du Colombier return estrdup(s);
1639a747e4fSDavid du Colombier
1649a747e4fSDavid du Colombier if(strchr(s, ' ')==nil && strchr(s, '@')!=nil){
1659a747e4fSDavid du Colombier p = emalloc(strlen(s)+8);
1669a747e4fSDavid du Colombier strcpy(p, "mailto:");
1679a747e4fSDavid du Colombier strcat(p, s);
1689a747e4fSDavid du Colombier return p;
1699a747e4fSDavid du Colombier }
1709a747e4fSDavid du Colombier
1719a747e4fSDavid du Colombier if(ty == Toldpage)
1729a747e4fSDavid du Colombier p = smprint("../../%s", s);
1739a747e4fSDavid du Colombier else
1749a747e4fSDavid du Colombier p = smprint("../%s", s);
1759a747e4fSDavid du Colombier
1769a747e4fSDavid du Colombier for(q=p; *q; q++)
1779a747e4fSDavid du Colombier if(*q==' ')
1789a747e4fSDavid du Colombier *q = '_';
1799a747e4fSDavid du Colombier return p;
1809a747e4fSDavid du Colombier }
1819a747e4fSDavid du Colombier
182ed397113SDavid du Colombier int okayinlist[Nwtxt] =
183ed397113SDavid du Colombier {
184ed397113SDavid du Colombier [Wbullet] 1,
185ed397113SDavid du Colombier [Wlink] 1,
186ed397113SDavid du Colombier [Wman] 1,
187ed397113SDavid du Colombier [Wplain] 1,
188ed397113SDavid du Colombier };
189ed397113SDavid du Colombier
190ed397113SDavid du Colombier int okayinpre[Nwtxt] =
191ed397113SDavid du Colombier {
192ed397113SDavid du Colombier [Wlink] 1,
193ed397113SDavid du Colombier [Wman] 1,
194ed397113SDavid du Colombier [Wpre] 1,
195ed397113SDavid du Colombier };
196ed397113SDavid du Colombier
197ed397113SDavid du Colombier int okayinpara[Nwtxt] =
198ed397113SDavid du Colombier {
199ed397113SDavid du Colombier [Wpara] 1,
200ed397113SDavid du Colombier [Wlink] 1,
201ed397113SDavid du Colombier [Wman] 1,
202ed397113SDavid du Colombier [Wplain] 1,
203ed397113SDavid du Colombier };
204ed397113SDavid du Colombier
205ed397113SDavid du Colombier char*
nospaces(char * s)206ed397113SDavid du Colombier nospaces(char *s)
207ed397113SDavid du Colombier {
208ed397113SDavid du Colombier char *q;
209ed397113SDavid du Colombier s = strdup(s);
210ed397113SDavid du Colombier if(s == nil)
211ed397113SDavid du Colombier return nil;
212ed397113SDavid du Colombier for(q=s; *q; q++)
213ed397113SDavid du Colombier if(*q == ' ')
214ed397113SDavid du Colombier *q = '_';
215ed397113SDavid du Colombier return s;
216ed397113SDavid du Colombier }
217ed397113SDavid du Colombier
2189a747e4fSDavid du Colombier String*
pagehtml(String * s,Wpage * wtxt,int ty)2199a747e4fSDavid du Colombier pagehtml(String *s, Wpage *wtxt, int ty)
2209a747e4fSDavid du Colombier {
2219a747e4fSDavid du Colombier char *p, tmp[40];
222ed397113SDavid du Colombier int inlist, inpara, inpre, t, tnext;
2239a747e4fSDavid du Colombier Wpage *w;
2249a747e4fSDavid du Colombier
2259a747e4fSDavid du Colombier inlist = 0;
2269a747e4fSDavid du Colombier inpre = 0;
2279a747e4fSDavid du Colombier inpara = 0;
2289a747e4fSDavid du Colombier
2299a747e4fSDavid du Colombier for(w=wtxt; w; w=w->next){
230ed397113SDavid du Colombier t = w->type;
231ed397113SDavid du Colombier tnext = Whr;
232ed397113SDavid du Colombier if(w->next)
233ed397113SDavid du Colombier tnext = w->next->type;
2349a747e4fSDavid du Colombier
235ed397113SDavid du Colombier if(inlist && !okayinlist[t]){
2369a747e4fSDavid du Colombier inlist = 0;
237ed397113SDavid du Colombier s = s_append(s, "\n</li>\n</ul>\n");
2389a747e4fSDavid du Colombier }
239ed397113SDavid du Colombier if(inpre && !okayinpre[t]){
2409a747e4fSDavid du Colombier inpre = 0;
2419a747e4fSDavid du Colombier s = s_append(s, "</pre>\n");
2429a747e4fSDavid du Colombier }
243ed397113SDavid du Colombier
244ed397113SDavid du Colombier switch(t){
245ed397113SDavid du Colombier case Wheading:
246ed397113SDavid du Colombier p = nospaces(w->text);
247ed397113SDavid du Colombier s = s_appendlist(s,
248ed397113SDavid du Colombier "\n<a name=\"", p, "\" /><h3>",
249ed397113SDavid du Colombier w->text, "</h3>\n", nil);
250ed397113SDavid du Colombier free(p);
251ed397113SDavid du Colombier break;
252ed397113SDavid du Colombier
253ed397113SDavid du Colombier case Wpara:
254ed397113SDavid du Colombier if(inpara){
255ed397113SDavid du Colombier s = s_append(s, "\n</p>\n");
256ed397113SDavid du Colombier inpara = 0;
257ed397113SDavid du Colombier }
258ed397113SDavid du Colombier if(okayinpara[tnext]){
259ed397113SDavid du Colombier s = s_append(s, "\n<p class='para'>\n");
2609a747e4fSDavid du Colombier inpara = 1;
2619a747e4fSDavid du Colombier }
2629a747e4fSDavid du Colombier break;
2639a747e4fSDavid du Colombier
2649a747e4fSDavid du Colombier case Wbullet:
2659a747e4fSDavid du Colombier if(!inlist){
2669a747e4fSDavid du Colombier inlist = 1;
2679a747e4fSDavid du Colombier s = s_append(s, "\n<ul>\n");
268ed397113SDavid du Colombier }else
269ed397113SDavid du Colombier s = s_append(s, "\n</li>\n");
2709a747e4fSDavid du Colombier s = s_append(s, "\n<li>\n");
2719a747e4fSDavid du Colombier break;
2729a747e4fSDavid du Colombier
2739a747e4fSDavid du Colombier case Wlink:
2749a747e4fSDavid du Colombier if(w->url == nil)
2759a747e4fSDavid du Colombier p = mkurl(w->text, ty);
2769a747e4fSDavid du Colombier else
2779a747e4fSDavid du Colombier p = w->url;
2789a747e4fSDavid du Colombier s = s_appendlist(s, "<a href=\"", p, "\">", nil);
2799a747e4fSDavid du Colombier s = s_escappend(s, w->text, 0);
2809a747e4fSDavid du Colombier s = s_append(s, "</a>");
2819a747e4fSDavid du Colombier if(w->url == nil)
2829a747e4fSDavid du Colombier free(p);
2839a747e4fSDavid du Colombier break;
2849a747e4fSDavid du Colombier
2859a747e4fSDavid du Colombier case Wman:
2869a747e4fSDavid du Colombier sprint(tmp, "%d", w->section);
2879a747e4fSDavid du Colombier s = s_appendlist(s,
2889a747e4fSDavid du Colombier "<a href=\"http://plan9.bell-labs.com/magic/man2html/",
2899a747e4fSDavid du Colombier tmp, "/", w->text, "\"><i>", w->text, "</i>(",
2909a747e4fSDavid du Colombier tmp, ")</a>", nil);
2919a747e4fSDavid du Colombier break;
2929a747e4fSDavid du Colombier
2939a747e4fSDavid du Colombier case Wpre:
2949a747e4fSDavid du Colombier if(!inpre){
2959a747e4fSDavid du Colombier inpre = 1;
2969a747e4fSDavid du Colombier s = s_append(s, "\n<pre>\n");
2979a747e4fSDavid du Colombier }
2989a747e4fSDavid du Colombier s = s_escappend(s, w->text, 1);
2999a747e4fSDavid du Colombier s = s_append(s, "\n");
3009a747e4fSDavid du Colombier break;
3019a747e4fSDavid du Colombier
30213ec2712SDavid du Colombier case Whr:
30313ec2712SDavid du Colombier s = s_append(s, "<hr />");
30413ec2712SDavid du Colombier break;
30513ec2712SDavid du Colombier
3069a747e4fSDavid du Colombier case Wplain:
3079a747e4fSDavid du Colombier s = s_escappend(s, w->text, 0);
3089a747e4fSDavid du Colombier break;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier }
3119a747e4fSDavid du Colombier if(inlist)
312ed397113SDavid du Colombier s = s_append(s, "\n</li>\n</ul>\n");
3139a747e4fSDavid du Colombier if(inpre)
3149a747e4fSDavid du Colombier s = s_append(s, "</pre>\n");
315ed397113SDavid du Colombier if(inpara)
316ed397113SDavid du Colombier s = s_append(s, "\n</p>\n");
3179a747e4fSDavid du Colombier return s;
3189a747e4fSDavid du Colombier }
3199a747e4fSDavid du Colombier
3209a747e4fSDavid du Colombier static String*
copythru(String * s,char ** newp,int * nlinep,int l)3219a747e4fSDavid du Colombier copythru(String *s, char **newp, int *nlinep, int l)
3229a747e4fSDavid du Colombier {
3239a747e4fSDavid du Colombier char *oq, *q, *r;
3249a747e4fSDavid du Colombier int ol;
3259a747e4fSDavid du Colombier
3269a747e4fSDavid du Colombier q = *newp;
3279a747e4fSDavid du Colombier oq = q;
3289a747e4fSDavid du Colombier ol = *nlinep;
3299a747e4fSDavid du Colombier while(ol < l){
3309a747e4fSDavid du Colombier if(r = strchr(q, '\n'))
3319a747e4fSDavid du Colombier q = r+1;
3329a747e4fSDavid du Colombier else{
3339a747e4fSDavid du Colombier q += strlen(q);
3349a747e4fSDavid du Colombier break;
3359a747e4fSDavid du Colombier }
3369a747e4fSDavid du Colombier ol++;
3379a747e4fSDavid du Colombier }
3389a747e4fSDavid du Colombier if(*nlinep < l)
3399a747e4fSDavid du Colombier *nlinep = l;
3409a747e4fSDavid du Colombier *newp = q;
3419a747e4fSDavid du Colombier return s_nappend(s, oq, q-oq);
3429a747e4fSDavid du Colombier }
3439a747e4fSDavid du Colombier
3449a747e4fSDavid du Colombier static int
dodiff(char * f1,char * f2)3459a747e4fSDavid du Colombier dodiff(char *f1, char *f2)
3469a747e4fSDavid du Colombier {
3479a747e4fSDavid du Colombier int p[2];
3489a747e4fSDavid du Colombier
3499a747e4fSDavid du Colombier if(pipe(p) < 0){
3509a747e4fSDavid du Colombier return -1;
3519a747e4fSDavid du Colombier }
3529a747e4fSDavid du Colombier
3539a747e4fSDavid du Colombier switch(fork()){
3549a747e4fSDavid du Colombier case -1:
3559a747e4fSDavid du Colombier return -1;
3569a747e4fSDavid du Colombier
3579a747e4fSDavid du Colombier case 0:
3589a747e4fSDavid du Colombier close(p[0]);
3599a747e4fSDavid du Colombier dup(p[1], 1);
3609a747e4fSDavid du Colombier execl("/bin/diff", "diff", f1, f2, nil);
3619a747e4fSDavid du Colombier _exits(nil);
3629a747e4fSDavid du Colombier }
3639a747e4fSDavid du Colombier close(p[1]);
3649a747e4fSDavid du Colombier return p[0];
3659a747e4fSDavid du Colombier }
3669a747e4fSDavid du Colombier
3679a747e4fSDavid du Colombier
3689a747e4fSDavid du Colombier /* print document i grayed out, with only diffs relative to j in black */
3699a747e4fSDavid du Colombier static String*
s_diff(String * s,Whist * h,int i,int j)3709a747e4fSDavid du Colombier s_diff(String *s, Whist *h, int i, int j)
3719a747e4fSDavid du Colombier {
3729a747e4fSDavid du Colombier char *p, *q, *pnew;
3739a747e4fSDavid du Colombier int fdiff, fd1, fd2, n1, n2;
3749a747e4fSDavid du Colombier Biobuf b;
3759a747e4fSDavid du Colombier char fn1[40], fn2[40];
3769a747e4fSDavid du Colombier String *new, *old;
3779a747e4fSDavid du Colombier int nline;
3789a747e4fSDavid du Colombier
3799a747e4fSDavid du Colombier if(j < 0)
3809a747e4fSDavid du Colombier return pagehtml(s, h->doc[i].wtxt, Tpage);
3819a747e4fSDavid du Colombier
3829a747e4fSDavid du Colombier strcpy(fn1, "/tmp/wiki.XXXXXX");
3839a747e4fSDavid du Colombier strcpy(fn2, "/tmp/wiki.XXXXXX");
3849a747e4fSDavid du Colombier if((fd1 = opentemp(fn1)) < 0 || (fd2 = opentemp(fn2)) < 0){
3859a747e4fSDavid du Colombier close(fd1);
3869a747e4fSDavid du Colombier s = s_append(s, "\nopentemp failed; sorry\n");
3879a747e4fSDavid du Colombier return s;
3889a747e4fSDavid du Colombier }
3899a747e4fSDavid du Colombier
3909a747e4fSDavid du Colombier new = pagehtml(s_reset(nil), h->doc[i].wtxt, Tpage);
3919a747e4fSDavid du Colombier old = pagehtml(s_reset(nil), h->doc[j].wtxt, Tpage);
3929a747e4fSDavid du Colombier write(fd1, s_to_c(new), s_len(new));
3939a747e4fSDavid du Colombier write(fd2, s_to_c(old), s_len(old));
3949a747e4fSDavid du Colombier
3959a747e4fSDavid du Colombier fdiff = dodiff(fn2, fn1);
3969a747e4fSDavid du Colombier if(fdiff < 0)
3979a747e4fSDavid du Colombier s = s_append(s, "\ndiff failed; sorry\n");
3989a747e4fSDavid du Colombier else{
3999a747e4fSDavid du Colombier nline = 0;
4009a747e4fSDavid du Colombier pnew = s_to_c(new);
4019a747e4fSDavid du Colombier Binit(&b, fdiff, OREAD);
4029a747e4fSDavid du Colombier while(p = Brdline(&b, '\n')){
4039a747e4fSDavid du Colombier if(p[0]=='<' || p[0]=='>' || p[0]=='-')
4049a747e4fSDavid du Colombier continue;
4059a747e4fSDavid du Colombier p[Blinelen(&b)-1] = '\0';
406e9ec4e8fSDavid du Colombier if((p = strpbrk(p, "acd")) == nil)
4079a747e4fSDavid du Colombier continue;
408e9ec4e8fSDavid du Colombier n1 = atoi(p+1);
409e9ec4e8fSDavid du Colombier if(q = strchr(p, ','))
4109a747e4fSDavid du Colombier n2 = atoi(q+1);
4119a747e4fSDavid du Colombier else
4129a747e4fSDavid du Colombier n2 = n1;
413e9ec4e8fSDavid du Colombier switch(*p){
414ed397113SDavid du Colombier case 'a':
415ed397113SDavid du Colombier case 'c':
416ed397113SDavid du Colombier s = s_append(s, "<span class='old_text'>");
4179a747e4fSDavid du Colombier s = copythru(s, &pnew, &nline, n1-1);
418ed397113SDavid du Colombier s = s_append(s, "</span><span class='new_text'>");
4199a747e4fSDavid du Colombier s = copythru(s, &pnew, &nline, n2);
420ed397113SDavid du Colombier s = s_append(s, "</span>");
4219a747e4fSDavid du Colombier break;
4229a747e4fSDavid du Colombier }
4239a747e4fSDavid du Colombier }
4249a747e4fSDavid du Colombier close(fdiff);
425ed397113SDavid du Colombier s = s_append(s, "<span class='old_text'>");
4269a747e4fSDavid du Colombier s = s_append(s, pnew);
427ed397113SDavid du Colombier s = s_append(s, "</span>");
428ed397113SDavid du Colombier
4299a747e4fSDavid du Colombier }
4309a747e4fSDavid du Colombier s_free(new);
4319a747e4fSDavid du Colombier s_free(old);
4329a747e4fSDavid du Colombier close(fd1);
4339a747e4fSDavid du Colombier close(fd2);
4349a747e4fSDavid du Colombier return s;
4359a747e4fSDavid du Colombier }
4369a747e4fSDavid du Colombier
4379a747e4fSDavid du Colombier static String*
diffhtml(String * s,Whist * h)4389a747e4fSDavid du Colombier diffhtml(String *s, Whist *h)
4399a747e4fSDavid du Colombier {
4409a747e4fSDavid du Colombier int i;
4419a747e4fSDavid du Colombier char tmp[50];
4429a747e4fSDavid du Colombier char *atime;
4439a747e4fSDavid du Colombier
4449a747e4fSDavid du Colombier for(i=h->ndoc-1; i>=0; i--){
445ed397113SDavid du Colombier s = s_append(s, "<hr /><div class='diff_head'>\n");
4469a747e4fSDavid du Colombier if(i==h->current)
4479a747e4fSDavid du Colombier sprint(tmp, "index.html");
4489a747e4fSDavid du Colombier else
4499a747e4fSDavid du Colombier sprint(tmp, "%lud", h->doc[i].time);
4509a747e4fSDavid du Colombier atime = ctime(h->doc[i].time);
4519a747e4fSDavid du Colombier atime[strlen(atime)-1] = '\0';
4529a747e4fSDavid du Colombier s = s_appendlist(s,
4539a747e4fSDavid du Colombier "<a href=\"", tmp, "\">",
4549a747e4fSDavid du Colombier atime, "</a>", nil);
4559a747e4fSDavid du Colombier if(h->doc[i].author)
4569a747e4fSDavid du Colombier s = s_appendlist(s, ", ", h->doc[i].author, nil);
4579a747e4fSDavid du Colombier if(h->doc[i].conflict)
4589a747e4fSDavid du Colombier s = s_append(s, ", conflicting write");
4599a747e4fSDavid du Colombier s = s_append(s, "\n");
4609a747e4fSDavid du Colombier if(h->doc[i].comment)
461ed397113SDavid du Colombier s = s_appendlist(s, "<br /><i>", h->doc[i].comment, "</i>\n", nil);
462ed397113SDavid du Colombier s = s_append(s, "</div><hr />");
4639a747e4fSDavid du Colombier s = s_diff(s, h, i, i-1);
4649a747e4fSDavid du Colombier }
4659a747e4fSDavid du Colombier s = s_append(s, "<hr>");
4669a747e4fSDavid du Colombier return s;
4679a747e4fSDavid du Colombier }
4689a747e4fSDavid du Colombier
4699a747e4fSDavid du Colombier static String*
historyhtml(String * s,Whist * h)4709a747e4fSDavid du Colombier historyhtml(String *s, Whist *h)
4719a747e4fSDavid du Colombier {
4729a747e4fSDavid du Colombier int i;
4739a747e4fSDavid du Colombier char tmp[40];
4749a747e4fSDavid du Colombier char *atime;
4759a747e4fSDavid du Colombier
4769a747e4fSDavid du Colombier s = s_append(s, "<ul>\n");
4779a747e4fSDavid du Colombier for(i=h->ndoc-1; i>=0; i--){
4789a747e4fSDavid du Colombier if(i==h->current)
4799a747e4fSDavid du Colombier sprint(tmp, "index.html");
4809a747e4fSDavid du Colombier else
4819a747e4fSDavid du Colombier sprint(tmp, "%lud", h->doc[i].time);
4829a747e4fSDavid du Colombier atime = ctime(h->doc[i].time);
4839a747e4fSDavid du Colombier atime[strlen(atime)-1] = '\0';
4849a747e4fSDavid du Colombier s = s_appendlist(s,
4859a747e4fSDavid du Colombier "<li><a href=\"", tmp, "\">",
4869a747e4fSDavid du Colombier atime, "</a>", nil);
4879a747e4fSDavid du Colombier if(h->doc[i].author)
4889a747e4fSDavid du Colombier s = s_appendlist(s, ", ", h->doc[i].author, nil);
4899a747e4fSDavid du Colombier if(h->doc[i].conflict)
4909a747e4fSDavid du Colombier s = s_append(s, ", conflicting write");
4919a747e4fSDavid du Colombier s = s_append(s, "\n");
4929a747e4fSDavid du Colombier if(h->doc[i].comment)
4939a747e4fSDavid du Colombier s = s_appendlist(s, "<br><i>", h->doc[i].comment, "</i>\n", nil);
4949a747e4fSDavid du Colombier }
4959a747e4fSDavid du Colombier s = s_append(s, "</ul>");
4969a747e4fSDavid du Colombier return s;
4979a747e4fSDavid du Colombier }
4989a747e4fSDavid du Colombier
4999a747e4fSDavid du Colombier String*
tohtml(Whist * h,Wdoc * d,int ty)5009a747e4fSDavid du Colombier tohtml(Whist *h, Wdoc *d, int ty)
5019a747e4fSDavid du Colombier {
5029a747e4fSDavid du Colombier char *atime;
5039a747e4fSDavid du Colombier char *p, *q, ver[40];
5049a747e4fSDavid du Colombier int nsub;
5059a747e4fSDavid du Colombier Sub sub[3];
5069a747e4fSDavid du Colombier String *s, *t;
5079a747e4fSDavid du Colombier
5089a747e4fSDavid du Colombier t = gettemplate(ty);
5099a747e4fSDavid du Colombier if(p = strstr(s_to_c(t), "PAGE"))
5109a747e4fSDavid du Colombier q = p+4;
5119a747e4fSDavid du Colombier else{
5129a747e4fSDavid du Colombier p = s_to_c(t)+s_len(t);
5139a747e4fSDavid du Colombier q = nil;
5149a747e4fSDavid du Colombier }
5159a747e4fSDavid du Colombier
5169a747e4fSDavid du Colombier nsub = 0;
5179a747e4fSDavid du Colombier if(h){
5189a747e4fSDavid du Colombier sub[nsub] = (Sub){ "TITLE", h->title };
5199a747e4fSDavid du Colombier nsub++;
5209a747e4fSDavid du Colombier }
5219a747e4fSDavid du Colombier if(d){
5229a747e4fSDavid du Colombier sprint(ver, "%lud", d->time);
5239a747e4fSDavid du Colombier sub[nsub] = (Sub){ "VERSION", ver };
5249a747e4fSDavid du Colombier nsub++;
5259a747e4fSDavid du Colombier atime = ctime(d->time);
5269a747e4fSDavid du Colombier atime[strlen(atime)-1] = '\0';
5279a747e4fSDavid du Colombier sub[nsub] = (Sub){ "DATE", atime };
5289a747e4fSDavid du Colombier nsub++;
5299a747e4fSDavid du Colombier }
5309a747e4fSDavid du Colombier
5319a747e4fSDavid du Colombier s = s_reset(nil);
5329a747e4fSDavid du Colombier s = s_appendsub(s, s_to_c(t), p-s_to_c(t), sub, nsub);
5339a747e4fSDavid du Colombier switch(ty){
5349a747e4fSDavid du Colombier case Tpage:
5359a747e4fSDavid du Colombier case Toldpage:
5369a747e4fSDavid du Colombier s = pagehtml(s, d->wtxt, ty);
5379a747e4fSDavid du Colombier break;
5389a747e4fSDavid du Colombier case Tedit:
5399a747e4fSDavid du Colombier s = pagetext(s, d->wtxt, 0);
5409a747e4fSDavid du Colombier break;
5419a747e4fSDavid du Colombier case Tdiff:
5429a747e4fSDavid du Colombier s = diffhtml(s, h);
5439a747e4fSDavid du Colombier break;
5449a747e4fSDavid du Colombier case Thistory:
5459a747e4fSDavid du Colombier s = historyhtml(s, h);
5469a747e4fSDavid du Colombier break;
5479a747e4fSDavid du Colombier case Tnew:
5489a747e4fSDavid du Colombier case Twerror:
5499a747e4fSDavid du Colombier break;
5509a747e4fSDavid du Colombier }
5519a747e4fSDavid du Colombier if(q)
5529a747e4fSDavid du Colombier s = s_appendsub(s, q, strlen(q), sub, nsub);
5539a747e4fSDavid du Colombier s_free(t);
5549a747e4fSDavid du Colombier return s;
5559a747e4fSDavid du Colombier }
5569a747e4fSDavid du Colombier
5579a747e4fSDavid du Colombier enum {
5589a747e4fSDavid du Colombier LINELEN = 70,
5599a747e4fSDavid du Colombier };
5609a747e4fSDavid du Colombier
5619a747e4fSDavid du Colombier static String*
s_appendbrk(String * s,char * p,char * prefix,int dosharp)5629a747e4fSDavid du Colombier s_appendbrk(String *s, char *p, char *prefix, int dosharp)
5639a747e4fSDavid du Colombier {
5649a747e4fSDavid du Colombier char *e, *w, *x;
5659a747e4fSDavid du Colombier int first, l;
566b7327ca2SDavid du Colombier Rune r;
5679a747e4fSDavid du Colombier
5689a747e4fSDavid du Colombier first = 1;
5699a747e4fSDavid du Colombier while(*p){
5709a747e4fSDavid du Colombier s = s_append(s, p);
5719a747e4fSDavid du Colombier e = strrchr(s_to_c(s), '\n');
5729a747e4fSDavid du Colombier if(e == nil)
5739a747e4fSDavid du Colombier e = s_to_c(s);
5749a747e4fSDavid du Colombier else
5759a747e4fSDavid du Colombier e++;
576b7327ca2SDavid du Colombier if(utflen(e) <= LINELEN)
5779a747e4fSDavid du Colombier break;
578b7327ca2SDavid du Colombier x = e; l=LINELEN;
579b7327ca2SDavid du Colombier while(l--)
580b7327ca2SDavid du Colombier x+=chartorune(&r, x);
581b7327ca2SDavid du Colombier x = strchr(x, ' ');
5829a747e4fSDavid du Colombier if(x){
5839a747e4fSDavid du Colombier *x = '\0';
5849a747e4fSDavid du Colombier w = strrchr(e, ' ');
5859a747e4fSDavid du Colombier *x = ' ';
5869a747e4fSDavid du Colombier }else
5879a747e4fSDavid du Colombier w = strrchr(e, ' ');
5889a747e4fSDavid du Colombier
5899a747e4fSDavid du Colombier if(w-s_to_c(s) < strlen(prefix))
5909a747e4fSDavid du Colombier break;
5919a747e4fSDavid du Colombier
5929a747e4fSDavid du Colombier x = estrdup(w+1);
5939a747e4fSDavid du Colombier *w = '\0';
5949a747e4fSDavid du Colombier s->ptr = w;
5959a747e4fSDavid du Colombier s_append(s, "\n");
5969a747e4fSDavid du Colombier if(dosharp)
5979a747e4fSDavid du Colombier s_append(s, "#");
5989a747e4fSDavid du Colombier s_append(s, prefix);
5999a747e4fSDavid du Colombier if(!first)
6009a747e4fSDavid du Colombier free(p);
6019a747e4fSDavid du Colombier first = 0;
6029a747e4fSDavid du Colombier p = x;
6039a747e4fSDavid du Colombier }
6049a747e4fSDavid du Colombier if(!first)
6059a747e4fSDavid du Colombier free(p);
6069a747e4fSDavid du Colombier return s;
6079a747e4fSDavid du Colombier }
6089a747e4fSDavid du Colombier
6099a747e4fSDavid du Colombier static void
s_endline(String * s,int dosharp)6109a747e4fSDavid du Colombier s_endline(String *s, int dosharp)
6119a747e4fSDavid du Colombier {
6129a747e4fSDavid du Colombier if(dosharp){
6139a747e4fSDavid du Colombier if(s->ptr == s->base+1 && s->ptr[-1] == '#')
6149a747e4fSDavid du Colombier return;
6159a747e4fSDavid du Colombier
6169a747e4fSDavid du Colombier if(s->ptr > s->base+1 && s->ptr[-1] == '#' && s->ptr[-2] == '\n')
6179a747e4fSDavid du Colombier return;
6189a747e4fSDavid du Colombier s_append(s, "\n#");
6199a747e4fSDavid du Colombier }else{
6209a747e4fSDavid du Colombier if(s->ptr > s->base+1 && s->ptr[-1] == '\n')
6219a747e4fSDavid du Colombier return;
6229a747e4fSDavid du Colombier s_append(s, "\n");
6239a747e4fSDavid du Colombier }
6249a747e4fSDavid du Colombier }
6259a747e4fSDavid du Colombier
6269a747e4fSDavid du Colombier String*
pagetext(String * s,Wpage * page,int dosharp)6279a747e4fSDavid du Colombier pagetext(String *s, Wpage *page, int dosharp)
6289a747e4fSDavid du Colombier {
6299a747e4fSDavid du Colombier int inlist, inpara;
6309a747e4fSDavid du Colombier char *prefix, *sharp, tmp[40];
6319a747e4fSDavid du Colombier String *t;
6329a747e4fSDavid du Colombier Wpage *w;
6339a747e4fSDavid du Colombier
6349a747e4fSDavid du Colombier inlist = 0;
6359a747e4fSDavid du Colombier inpara = 0;
6369a747e4fSDavid du Colombier prefix = "";
6379a747e4fSDavid du Colombier sharp = dosharp ? "#" : "";
6389a747e4fSDavid du Colombier s = s_append(s, sharp);
6399a747e4fSDavid du Colombier for(w=page; w; w=w->next){
6409a747e4fSDavid du Colombier switch(w->type){
6419a747e4fSDavid du Colombier case Wheading:
6429a747e4fSDavid du Colombier if(inlist){
6439a747e4fSDavid du Colombier prefix = "";
6449a747e4fSDavid du Colombier inlist = 0;
6459a747e4fSDavid du Colombier }
6469a747e4fSDavid du Colombier s_endline(s, dosharp);
6479a747e4fSDavid du Colombier if(!inpara){
6489a747e4fSDavid du Colombier inpara = 1;
6499a747e4fSDavid du Colombier s = s_appendlist(s, "\n", sharp, nil);
6509a747e4fSDavid du Colombier }
6519a747e4fSDavid du Colombier s = s_appendlist(s, w->text, "\n", sharp, "\n", sharp, nil);
6529a747e4fSDavid du Colombier break;
6539a747e4fSDavid du Colombier
6549a747e4fSDavid du Colombier case Wpara:
6559a747e4fSDavid du Colombier s_endline(s, dosharp);
6569a747e4fSDavid du Colombier if(inlist){
6579a747e4fSDavid du Colombier prefix = "";
6589a747e4fSDavid du Colombier inlist = 0;
6599a747e4fSDavid du Colombier }
6609a747e4fSDavid du Colombier if(!inpara){
6619a747e4fSDavid du Colombier inpara = 1;
6629a747e4fSDavid du Colombier s = s_appendlist(s, "\n", sharp, nil);
6639a747e4fSDavid du Colombier }
6649a747e4fSDavid du Colombier break;
6659a747e4fSDavid du Colombier
6669a747e4fSDavid du Colombier case Wbullet:
6679a747e4fSDavid du Colombier s_endline(s, dosharp);
6689a747e4fSDavid du Colombier if(!inlist)
6699a747e4fSDavid du Colombier inlist = 1;
6709a747e4fSDavid du Colombier if(inpara)
6719a747e4fSDavid du Colombier inpara = 0;
6729a747e4fSDavid du Colombier s = s_append(s, " *\t");
6739a747e4fSDavid du Colombier prefix = "\t";
6749a747e4fSDavid du Colombier break;
6759a747e4fSDavid du Colombier
6769a747e4fSDavid du Colombier case Wlink:
6779a747e4fSDavid du Colombier if(inpara)
6789a747e4fSDavid du Colombier inpara = 0;
6799a747e4fSDavid du Colombier t = s_append(s_copy("["), w->text);
6809a747e4fSDavid du Colombier if(w->url == nil)
6819a747e4fSDavid du Colombier t = s_append(t, "]");
6829a747e4fSDavid du Colombier else{
6839a747e4fSDavid du Colombier t = s_append(t, " | ");
6849a747e4fSDavid du Colombier t = s_append(t, w->url);
6859a747e4fSDavid du Colombier t = s_append(t, "]");
6869a747e4fSDavid du Colombier }
6879a747e4fSDavid du Colombier s = s_appendbrk(s, s_to_c(t), prefix, dosharp);
6889a747e4fSDavid du Colombier s_free(t);
6899a747e4fSDavid du Colombier break;
6909a747e4fSDavid du Colombier
6919a747e4fSDavid du Colombier case Wman:
6929a747e4fSDavid du Colombier if(inpara)
6939a747e4fSDavid du Colombier inpara = 0;
6949a747e4fSDavid du Colombier s = s_appendbrk(s, w->text, prefix, dosharp);
6959a747e4fSDavid du Colombier sprint(tmp, "(%d)", w->section);
6969a747e4fSDavid du Colombier s = s_appendbrk(s, tmp, prefix, dosharp);
6979a747e4fSDavid du Colombier break;
6989a747e4fSDavid du Colombier
6999a747e4fSDavid du Colombier case Wpre:
7009a747e4fSDavid du Colombier if(inlist){
7019a747e4fSDavid du Colombier prefix = "";
7029a747e4fSDavid du Colombier inlist = 0;
7039a747e4fSDavid du Colombier }
7049a747e4fSDavid du Colombier if(inpara)
7059a747e4fSDavid du Colombier inpara = 0;
7069a747e4fSDavid du Colombier s_endline(s, dosharp);
7079a747e4fSDavid du Colombier s = s_appendlist(s, "! ", w->text, "\n", sharp, nil);
7089a747e4fSDavid du Colombier break;
70913ec2712SDavid du Colombier case Whr:
71013ec2712SDavid du Colombier s_endline(s, dosharp);
71113ec2712SDavid du Colombier s = s_appendlist(s, "------------------------------------------------------ \n", sharp, nil);
71213ec2712SDavid du Colombier break;
7139a747e4fSDavid du Colombier
7149a747e4fSDavid du Colombier case Wplain:
7159a747e4fSDavid du Colombier if(inpara)
7169a747e4fSDavid du Colombier inpara = 0;
7179a747e4fSDavid du Colombier s = s_appendbrk(s, w->text, prefix, dosharp);
7189a747e4fSDavid du Colombier break;
7199a747e4fSDavid du Colombier }
7209a747e4fSDavid du Colombier }
7219a747e4fSDavid du Colombier s_endline(s, dosharp);
7229a747e4fSDavid du Colombier s->ptr--;
7239a747e4fSDavid du Colombier *s->ptr = '\0';
7249a747e4fSDavid du Colombier return s;
7259a747e4fSDavid du Colombier }
7269a747e4fSDavid du Colombier
7279a747e4fSDavid du Colombier static String*
historytext(String * s,Whist * h)7289a747e4fSDavid du Colombier historytext(String *s, Whist *h)
7299a747e4fSDavid du Colombier {
7309a747e4fSDavid du Colombier int i;
7319a747e4fSDavid du Colombier char tmp[40];
7329a747e4fSDavid du Colombier char *atime;
7339a747e4fSDavid du Colombier
7349a747e4fSDavid du Colombier for(i=h->ndoc-1; i>=0; i--){
7359a747e4fSDavid du Colombier if(i==h->current)
7369a747e4fSDavid du Colombier sprint(tmp, "[current]");
7379a747e4fSDavid du Colombier else
7389a747e4fSDavid du Colombier sprint(tmp, "[%lud/]", h->doc[i].time);
7399a747e4fSDavid du Colombier atime = ctime(h->doc[i].time);
7409a747e4fSDavid du Colombier atime[strlen(atime)-1] = '\0';
7419a747e4fSDavid du Colombier s = s_appendlist(s, " * ", tmp, " ", atime, nil);
7429a747e4fSDavid du Colombier if(h->doc[i].author)
7439a747e4fSDavid du Colombier s = s_appendlist(s, ", ", h->doc[i].author, nil);
7449a747e4fSDavid du Colombier if(h->doc[i].conflict)
7459a747e4fSDavid du Colombier s = s_append(s, ", conflicting write");
7469a747e4fSDavid du Colombier s = s_append(s, "\n");
7479a747e4fSDavid du Colombier if(h->doc[i].comment)
7489a747e4fSDavid du Colombier s = s_appendlist(s, "<i>", h->doc[i].comment, "</i>\n", nil);
7499a747e4fSDavid du Colombier }
7509a747e4fSDavid du Colombier return s;
7519a747e4fSDavid du Colombier }
7529a747e4fSDavid du Colombier
7539a747e4fSDavid du Colombier String*
totext(Whist * h,Wdoc * d,int ty)7549a747e4fSDavid du Colombier totext(Whist *h, Wdoc *d, int ty)
7559a747e4fSDavid du Colombier {
7569a747e4fSDavid du Colombier char *atime;
7579a747e4fSDavid du Colombier char *p, *q, ver[40];
7589a747e4fSDavid du Colombier int nsub;
7599a747e4fSDavid du Colombier Sub sub[3];
7609a747e4fSDavid du Colombier String *s, *t;
7619a747e4fSDavid du Colombier
7629a747e4fSDavid du Colombier t = gettemplate(Ntemplate+ty);
7639a747e4fSDavid du Colombier if(p = strstr(s_to_c(t), "PAGE"))
7649a747e4fSDavid du Colombier q = p+4;
7659a747e4fSDavid du Colombier else{
7669a747e4fSDavid du Colombier p = s_to_c(t)+s_len(t);
7679a747e4fSDavid du Colombier q = nil;
7689a747e4fSDavid du Colombier }
7699a747e4fSDavid du Colombier
7709a747e4fSDavid du Colombier nsub = 0;
7719a747e4fSDavid du Colombier if(h){
7729a747e4fSDavid du Colombier sub[nsub] = (Sub){ "TITLE", h->title };
7739a747e4fSDavid du Colombier nsub++;
7749a747e4fSDavid du Colombier }
7759a747e4fSDavid du Colombier if(d){
7769a747e4fSDavid du Colombier sprint(ver, "%lud", d->time);
7779a747e4fSDavid du Colombier sub[nsub] = (Sub){ "VERSION", ver };
7789a747e4fSDavid du Colombier nsub++;
7799a747e4fSDavid du Colombier atime = ctime(d->time);
7809a747e4fSDavid du Colombier atime[strlen(atime)-1] = '\0';
7819a747e4fSDavid du Colombier sub[nsub] = (Sub){ "DATE", atime };
7829a747e4fSDavid du Colombier nsub++;
7839a747e4fSDavid du Colombier }
7849a747e4fSDavid du Colombier
7859a747e4fSDavid du Colombier s = s_reset(nil);
7869a747e4fSDavid du Colombier s = s_appendsub(s, s_to_c(t), p-s_to_c(t), sub, nsub);
7879a747e4fSDavid du Colombier switch(ty){
7889a747e4fSDavid du Colombier case Tpage:
7899a747e4fSDavid du Colombier case Toldpage:
7909a747e4fSDavid du Colombier s = pagetext(s, d->wtxt, 0);
7919a747e4fSDavid du Colombier break;
7929a747e4fSDavid du Colombier case Thistory:
7939a747e4fSDavid du Colombier s = historytext(s, h);
7949a747e4fSDavid du Colombier break;
7959a747e4fSDavid du Colombier case Tnew:
7969a747e4fSDavid du Colombier case Twerror:
7979a747e4fSDavid du Colombier break;
7989a747e4fSDavid du Colombier }
7999a747e4fSDavid du Colombier if(q)
8009a747e4fSDavid du Colombier s = s_appendsub(s, q, strlen(q), sub, nsub);
8019a747e4fSDavid du Colombier s_free(t);
8029a747e4fSDavid du Colombier return s;
8039a747e4fSDavid du Colombier }
8049a747e4fSDavid du Colombier
8059a747e4fSDavid du Colombier String*
doctext(String * s,Wdoc * d)8069a747e4fSDavid du Colombier doctext(String *s, Wdoc *d)
8079a747e4fSDavid du Colombier {
8089a747e4fSDavid du Colombier char tmp[40];
8099a747e4fSDavid du Colombier
8109a747e4fSDavid du Colombier sprint(tmp, "D%lud", d->time);
8119a747e4fSDavid du Colombier s = s_append(s, tmp);
8129a747e4fSDavid du Colombier if(d->comment){
8139a747e4fSDavid du Colombier s = s_append(s, "\nC");
8149a747e4fSDavid du Colombier s = s_append(s, d->comment);
8159a747e4fSDavid du Colombier }
8169a747e4fSDavid du Colombier if(d->author){
8179a747e4fSDavid du Colombier s = s_append(s, "\nA");
8189a747e4fSDavid du Colombier s = s_append(s, d->author);
8199a747e4fSDavid du Colombier }
8209a747e4fSDavid du Colombier if(d->conflict)
8219a747e4fSDavid du Colombier s = s_append(s, "\nX");
8229a747e4fSDavid du Colombier s = s_append(s, "\n");
8239a747e4fSDavid du Colombier s = pagetext(s, d->wtxt, 1);
8249a747e4fSDavid du Colombier return s;
8259a747e4fSDavid du Colombier }
826