Rune* runestrrchr(Rune *s, Rune c) { Rune *r; if(c == 0) return runestrchr(s, 0); r = 0; while(s = runestrchr(s, c)) r = s++; return r; }
/* this is a HACK */ Rune* urlcombine(Rune *b, Rune *u) { Rune *p, *q, *sep, *s; Rune endrune[] = { L'?', L'#' }; int i, restore; if(u == nil) error("urlcombine: u == nil"); if(validurl(u)) return erunestrdup(u); if(b==nil || !validurl(b)) error("urlcombine: b==nil || !validurl(b)"); if(runestrncmp(u, L"//", 2) == 0){ q = runestrchr(b, L':'); return runesmprint("%.*S:%S", (int)(q-b), b, u); } p = runestrstr(b, L"://"); if(p != nil) p += 3; sep = L""; q = nil; if(*u ==L'/') q = runestrchr(p, L'/'); else if(*u==L'#' || *u==L'?'){ for(i=0; i<nelem(endrune); i++) if(q = runestrchr(p, endrune[i])) break; }else if(p != nil){ sep = L"/"; restore = 0; s = runestrchr(p, L'?'); if(s != nil){ *s = '\0'; restore = 1; } q = runestrrchr(p, L'/'); if(restore) *s = L'?'; }else sep = L"/"; if(q == nil) p = runesmprint("%S%S%S", b, sep, u); else p = runesmprint("%.*S%S%S", (int)(q-b), b, sep, u); urlcanon(p); return p; }
void textdoubleclick(Text *t, uint *q0, uint *q1) { int c, i; Rune *r, *l, *p; uint q; if(textclickhtmlmatch(t, q0, q1)) return; for(i=0; left[i]!=nil; i++){ q = *q0; l = left[i]; r = right[i]; /* try matching character to left, looking right */ if(q == 0) c = '\n'; else c = textreadc(t, q-1); p = runestrchr(l, c); if(p != nil){ if(textclickmatch(t, c, r[p-l], 1, &q)) *q1 = q-(c!='\n'); return; } /* try matching character to right, looking left */ if(q == t->file->b.nc) c = '\n'; else c = textreadc(t, q); p = runestrchr(r, c); if(p != nil){ if(textclickmatch(t, c, l[p-r], -1, &q)){ *q1 = *q0+(*q0<t->file->b.nc && c=='\n'); *q0 = q; if(c!='\n' || q!=0 || textreadc(t, 0)=='\n') (*q0)++; } return; } } /* try filling out word to right */ while(*q1<t->file->b.nc && isalnum(textreadc(t, *q1))) (*q1)++; /* try filling out word to left */ while(*q0>0 && isalnum(textreadc(t, *q0-1))) (*q0)--; }
Rune* runestrcat(Rune *s1, const Rune *s2) { runestrcpy((Rune*)runestrchr(s1, 0), s2); return s1; }
Rune* runestrcat(Rune *s1, Rune *s2) { runestrcpy(runestrchr(s1, 0), s2); return s1; }
Rune * runestrstr(const Rune *s1, const Rune *s2) { const Rune *p1, *p2; Rune r0, r1, r2; r0 = *s2; for(s1 = runestrchr(s1, r0); *s1 != 0; s1 = runestrchr(s1+1, r0)) for(p1 = s1, p2 = s2;; p1++, p2++) { r2 = *p2; if(r2 == 0) return (Rune *)s1; r1 = *p1; if(r1 != r2) break; } return NULL; }
int isfilec(Rune r) { static Rune Lx[] = { '.', '-', '+', '/', ':', 0 }; if(isalnum(r)) return TRUE; if(runestrchr(Lx, r)) return TRUE; return FALSE; }
void urlcanon(Rune *name){ Rune *s, *t; Rune **comp, **p, **q; int rooted; name = runestrchr(name, L'/')+2; rooted=name[0]==L'/'; /* * Break the name into a list of components */ comp=emalloc(runestrlen(name)*sizeof(char *)); p=comp; *p++=name; for(s=name;;s++){ if(*s==L'/'){ *p++=s+1; *s='\0'; } else if(*s=='\0') break; } *p=0; /* * go through the component list, deleting components that are empty (except * the last component) or ., and any .. and its non-.. predecessor. */ p=q=comp; while(*p){ if(runestrcmp(*p, L"")==0 && p[1]!=0 || runestrcmp(*p, L".")==0) p++; else if(runestrcmp(*p, L"..")==0 && q!=comp && runestrcmp(q[-1], L"..")!=0){ --q; p++; } else *q++=*p++; } *q=0; /* * rebuild the path name */ s=name; if(rooted) *s++='/'; for(p=comp;*p;p++){ t=*p; while(*t) *s++=*t++; if(p[1]!=0) *s++='/'; } *s='\0'; free(comp); }
/* * Return pointer to first occurrence of s2 in s1, * 0 if none */ Rune* runestrstr(Rune *s1, Rune *s2) { Rune *p, *pa, *pb; int c0, c; c0 = *s2; if(c0 == 0) return s1; s2++; for(p=runestrchr(s1, c0); p; p=runestrchr(p+1, c0)) { pa = p; for(pb=s2;; pb++) { c = *pb; if(c == 0) return p; if(c != *++pa) break; } } return 0; }
Rune* runestrncat(Rune *s1, const Rune *s2, int32_t n) { Rune *os1; os1 = s1; s1 = runestrchr(s1, 0); while(*s1++ = *s2++) if(--n < 0) { s1[-1] = 0; break; } return os1; }
static void setname(void) { Rune *r, *p; if(istack == nil || istack->name == nil) return; _nr(L(".F"), istack->name); r = erunestrdup(istack->name); p = runestrchr(r, '.'); if(p) *p = 0; _nr(L(".B"), r); free(r); }
void pagesetrefresh(Page *p) { Runestr rs; Rune *s, *q, *t; char *v; int n; if(!p->doc || !p->doc->refresh) return; s = p->doc->refresh; q = runestrchr(s, L'='); if(q == nil) return; q++; if(!q) return; n = runestrlen(q); if(*q == L'''){ q++; n -= 2; }
long runestrlen(const Rune *s) { return runestrchr(s, 0) - s; }
/* * return 0 if no match * >0 if a match * <0 if we ran out of _relist space */ static int rregexec1(Reprog *progp, /* program to run */ Rune *bol, /* string to run machine on */ Resub *mp, /* subexpression elements */ int ms, /* number of elements at mp */ Reljunk *j) { int flag=0; Reinst *inst; Relist *tlp; Rune *s; int i, checkstart; Rune r, *rp, *ep; Relist* tl; /* This list, next list */ Relist* nl; Relist* tle; /* ends of this and next list */ Relist* nle; int match; Rune *p; match = 0; checkstart = j->startchar; if(mp) for(i=0; i<ms; i++) { mp[i].rsp = 0; mp[i].rep = 0; } j->relist[0][0].inst = 0; j->relist[1][0].inst = 0; /* Execute machine once for each character, including terminal NUL */ s = j->rstarts; do{ /* fast check for first char */ if(checkstart) { switch(j->starttype) { case RUNE: p = runestrchr(s, j->startchar); if(p == 0 || s == j->reol) return match; s = p; break; case BOL: if(s == bol) break; p = runestrchr(s, '\n'); if(p == 0 || s == j->reol) return match; s = p+1; break; } } r = *s; /* switch run lists */ tl = j->relist[flag]; tle = j->reliste[flag]; nl = j->relist[flag^=1]; nle = j->reliste[flag]; nl->inst = 0; /* Add first instruction to current list */ _rrenewemptythread(tl, progp->startinst, ms, s); /* Execute machine until current list is empty */ for(tlp=tl; tlp->inst; tlp++){ for(inst=tlp->inst; ; inst = inst->next){ switch(inst->type){ case RUNE: /* regular character */ if(inst->r == r) if(_renewthread(nl, inst->next, ms, &tlp->se)==nle) return -1; break; case LBRA: tlp->se.m[inst->subid].rsp = s; continue; case RBRA: tlp->se.m[inst->subid].rep = s; continue; case ANY: if(r != '\n') if(_renewthread(nl, inst->next, ms, &tlp->se)==nle) return -1; break; case ANYNL: if(_renewthread(nl, inst->next, ms, &tlp->se)==nle) return -1; break; case BOL: if(s == bol || *(s-1) == '\n') continue; break; case EOL: if(s == j->reol || r == 0 || r == '\n') continue; break; case CCLASS: ep = inst->cp->end; for(rp = inst->cp->spans; rp < ep; rp += 2) if(r >= rp[0] && r <= rp[1]){ if(_renewthread(nl, inst->next, ms, &tlp->se)==nle) return -1; break; } break; case NCCLASS: ep = inst->cp->end; for(rp = inst->cp->spans; rp < ep; rp += 2) if(r >= rp[0] && r <= rp[1]) break; if(rp == ep) if(_renewthread(nl, inst->next, ms, &tlp->se)==nle) return -1; break; case OR: /* evaluate right choice later */ if(_renewthread(tlp, inst->right, ms, &tlp->se) == tle) return -1; /* efficiency: advance and re-evaluate */ continue; case END: /* Match! */ match = 1; tlp->se.m[0].rep = s; if(mp != 0) _renewmatch(mp, ms, &tlp->se); break; } break; } } if(s == j->reol) break; checkstart = j->startchar && nl->inst==0; s++; }while(r); return match; }
void urlcanon(Rune *name) { Rune *s, *e, *tail, tailr; Rune **comp, **p, **q; int n; name = runestrstr(name, L"://"); if(name == nil) return; name = runestrchr(name+3, '/'); if(name == nil) return; if(*name == L'/') name++; n = 0; for(e = name; *e != 0; e++) if(*e == L'/') n++; comp = emalloc((n+2)*sizeof *comp); /* * Break the name into a list of components */ p = comp; *p++ = name; tail = nil; tailr = L'☺'; /* silence compiler */ for(s = name; *s != 0; s++){ if(*s == '?' || *s == '#'){ tail = s+1; tailr = *s; *s = 0; break; } else if(*s == L'/'){ *p++ = s+1; *s = 0; } } /* * go through the component list, deleting components that are empty (except * the last component) or ., and any .. and its predecessor. */ for(p = q = comp; *p != nil; p++){ if(runestrcmp(*p, L"") == 0 && p[1] != nil || runestrcmp(*p, L".") == 0) continue; else if(q>comp && runestrcmp(*p, L"..") == 0 && runestrcmp(q[-1], L"..") != 0) q--; else *q++ = *p; } *q = nil; /* * rebuild the path name */ s = name; for(p = comp; p<q; p++){ n = runestrlen(*p); memmove(s, *p, sizeof(Rune)*n); s += n; if(p[1] != nil) *s++ = '/'; } *s = 0; if(tail) runeseprint(s, e+1, "%C%S", tailr, tail); free(comp); }
int search(Text *ct, Rune *r, uint n) { uint q, nb, maxn; int around; Rune *s, *b, *c; if(n==0 || n>ct->file->b.nc) return FALSE; if(2*n > RBUFSIZE){ warning(nil, "string too long\n"); return FALSE; } maxn = max(2*n, RBUFSIZE); s = fbufalloc(); b = s; nb = 0; b[nb] = 0; around = 0; q = ct->q1; for(;;){ if(q >= ct->file->b.nc){ q = 0; around = 1; nb = 0; b[nb] = 0; } if(nb > 0){ c = runestrchr(b, r[0]); if(c == nil){ q += nb; nb = 0; b[nb] = 0; if(around && q>=ct->q1) break; continue; } q += (c-b); nb -= (c-b); b = c; } /* reload if buffer covers neither string nor rest of file */ if(nb<n && nb!=ct->file->b.nc-q){ nb = ct->file->b.nc-q; if(nb >= maxn) nb = maxn-1; bufread(&ct->file->b, q, s, nb); b = s; b[nb] = '\0'; } /* this runeeq is fishy but the null at b[nb] makes it safe */ if(runeeq(b, n, r, n)==TRUE){ if(ct->w){ textshow(ct, q, q+n, 1); winsettag(ct->w); }else{ ct->q0 = q; ct->q1 = q+n; } seltext = ct; fbuffree(s); return TRUE; } --nb; b++; q++; if(around && q>=ct->q1) break; } fbuffree(s); return FALSE; }
int32_t runestrlen(Rune *s) { return runestrchr(s, 0) - s; }