19a747e4fSDavid du Colombier #include "awiki.h"
29a747e4fSDavid du Colombier
39a747e4fSDavid du Colombier Wiki *wlist;
49a747e4fSDavid du Colombier
59a747e4fSDavid du Colombier void
link(Wiki * w)69a747e4fSDavid du Colombier link(Wiki *w)
79a747e4fSDavid du Colombier {
89a747e4fSDavid du Colombier if(w->linked)
99a747e4fSDavid du Colombier return;
109a747e4fSDavid du Colombier w->linked = 1;
119a747e4fSDavid du Colombier w->prev = nil;
129a747e4fSDavid du Colombier w->next = wlist;
139a747e4fSDavid du Colombier if(wlist)
149a747e4fSDavid du Colombier wlist->prev = w;
159a747e4fSDavid du Colombier wlist = w;
169a747e4fSDavid du Colombier }
179a747e4fSDavid du Colombier
189a747e4fSDavid du Colombier void
unlink(Wiki * w)199a747e4fSDavid du Colombier unlink(Wiki *w)
209a747e4fSDavid du Colombier {
219a747e4fSDavid du Colombier if(!w->linked)
229a747e4fSDavid du Colombier return;
239a747e4fSDavid du Colombier w->linked = 0;
249a747e4fSDavid du Colombier
259a747e4fSDavid du Colombier if(w->next)
269a747e4fSDavid du Colombier w->next->prev = w->prev;
279a747e4fSDavid du Colombier if(w->prev)
289a747e4fSDavid du Colombier w->prev->next = w->next;
299a747e4fSDavid du Colombier else
309a747e4fSDavid du Colombier wlist = w->next;
319a747e4fSDavid du Colombier
329a747e4fSDavid du Colombier w->next = nil;
339a747e4fSDavid du Colombier w->prev = nil;
349a747e4fSDavid du Colombier }
359a747e4fSDavid du Colombier
369a747e4fSDavid du Colombier void
wikiname(Window * w,char * name)379a747e4fSDavid du Colombier wikiname(Window *w, char *name)
389a747e4fSDavid du Colombier {
399a747e4fSDavid du Colombier char *p, *q;
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier p = emalloc(strlen(dir)+1+strlen(name)+1+1);
429a747e4fSDavid du Colombier strcpy(p, dir);
439a747e4fSDavid du Colombier strcat(p, "/");
449a747e4fSDavid du Colombier strcat(p, name);
459a747e4fSDavid du Colombier for(q=p; *q; q++)
469a747e4fSDavid du Colombier if(*q==' ')
479a747e4fSDavid du Colombier *q = '_';
489a747e4fSDavid du Colombier winname(w, p);
499a747e4fSDavid du Colombier free(p);
509a747e4fSDavid du Colombier }
519a747e4fSDavid du Colombier
529a747e4fSDavid du Colombier int
wikiput(Wiki * w)539a747e4fSDavid du Colombier wikiput(Wiki *w)
549a747e4fSDavid du Colombier {
559a747e4fSDavid du Colombier int fd, n;
569a747e4fSDavid du Colombier char buf[1024], *p;
579a747e4fSDavid du Colombier Biobuf *b;
589a747e4fSDavid du Colombier
599a747e4fSDavid du Colombier if((fd = open("new", ORDWR)) < 0){
609a747e4fSDavid du Colombier fprint(2, "Wiki: cannot open raw: %r\n");
619a747e4fSDavid du Colombier return -1;
629a747e4fSDavid du Colombier }
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier winopenbody(w->win, OREAD);
659a747e4fSDavid du Colombier b = w->win->body;
669a747e4fSDavid du Colombier if((p = Brdline(b, '\n'))==nil){
679a747e4fSDavid du Colombier Short:
689a747e4fSDavid du Colombier winclosebody(w->win);
699a747e4fSDavid du Colombier fprint(2, "Wiki: no data\n");
709a747e4fSDavid du Colombier close(fd);
719a747e4fSDavid du Colombier return -1;
729a747e4fSDavid du Colombier }
739a747e4fSDavid du Colombier write(fd, p, Blinelen(b));
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier snprint(buf, sizeof buf, "D%lud\n", w->time);
769a747e4fSDavid du Colombier if(email)
779a747e4fSDavid du Colombier snprint(buf+strlen(buf), sizeof(buf)-strlen(buf), "A%s\n", email);
789a747e4fSDavid du Colombier
799a747e4fSDavid du Colombier if(Bgetc(b) == '#'){
809a747e4fSDavid du Colombier p = Brdline(b, '\n');
819a747e4fSDavid du Colombier if(p == nil)
829a747e4fSDavid du Colombier goto Short;
839a747e4fSDavid du Colombier snprint(buf+strlen(buf), sizeof(buf)-strlen(buf), "C%s\n", p);
849a747e4fSDavid du Colombier }
859a747e4fSDavid du Colombier write(fd, buf, strlen(buf));
869a747e4fSDavid du Colombier write(fd, "\n\n", 2);
879a747e4fSDavid du Colombier
889a747e4fSDavid du Colombier while((n = Bread(b, buf, sizeof buf)) > 0)
899a747e4fSDavid du Colombier write(fd, buf, n);
909a747e4fSDavid du Colombier winclosebody(w->win);
919a747e4fSDavid du Colombier
929a747e4fSDavid du Colombier werrstr("");
939a747e4fSDavid du Colombier if((n=write(fd, "", 0)) != 0){
949a747e4fSDavid du Colombier fprint(2, "Wiki commit %lud %d %d: %r\n", w->time, fd, n);
959a747e4fSDavid du Colombier close(fd);
969a747e4fSDavid du Colombier return -1;
979a747e4fSDavid du Colombier }
989a747e4fSDavid du Colombier seek(fd, 0, 0);
9922a0222bSDavid du Colombier if((n = read(fd, buf, 300)) < 0){
1009a747e4fSDavid du Colombier fprint(2, "Wiki readback: %r\n");
1019a747e4fSDavid du Colombier close(fd);
1029a747e4fSDavid du Colombier return -1;
1039a747e4fSDavid du Colombier }
1049a747e4fSDavid du Colombier close(fd);
1059a747e4fSDavid du Colombier buf[n] = '\0';
10622a0222bSDavid du Colombier sprint(buf, "%s/", buf);
1079a747e4fSDavid du Colombier free(w->arg);
1089a747e4fSDavid du Colombier w->arg = estrdup(buf);
1099a747e4fSDavid du Colombier w->isnew = 0;
1109a747e4fSDavid du Colombier wikiget(w);
1119a747e4fSDavid du Colombier wikiname(w->win, w->arg);
1129a747e4fSDavid du Colombier return n;
1139a747e4fSDavid du Colombier }
1149a747e4fSDavid du Colombier
1159a747e4fSDavid du Colombier void
wikiget(Wiki * w)1169a747e4fSDavid du Colombier wikiget(Wiki *w)
1179a747e4fSDavid du Colombier {
1189a747e4fSDavid du Colombier char *p;
1199a747e4fSDavid du Colombier int fd, normal;
1209a747e4fSDavid du Colombier Biobuf *bin;
1219a747e4fSDavid du Colombier
1229a747e4fSDavid du Colombier fprint(w->win->ctl, "dirty\n");
1239a747e4fSDavid du Colombier
1249a747e4fSDavid du Colombier p = emalloc(strlen(w->arg)+8+1);
1259a747e4fSDavid du Colombier strcpy(p, w->arg);
1269a747e4fSDavid du Colombier normal = 1;
1279a747e4fSDavid du Colombier if(p[strlen(p)-1] == '/'){
1289a747e4fSDavid du Colombier normal = 0;
1299a747e4fSDavid du Colombier strcat(p, "current");
1309a747e4fSDavid du Colombier }else if(strlen(p)>8 && strcmp(p+strlen(p)-8, "/current")==0){
1319a747e4fSDavid du Colombier normal = 0;
1329a747e4fSDavid du Colombier w->arg[strlen(w->arg)-7] = '\0';
1339a747e4fSDavid du Colombier }
1349a747e4fSDavid du Colombier
1359a747e4fSDavid du Colombier if((fd = open(p, OREAD)) < 0){
1369a747e4fSDavid du Colombier fprint(2, "Wiki: cannot read %s: %r\n", p);
1379a747e4fSDavid du Colombier winclean(w->win);
1389a747e4fSDavid du Colombier return;
1399a747e4fSDavid du Colombier }
1409a747e4fSDavid du Colombier free(p);
1419a747e4fSDavid du Colombier
1429a747e4fSDavid du Colombier winopenbody(w->win, OWRITE);
1439a747e4fSDavid du Colombier bin = emalloc(sizeof(*bin));
1449a747e4fSDavid du Colombier Binit(bin, fd, OREAD);
1459a747e4fSDavid du Colombier
1469a747e4fSDavid du Colombier p = nil;
1479a747e4fSDavid du Colombier if(!normal){
1489a747e4fSDavid du Colombier if((p = Brdline(bin, '\n')) == nil){
1499a747e4fSDavid du Colombier fprint(2, "Wiki: cannot read title: %r\n");
1509a747e4fSDavid du Colombier winclean(w->win);
1519a747e4fSDavid du Colombier close(fd);
1529a747e4fSDavid du Colombier free(bin);
1539a747e4fSDavid du Colombier return;
1549a747e4fSDavid du Colombier }
1559a747e4fSDavid du Colombier p[Blinelen(bin)-1] = '\0';
1569a747e4fSDavid du Colombier }
1579a747e4fSDavid du Colombier /* clear window */
1589a747e4fSDavid du Colombier if(w->win->data < 0)
1599a747e4fSDavid du Colombier w->win->data = winopenfile(w->win, "data");
1609a747e4fSDavid du Colombier if(winsetaddr(w->win, ",", 0))
1619a747e4fSDavid du Colombier write(w->win->data, "", 0);
1629a747e4fSDavid du Colombier
1639a747e4fSDavid du Colombier if(!normal)
1649a747e4fSDavid du Colombier Bprint(w->win->body, "%s\n\n", p);
1659a747e4fSDavid du Colombier
1669a747e4fSDavid du Colombier while(p = Brdline(bin, '\n')){
1679a747e4fSDavid du Colombier p[Blinelen(bin)-1] = '\0';
1689a747e4fSDavid du Colombier if(normal)
1699a747e4fSDavid du Colombier Bprint(w->win->body, "%s\n", p);
1709a747e4fSDavid du Colombier else{
1719a747e4fSDavid du Colombier if(p[0]=='D')
1729a747e4fSDavid du Colombier w->time = strtoul(p+1, 0, 10);
1739a747e4fSDavid du Colombier else if(p[0]=='#')
1749a747e4fSDavid du Colombier Bprint(w->win->body, "%s\n", p+1);
1759a747e4fSDavid du Colombier }
1769a747e4fSDavid du Colombier }
1779a747e4fSDavid du Colombier winclean(w->win);
1789a747e4fSDavid du Colombier free(bin);
1799a747e4fSDavid du Colombier close(fd);
1809a747e4fSDavid du Colombier }
1819a747e4fSDavid du Colombier
1829a747e4fSDavid du Colombier static int
iscmd(char * s,char * cmd)1839a747e4fSDavid du Colombier iscmd(char *s, char *cmd)
1849a747e4fSDavid du Colombier {
1859a747e4fSDavid du Colombier int len;
1869a747e4fSDavid du Colombier
1879a747e4fSDavid du Colombier len = strlen(cmd);
1889a747e4fSDavid du Colombier return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n');
1899a747e4fSDavid du Colombier }
1909a747e4fSDavid du Colombier
1919a747e4fSDavid du Colombier static char*
skip(char * s,char * cmd)1929a747e4fSDavid du Colombier skip(char *s, char *cmd)
1939a747e4fSDavid du Colombier {
1949a747e4fSDavid du Colombier s += strlen(cmd);
1959a747e4fSDavid du Colombier while(*s==' ' || *s=='\t' || *s=='\n')
1969a747e4fSDavid du Colombier s++;
1979a747e4fSDavid du Colombier return s;
1989a747e4fSDavid du Colombier }
1999a747e4fSDavid du Colombier
2009a747e4fSDavid du Colombier int
wikiload(Wiki * w,char * arg)2019a747e4fSDavid du Colombier wikiload(Wiki *w, char *arg)
2029a747e4fSDavid du Colombier {
2039a747e4fSDavid du Colombier char *p, *q, *path, *addr;
2049a747e4fSDavid du Colombier int rv;
2059a747e4fSDavid du Colombier
2069a747e4fSDavid du Colombier p = nil;
2079a747e4fSDavid du Colombier if(arg[0] == '/')
2089a747e4fSDavid du Colombier path = arg;
2099a747e4fSDavid du Colombier else{
2109a747e4fSDavid du Colombier p = emalloc(strlen(w->arg)+1+strlen(arg)+1);
2119a747e4fSDavid du Colombier strcpy(p, w->arg);
2129a747e4fSDavid du Colombier if(q = strrchr(p, '/')){
2139a747e4fSDavid du Colombier ++q;
2149a747e4fSDavid du Colombier *q = '\0';
2159a747e4fSDavid du Colombier }else
2169a747e4fSDavid du Colombier *p = '\0';
2179a747e4fSDavid du Colombier strcat(p, arg);
2189a747e4fSDavid du Colombier cleanname(p);
2199a747e4fSDavid du Colombier path = p;
2209a747e4fSDavid du Colombier }
2219a747e4fSDavid du Colombier if(addr=strchr(path, ':'))
2229a747e4fSDavid du Colombier *addr++ = '\0';
2239a747e4fSDavid du Colombier
2249a747e4fSDavid du Colombier rv = wikiopen(path, addr)==0;
2259a747e4fSDavid du Colombier free(p);
2269a747e4fSDavid du Colombier if(rv)
2279a747e4fSDavid du Colombier return 1;
2289a747e4fSDavid du Colombier return wikiopen(arg, 0)==0;
2299a747e4fSDavid du Colombier }
2309a747e4fSDavid du Colombier
2319a747e4fSDavid du Colombier /* return 1 if handled, 0 otherwise */
2329a747e4fSDavid du Colombier int
wikicmd(Wiki * w,char * s)2339a747e4fSDavid du Colombier wikicmd(Wiki *w, char *s)
2349a747e4fSDavid du Colombier {
2359a747e4fSDavid du Colombier char *p;
2369a747e4fSDavid du Colombier s = skip(s, "");
2379a747e4fSDavid du Colombier
2389a747e4fSDavid du Colombier if(iscmd(s, "Del")){
2399a747e4fSDavid du Colombier if(windel(w->win, 0))
2409a747e4fSDavid du Colombier w->dead = 1;
2419a747e4fSDavid du Colombier return 1;
2429a747e4fSDavid du Colombier }
2439a747e4fSDavid du Colombier if(iscmd(s, "New")){
2449a747e4fSDavid du Colombier wikinew(skip(s, "New"));
2459a747e4fSDavid du Colombier return 1;
2469a747e4fSDavid du Colombier }
2479a747e4fSDavid du Colombier if(iscmd(s, "History"))
2489a747e4fSDavid du Colombier return wikiload(w, "history.txt");
2499a747e4fSDavid du Colombier if(iscmd(s, "Diff"))
2509a747e4fSDavid du Colombier return wikidiff(w);
2519a747e4fSDavid du Colombier if(iscmd(s, "Get")){
252*90630c3aSDavid du Colombier if(winisdirty(w->win) && !w->win->warned){
253*90630c3aSDavid du Colombier w->win->warned = 1;
2549a747e4fSDavid du Colombier fprint(2, "%s/%s modified\n", dir, w->arg);
255*90630c3aSDavid du Colombier }else{
256*90630c3aSDavid du Colombier w->win->warned = 0;
2579a747e4fSDavid du Colombier wikiget(w);
258*90630c3aSDavid du Colombier }
2599a747e4fSDavid du Colombier return 1;
2609a747e4fSDavid du Colombier }
2619a747e4fSDavid du Colombier if(iscmd(s, "Put")){
2629a747e4fSDavid du Colombier if((p=strchr(w->arg, '/')) && p[1]!='\0')
2639a747e4fSDavid du Colombier fprint(2, "%s/%s is read-only\n", dir, w->arg);
2649a747e4fSDavid du Colombier else
2659a747e4fSDavid du Colombier wikiput(w);
2669a747e4fSDavid du Colombier return 1;
2679a747e4fSDavid du Colombier }
2689a747e4fSDavid du Colombier return 0;
2699a747e4fSDavid du Colombier }
2709a747e4fSDavid du Colombier
2719a747e4fSDavid du Colombier /* need to expand selection more than default word */
2729a747e4fSDavid du Colombier static long
eval(Window * w,char * s,...)2739a747e4fSDavid du Colombier eval(Window *w, char *s, ...)
2749a747e4fSDavid du Colombier {
2759a747e4fSDavid du Colombier char buf[64];
2769a747e4fSDavid du Colombier va_list arg;
2779a747e4fSDavid du Colombier
2789a747e4fSDavid du Colombier va_start(arg, s);
2799a747e4fSDavid du Colombier vsnprint(buf, sizeof buf, s, arg);
2809a747e4fSDavid du Colombier va_end(arg);
2819a747e4fSDavid du Colombier
2829a747e4fSDavid du Colombier if(winsetaddr(w, buf, 1)==0)
2839a747e4fSDavid du Colombier return -1;
2849a747e4fSDavid du Colombier
2859a747e4fSDavid du Colombier if(pread(w->addr, buf, 24, 0) != 24)
2869a747e4fSDavid du Colombier return -1;
2879a747e4fSDavid du Colombier return strtol(buf, 0, 10);
2889a747e4fSDavid du Colombier }
2899a747e4fSDavid du Colombier
2909a747e4fSDavid du Colombier static int
getdot(Window * w,long * q0,long * q1)2919a747e4fSDavid du Colombier getdot(Window *w, long *q0, long *q1)
2929a747e4fSDavid du Colombier {
2939a747e4fSDavid du Colombier char buf[24];
2949a747e4fSDavid du Colombier
2959a747e4fSDavid du Colombier ctlprint(w->ctl, "addr=dot\n");
2969a747e4fSDavid du Colombier if(pread(w->addr, buf, 24, 0) != 24)
2979a747e4fSDavid du Colombier return -1;
2989a747e4fSDavid du Colombier *q0 = atoi(buf);
2999a747e4fSDavid du Colombier *q1 = atoi(buf+12);
3009a747e4fSDavid du Colombier return 0;
3019a747e4fSDavid du Colombier }
3029a747e4fSDavid du Colombier
3039a747e4fSDavid du Colombier static Event*
expand(Window * w,Event * e,Event * eacme)3049a747e4fSDavid du Colombier expand(Window *w, Event *e, Event *eacme)
3059a747e4fSDavid du Colombier {
3069a747e4fSDavid du Colombier long q0, q1, x;
3079a747e4fSDavid du Colombier
3089a747e4fSDavid du Colombier if(getdot(w, &q0, &q1)==0 && q0 <= e->q0 && e->q0 <= q1){
3099a747e4fSDavid du Colombier e->q0 = q0;
3109a747e4fSDavid du Colombier e->q1 = q1;
3119a747e4fSDavid du Colombier return e;
3129a747e4fSDavid du Colombier }
3139a747e4fSDavid du Colombier
3149a747e4fSDavid du Colombier q0 = eval(w, "#%lud-/\\[/", e->q0);
3159a747e4fSDavid du Colombier if(q0 < 0)
3169a747e4fSDavid du Colombier return eacme;
3179a747e4fSDavid du Colombier if(eval(w, "#%lud+/\\]/", q0) < e->q0) /* [ closes before us */
3189a747e4fSDavid du Colombier return eacme;
3199a747e4fSDavid du Colombier q1 = eval(w, "#%lud+/\\]/", e->q1);
3209a747e4fSDavid du Colombier if(q1 < 0)
3219a747e4fSDavid du Colombier return eacme;
3229a747e4fSDavid du Colombier if((x=eval(w, "#%lud-/\\[/", q1))==-1 || x > e->q1) /* ] opens after us */
3239a747e4fSDavid du Colombier return eacme;
3249a747e4fSDavid du Colombier e->q0 = q0+1;
3259a747e4fSDavid du Colombier e->q1 = q1;
3269a747e4fSDavid du Colombier return e;
3279a747e4fSDavid du Colombier }
3289a747e4fSDavid du Colombier
3299a747e4fSDavid du Colombier void
acmeevent(Wiki * wiki,Event * e)3309a747e4fSDavid du Colombier acmeevent(Wiki *wiki, Event *e)
3319a747e4fSDavid du Colombier {
3329a747e4fSDavid du Colombier Event *ea, *e2, *eq;
3339a747e4fSDavid du Colombier Window *w;
3349a747e4fSDavid du Colombier char *s, *t, *buf;
3359a747e4fSDavid du Colombier int na;
3369a747e4fSDavid du Colombier
3379a747e4fSDavid du Colombier w = wiki->win;
3389a747e4fSDavid du Colombier switch(e->c1){ /* origin of action */
3399a747e4fSDavid du Colombier default:
3409a747e4fSDavid du Colombier Unknown:
3419a747e4fSDavid du Colombier fprint(2, "unknown message %c%c\n", e->c1, e->c2);
3429a747e4fSDavid du Colombier break;
3439a747e4fSDavid du Colombier
3449a747e4fSDavid du Colombier case 'F': /* generated by our actions; ignore */
3459a747e4fSDavid du Colombier break;
3469a747e4fSDavid du Colombier
3479a747e4fSDavid du Colombier case 'E': /* write to body or tag; can't affect us */
348*90630c3aSDavid du Colombier break;
349*90630c3aSDavid du Colombier
3509a747e4fSDavid du Colombier case 'K': /* type away; we don't care */
3519a747e4fSDavid du Colombier if(e->c2 == 'I' || e->c2 == 'D')
352*90630c3aSDavid du Colombier w->warned = 0;
3539a747e4fSDavid du Colombier break;
3549a747e4fSDavid du Colombier
3559a747e4fSDavid du Colombier case 'M': /* mouse event */
3569a747e4fSDavid du Colombier switch(e->c2){ /* type of action */
3579a747e4fSDavid du Colombier case 'x': /* mouse: button 2 in tag */
3589a747e4fSDavid du Colombier case 'X': /* mouse: button 2 in body */
3599a747e4fSDavid du Colombier ea = nil;
3609a747e4fSDavid du Colombier //e2 = nil;
3619a747e4fSDavid du Colombier s = e->b;
3629a747e4fSDavid du Colombier if(e->flag & 2){ /* null string with non-null expansion */
3639a747e4fSDavid du Colombier e2 = recvp(w->cevent);
3649a747e4fSDavid du Colombier if(e->nb==0)
3659a747e4fSDavid du Colombier s = e2->b;
3669a747e4fSDavid du Colombier }
3679a747e4fSDavid du Colombier if(e->flag & 8){ /* chorded argument */
3689a747e4fSDavid du Colombier ea = recvp(w->cevent); /* argument */
3699a747e4fSDavid du Colombier na = ea->nb;
3709a747e4fSDavid du Colombier recvp(w->cevent); /* ignore origin */
3719a747e4fSDavid du Colombier }else
3729a747e4fSDavid du Colombier na = 0;
3739a747e4fSDavid du Colombier
3749a747e4fSDavid du Colombier /* append chorded arguments */
3759a747e4fSDavid du Colombier if(na){
3769a747e4fSDavid du Colombier t = emalloc(strlen(s)+1+na+1);
3779a747e4fSDavid du Colombier sprint(t, "%s %s", s, ea->b);
3789a747e4fSDavid du Colombier s = t;
3799a747e4fSDavid du Colombier }
3809a747e4fSDavid du Colombier /* if it's a known command, do it */
3819a747e4fSDavid du Colombier /* if it's a long message, it can't be for us anyway */
3829a747e4fSDavid du Colombier // DPRINT(2, "exec: %s\n", s);
3839a747e4fSDavid du Colombier if(!wikicmd(wiki, s)) /* send it back */
3849a747e4fSDavid du Colombier winwriteevent(w, e);
3859a747e4fSDavid du Colombier if(na)
3869a747e4fSDavid du Colombier free(s);
3879a747e4fSDavid du Colombier break;
3889a747e4fSDavid du Colombier
3899a747e4fSDavid du Colombier case 'l': /* mouse: button 3 in tag */
3909a747e4fSDavid du Colombier case 'L': /* mouse: button 3 in body */
3919a747e4fSDavid du Colombier //buf = nil;
3929a747e4fSDavid du Colombier eq = e;
3939a747e4fSDavid du Colombier if(e->flag & 2){ /* we do our own expansion for loads */
3949a747e4fSDavid du Colombier e2 = recvp(w->cevent);
3959a747e4fSDavid du Colombier eq = expand(w, eq, e2);
3969a747e4fSDavid du Colombier }
3979a747e4fSDavid du Colombier s = eq->b;
3989a747e4fSDavid du Colombier if(eq->q1>eq->q0 && eq->nb==0){
3999a747e4fSDavid du Colombier buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
4009a747e4fSDavid du Colombier winread(w, eq->q0, eq->q1, buf);
4019a747e4fSDavid du Colombier s = buf;
4029a747e4fSDavid du Colombier }
4039a747e4fSDavid du Colombier if(!wikiload(wiki, s))
4049a747e4fSDavid du Colombier winwriteevent(w, e);
4059a747e4fSDavid du Colombier break;
4069a747e4fSDavid du Colombier
4079a747e4fSDavid du Colombier case 'i': /* mouse: text inserted in tag */
4089a747e4fSDavid du Colombier case 'd': /* mouse: text deleted from tag */
4099a747e4fSDavid du Colombier break;
4109a747e4fSDavid du Colombier
4119a747e4fSDavid du Colombier case 'I': /* mouse: text inserted in body */
4129a747e4fSDavid du Colombier case 'D': /* mouse: text deleted from body */
413*90630c3aSDavid du Colombier w->warned = 0;
4149a747e4fSDavid du Colombier break;
4159a747e4fSDavid du Colombier
4169a747e4fSDavid du Colombier default:
4179a747e4fSDavid du Colombier goto Unknown;
4189a747e4fSDavid du Colombier }
4199a747e4fSDavid du Colombier }
4209a747e4fSDavid du Colombier }
4219a747e4fSDavid du Colombier
4229a747e4fSDavid du Colombier void
wikithread(void * v)4239a747e4fSDavid du Colombier wikithread(void *v)
4249a747e4fSDavid du Colombier {
4259a747e4fSDavid du Colombier char tmp[40];
4269a747e4fSDavid du Colombier Event *e;
4279a747e4fSDavid du Colombier Wiki *w;
4289a747e4fSDavid du Colombier
4299a747e4fSDavid du Colombier w = v;
4309a747e4fSDavid du Colombier
4319a747e4fSDavid du Colombier if(w->isnew){
4329a747e4fSDavid du Colombier sprint(tmp, "+new+%d", w->isnew);
4339a747e4fSDavid du Colombier wikiname(w->win, tmp);
4349a747e4fSDavid du Colombier if(w->arg){
4359a747e4fSDavid du Colombier winopenbody(w->win, OWRITE);
4369a747e4fSDavid du Colombier Bprint(w->win->body, "%s\n\n", w->arg);
4379a747e4fSDavid du Colombier }
4389a747e4fSDavid du Colombier winclean(w->win);
4399a747e4fSDavid du Colombier }else if(!w->special){
4409a747e4fSDavid du Colombier wikiget(w);
4419a747e4fSDavid du Colombier wikiname(w->win, w->arg);
4429a747e4fSDavid du Colombier if(w->addr)
4439a747e4fSDavid du Colombier winselect(w->win, w->addr, 1);
4449a747e4fSDavid du Colombier }
445*90630c3aSDavid du Colombier fprint(w->win->ctl, "menu\n");
446*90630c3aSDavid du Colombier wintagwrite(w->win, "Get History Diff New", 4+8+4+4);
447*90630c3aSDavid du Colombier winclean(w->win);
4489a747e4fSDavid du Colombier
4499a747e4fSDavid du Colombier while(!w->dead && (e = recvp(w->win->cevent)))
4509a747e4fSDavid du Colombier acmeevent(w, e);
4519a747e4fSDavid du Colombier
4529a747e4fSDavid du Colombier windormant(w->win);
4539a747e4fSDavid du Colombier unlink(w);
4549a747e4fSDavid du Colombier free(w->win);
4559a747e4fSDavid du Colombier free(w->arg);
4569a747e4fSDavid du Colombier free(w);
4579a747e4fSDavid du Colombier threadexits(nil);
4589a747e4fSDavid du Colombier }
4599a747e4fSDavid du Colombier
4609a747e4fSDavid du Colombier int
wikiopen(char * arg,char * addr)4619a747e4fSDavid du Colombier wikiopen(char *arg, char *addr)
4629a747e4fSDavid du Colombier {
4639a747e4fSDavid du Colombier Dir *d;
4649a747e4fSDavid du Colombier char *p;
4659a747e4fSDavid du Colombier Wiki *w;
4669a747e4fSDavid du Colombier
4679a747e4fSDavid du Colombier /*
4689a747e4fSDavid du Colombier if(arg==nil){
4699a747e4fSDavid du Colombier if(write(mapfd, title, strlen(title)) < 0
4709a747e4fSDavid du Colombier || seek(mapfd, 0, 0) < 0 || (n=read(mapfd, tmp, sizeof(tmp)-2)) < 0){
4719a747e4fSDavid du Colombier fprint(2, "Wiki: no page '%s' found: %r\n", title);
4729a747e4fSDavid du Colombier return -1;
4739a747e4fSDavid du Colombier }
4749a747e4fSDavid du Colombier if(tmp[n-1] == '\n')
4759a747e4fSDavid du Colombier tmp[--n] = '\0';
4769a747e4fSDavid du Colombier tmp[n++] = '/';
4779a747e4fSDavid du Colombier tmp[n] = '\0';
4789a747e4fSDavid du Colombier arg = tmp;
4799a747e4fSDavid du Colombier }
4809a747e4fSDavid du Colombier */
481e40528acSDavid du Colombier
482e40528acSDavid du Colombier /* replace embedded '\n' in links by ' ' */
483e40528acSDavid du Colombier for(p=arg; *p; p++)
484e40528acSDavid du Colombier if(*p=='\n')
485e40528acSDavid du Colombier *p = ' ';
486e40528acSDavid du Colombier
4879a747e4fSDavid du Colombier if(strncmp(arg, dir, strlen(dir))==0 && arg[strlen(dir)]=='/' && arg[strlen(dir)+1])
4889a747e4fSDavid du Colombier arg += strlen(dir)+1;
4899a747e4fSDavid du Colombier else if(arg[0] == '/')
4909a747e4fSDavid du Colombier return -1;
4919a747e4fSDavid du Colombier
4929a747e4fSDavid du Colombier if((d = dirstat(arg)) == nil)
4939a747e4fSDavid du Colombier return -1;
4949a747e4fSDavid du Colombier
4959a747e4fSDavid du Colombier if((d->mode&DMDIR) && arg[strlen(arg)-1] != '/'){
4969a747e4fSDavid du Colombier p = emalloc(strlen(arg)+2);
4979a747e4fSDavid du Colombier strcpy(p, arg);
4989a747e4fSDavid du Colombier strcat(p, "/");
4999a747e4fSDavid du Colombier arg = p;
5009a747e4fSDavid du Colombier }else if(!(d->mode&DMDIR) && arg[strlen(arg)-1]=='/'){
5019a747e4fSDavid du Colombier arg = estrdup(arg);
5029a747e4fSDavid du Colombier arg[strlen(arg)-1] = '\0';
5039a747e4fSDavid du Colombier }else
5049a747e4fSDavid du Colombier arg = estrdup(arg);
5059a747e4fSDavid du Colombier free(d);
5069a747e4fSDavid du Colombier
5079a747e4fSDavid du Colombier /* rewrite /current into / */
5089a747e4fSDavid du Colombier if(strlen(arg) > 8 && strcmp(arg+strlen(arg)-8, "/current")==0)
5099a747e4fSDavid du Colombier arg[strlen(arg)-8+1] = '\0';
5109a747e4fSDavid du Colombier
5119a747e4fSDavid du Colombier /* look for window already open */
5129a747e4fSDavid du Colombier for(w=wlist; w; w=w->next){
5139a747e4fSDavid du Colombier if(strcmp(w->arg, arg)==0){
5149a747e4fSDavid du Colombier ctlprint(w->win->ctl, "show\n");
5159a747e4fSDavid du Colombier return 0;
5169a747e4fSDavid du Colombier }
5179a747e4fSDavid du Colombier }
5189a747e4fSDavid du Colombier
5199a747e4fSDavid du Colombier w = emalloc(sizeof *w);
5209a747e4fSDavid du Colombier w->arg = arg;
5219a747e4fSDavid du Colombier w->addr = addr;
5229a747e4fSDavid du Colombier w->win = newwindow();
5239a747e4fSDavid du Colombier link(w);
5249a747e4fSDavid du Colombier
5259a747e4fSDavid du Colombier proccreate(wineventproc, w->win, STACK);
5269a747e4fSDavid du Colombier threadcreate(wikithread, w, STACK);
5279a747e4fSDavid du Colombier return 0;
5289a747e4fSDavid du Colombier }
5299a747e4fSDavid du Colombier
5309a747e4fSDavid du Colombier void
wikinew(char * arg)5319a747e4fSDavid du Colombier wikinew(char *arg)
5329a747e4fSDavid du Colombier {
5339a747e4fSDavid du Colombier static int n;
5349a747e4fSDavid du Colombier Wiki *w;
5359a747e4fSDavid du Colombier
5369a747e4fSDavid du Colombier w = emalloc(sizeof *w);
5379a747e4fSDavid du Colombier if(arg)
5389a747e4fSDavid du Colombier arg = estrdup(arg);
5399a747e4fSDavid du Colombier w->arg = arg;
5409a747e4fSDavid du Colombier w->win = newwindow();
5419a747e4fSDavid du Colombier w->isnew = ++n;
5429a747e4fSDavid du Colombier proccreate(wineventproc, w->win, STACK);
5439a747e4fSDavid du Colombier threadcreate(wikithread, w, STACK);
5449a747e4fSDavid du Colombier }
5459a747e4fSDavid du Colombier
5469a747e4fSDavid du Colombier typedef struct Diffarg Diffarg;
5479a747e4fSDavid du Colombier struct Diffarg {
5489a747e4fSDavid du Colombier Wiki *w;
5499a747e4fSDavid du Colombier char *dir;
5509a747e4fSDavid du Colombier };
5519a747e4fSDavid du Colombier
5529a747e4fSDavid du Colombier void
execdiff(void * v)5539a747e4fSDavid du Colombier execdiff(void *v)
5549a747e4fSDavid du Colombier {
5559a747e4fSDavid du Colombier char buf[64];
5569a747e4fSDavid du Colombier Diffarg *a;
5579a747e4fSDavid du Colombier
5589a747e4fSDavid du Colombier a = v;
5599a747e4fSDavid du Colombier
5609a747e4fSDavid du Colombier rfork(RFFDG);
5619a747e4fSDavid du Colombier close(0);
5629a747e4fSDavid du Colombier open("/dev/null", OREAD);
5639a747e4fSDavid du Colombier sprint(buf, "/mnt/wsys/%d/body", a->w->win->id);
5649a747e4fSDavid du Colombier close(1);
5659a747e4fSDavid du Colombier open(buf, OWRITE);
5669a747e4fSDavid du Colombier close(2);
5679a747e4fSDavid du Colombier open(buf, OWRITE);
5689a747e4fSDavid du Colombier sprint(buf, "/mnt/wsys/%d", a->w->win->id);
5699a747e4fSDavid du Colombier bind(buf, "/dev", MBEFORE);
5709a747e4fSDavid du Colombier
5719a747e4fSDavid du Colombier procexecl(nil, "/acme/wiki/wiki.diff", "wiki.diff", a->dir, nil);
5729a747e4fSDavid du Colombier }
5739a747e4fSDavid du Colombier
5749a747e4fSDavid du Colombier int
wikidiff(Wiki * w)5759a747e4fSDavid du Colombier wikidiff(Wiki *w)
5769a747e4fSDavid du Colombier {
5779a747e4fSDavid du Colombier Diffarg *d;
5789a747e4fSDavid du Colombier char *p, *q, *r;
5799a747e4fSDavid du Colombier Wiki *nw;
5809a747e4fSDavid du Colombier
5819a747e4fSDavid du Colombier p = emalloc(strlen(w->arg)+10);
5829a747e4fSDavid du Colombier strcpy(p, w->arg);
5839a747e4fSDavid du Colombier if(q = strchr(p, '/'))
5849a747e4fSDavid du Colombier *q = '\0';
5859a747e4fSDavid du Colombier r = estrdup(p);
5869a747e4fSDavid du Colombier strcat(p, "/+Diff");
5879a747e4fSDavid du Colombier
5889a747e4fSDavid du Colombier nw = emalloc(sizeof *w);
5899a747e4fSDavid du Colombier nw->arg = p;
5909a747e4fSDavid du Colombier nw->win = newwindow();
5919a747e4fSDavid du Colombier nw->special = 1;
5929a747e4fSDavid du Colombier
5939a747e4fSDavid du Colombier d = emalloc(sizeof(*d));
5949a747e4fSDavid du Colombier d->w = nw;
5959a747e4fSDavid du Colombier d->dir = r;
5969a747e4fSDavid du Colombier wikiname(nw->win, p);
5979a747e4fSDavid du Colombier proccreate(wineventproc, nw->win, STACK);
5989a747e4fSDavid du Colombier proccreate(execdiff, d, STACK);
5999a747e4fSDavid du Colombier threadcreate(wikithread, nw, STACK);
6009a747e4fSDavid du Colombier return 1;
6019a747e4fSDavid du Colombier }
6029a747e4fSDavid du Colombier
603