util.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. #include <draw.h>
  13. #include <memdraw.h>
  14. #include <thread.h>
  15. #include <cursor.h>
  16. #include <mouse.h>
  17. #include <keyboard.h>
  18. #include <frame.h>
  19. #include <plumb.h>
  20. #include <html.h>
  21. #include <regexp.h>
  22. #include "dat.h"
  23. #include "fns.h"
  24. static Point prevmouse;
  25. static Window *mousew;
  26. int
  27. min(int a, int b)
  28. {
  29. if(a < b)
  30. return a;
  31. return b;
  32. }
  33. int
  34. max(int a, int b)
  35. {
  36. if(a > b)
  37. return a;
  38. return b;
  39. }
  40. void
  41. cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
  42. {
  43. uint8_t *q;
  44. Rune *s;
  45. int j, w;
  46. /*
  47. * Always guaranteed that n bytes may be interpreted
  48. * without worrying about partial runes. This may mean
  49. * reading up to UTFmax-1 more bytes than n; the caller
  50. * knows this. If n is a firm limit, the caller should
  51. * set p[n] = 0.
  52. */
  53. q = (uint8_t*)p;
  54. s = r;
  55. for(j=0; j<n; j+=w){
  56. if(*q < Runeself){
  57. w = 1;
  58. *s = *q++;
  59. }else{
  60. w = chartorune(s, (char*)q);
  61. q += w;
  62. }
  63. if(*s)
  64. s++;
  65. else if(nulls)
  66. *nulls = TRUE;
  67. }
  68. *nb = (char*)q-p;
  69. *nr = s-r;
  70. }
  71. void
  72. bytetorunestr(char *s, Runestr *rs)
  73. {
  74. Rune *r;
  75. int nb, nr;
  76. nb = strlen(s);
  77. r = runemalloc(nb+1);
  78. cvttorunes(s, nb, r, &nb, &nr, nil);
  79. r[nr] = '\0';
  80. rs->nr = nr;
  81. rs->r = r;
  82. }
  83. void
  84. error(char *s)
  85. {
  86. fprint(2, "abaco: %s: %r\n", s);
  87. // abort();
  88. threadexitsall(s);
  89. }
  90. void*
  91. emalloc(uint32_t n)
  92. {
  93. void *p;
  94. p = malloc(n);
  95. if(p == nil)
  96. error("malloc failed");
  97. setmalloctag(p, getcallerpc());
  98. memset(p, 0, n);
  99. return p;
  100. }
  101. void*
  102. erealloc(void *p, uint32_t n)
  103. {
  104. p = realloc(p, n);
  105. if(p == nil)
  106. error("realloc failed");
  107. setmalloctag(p, getcallerpc());
  108. return p;
  109. }
  110. Rune*
  111. erunestrdup(Rune *r)
  112. {
  113. void *p;
  114. if(r == nil)
  115. return nil;
  116. p = runestrdup(r);
  117. if(p == nil)
  118. error("runestrdup failed");
  119. setmalloctag(p, getcallerpc());
  120. return p;
  121. }
  122. char*
  123. estrdup(char *s)
  124. {
  125. char *t;
  126. t = strdup(s);
  127. if(t == nil)
  128. error("strdup failed");
  129. setmalloctag(t, getcallerpc());
  130. return t;
  131. }
  132. int
  133. runestreq(Runestr a, Runestr b)
  134. {
  135. return runeeq(a.r, a.nr, b.r, b.nr);
  136. }
  137. int
  138. runeeq(Rune *s1, uint n1, Rune *s2, uint n2)
  139. {
  140. if(n1 != n2)
  141. return FALSE;
  142. return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
  143. }
  144. void
  145. closerunestr(Runestr *rs)
  146. {
  147. rs->nr = 0;
  148. if(rs->r)
  149. free(rs->r);
  150. rs->r = nil;
  151. }
  152. void
  153. copyrunestr(Runestr *a, Runestr *b)
  154. {
  155. closerunestr(a);
  156. a->r = runemalloc(b->nr+1);
  157. runemove(a->r, b->r, b->nr);
  158. a->r[b->nr] = 0;
  159. a->nr = b->nr;
  160. }
  161. int
  162. isalnum(Rune c)
  163. {
  164. /*
  165. * Hard to get absolutely right. Use what we know about ASCII
  166. * and assume anything above the Latin control characters is
  167. * potentially an alphanumeric.
  168. */
  169. if(c <= ' ')
  170. return FALSE;
  171. if(0x7F<=c && c<=0xA0)
  172. return FALSE;
  173. if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
  174. return FALSE;
  175. return TRUE;
  176. }
  177. Rune*
  178. skipbl(Rune *r, int n, int *np)
  179. {
  180. while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){
  181. --n;
  182. r++;
  183. }
  184. *np = n;
  185. return r;
  186. }
  187. Rune*
  188. findbl(Rune *r, int n, int *np)
  189. {
  190. while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
  191. --n;
  192. r++;
  193. }
  194. *np = n;
  195. return r;
  196. }
  197. int
  198. istextfield(Item *i)
  199. {
  200. Formfield *ff;
  201. ff = ((Iformfield *)i)->formfield;
  202. if(ff->ftype==Ftext || ff->ftype==Ftextarea || ff->ftype==Fpassword)
  203. return TRUE;
  204. return FALSE;
  205. }
  206. int
  207. forceitem(Item *i)
  208. {
  209. if(i->state&IFwrap && i->tag!=Iruletag && i->tag!=Itabletag)
  210. return FALSE;
  211. return TRUE;
  212. }
  213. int
  214. dimwidth(Dimen d, int w)
  215. {
  216. int s, k;
  217. k = dimenkind(d);
  218. if(k == Dnone)
  219. return w;
  220. s = dimenspec(d);
  221. if(k == Dpixels)
  222. w = s;
  223. else if(k==Dpercent && s<100)
  224. w = s*w/100;
  225. return w;
  226. }
  227. void
  228. frdims(Dimen *d, int n, int t, int **ret)
  229. {
  230. int totpix, totpcnt, totrel;
  231. double spix, spcnt, relu, vd;
  232. int tt, trest, totpixrel, minrelu, i;
  233. int *x, *spec, *kind;
  234. if(n == 1){
  235. *ret = x = emalloc(sizeof(int));
  236. x[0] = t;
  237. return;
  238. }
  239. totpix = totpcnt = totrel = 0;
  240. spec = emalloc(n*sizeof(int));
  241. kind = emalloc(n*sizeof(int));
  242. for(i=0; i<n; i++){
  243. spec[i] = dimenspec(d[i]);
  244. if(spec[i] < 0)
  245. spec[i] = 0;
  246. kind[i] = dimenkind(d[i]);
  247. switch(kind[i]){
  248. case Dpixels:
  249. totpix += spec[i];
  250. break;
  251. case Dpercent:
  252. totpcnt += spec[i];
  253. break;
  254. case Drelative:
  255. totrel += spec[i];
  256. break;
  257. case Dnone:
  258. totrel++;
  259. break;
  260. }
  261. }
  262. spix = spcnt = 1.0;
  263. minrelu = 0;
  264. if(totrel > 0)
  265. minrelu = Scrollsize+Scrollgap;
  266. relu = (double)minrelu;
  267. tt = totpix + t*totpcnt/100 + totrel*minrelu;
  268. if(tt < t){
  269. if(totrel == 0){
  270. if(totpcnt != 0)
  271. spcnt = (double)((t-totpix)*100)/(double)(t*totpcnt);
  272. else
  273. spix = (double)t/(double)totpix;
  274. }else
  275. relu += (double)(t-tt)/(double)totrel;
  276. }else{
  277. totpixrel = totpix + totrel*minrelu;
  278. if(totpixrel < t)
  279. spcnt = (double)((t-totpixrel)*100)/(double)(t*totpcnt);
  280. else{
  281. trest = t - totrel*minrelu;
  282. if(trest > 0)
  283. spcnt = (double)trest/(double)(totpix + (t*totpcnt/100));
  284. else{
  285. spcnt = (double)t/(double)tt;
  286. relu = 0.0;
  287. }
  288. spix = spcnt;
  289. }
  290. }
  291. x = emalloc(n * sizeof(int));
  292. tt = 0;
  293. for(i=0; i<n-1; i++){
  294. vd = (double)spec[i];
  295. switch(kind[i]){
  296. case Dpixels:
  297. vd = vd*spix;
  298. break;
  299. case Dpercent:
  300. vd = vd*(double)t*spcnt/100.0;
  301. break;
  302. case Drelative:
  303. vd = vd*relu;
  304. break;
  305. case Dnone:
  306. vd = relu;
  307. break;
  308. }
  309. x[i] = (int)(vd+.5);
  310. tt += x[i];
  311. }
  312. x[n - 1] = t - tt;
  313. *ret = x;
  314. free(spec);
  315. free(kind);
  316. }
  317. Image *
  318. getbg(Page *p)
  319. {
  320. Docinfo *d;
  321. Cimage *ci;
  322. Image *bg;
  323. d = p->doc;
  324. if(d->backgrounditem){
  325. if(d->backgrounditem->aux){
  326. ci = d->backgrounditem->aux;
  327. if(ci->mi)
  328. getimage(ci, d->backgrounditem->altrep);
  329. bg = ci->i;
  330. }else
  331. bg = display->white;
  332. }else
  333. bg = getcolor(d->background.color);
  334. return bg;
  335. }
  336. Rune *
  337. getbase(Page *p)
  338. {
  339. if(p->doc)
  340. return p->doc->base;
  341. if(p->url->act.r)
  342. return p->url->act.r;
  343. return p->url->src.r;
  344. }
  345. Image *
  346. eallocimage(Display *d, Rectangle r, uint32_t chan, int repl, int col)
  347. {
  348. Image *i;
  349. i = allocimage(d, r, chan, repl, col);
  350. if(i == nil)
  351. error("allocimage failed");
  352. return i;
  353. }
  354. void
  355. rect3d(Image *im, Rectangle r, int i, Image **c, Point sp)
  356. {
  357. Point p[6];
  358. if(i < 0){
  359. r = insetrect(r, i);
  360. sp = addpt(sp, Pt(i,i));
  361. i = -i;
  362. }
  363. draw(im, Rect(r.min.x+i, r.min.y+i, r.max.x-i, r.max.y-i), c[2], nil, sp);
  364. p[0] = r.min;
  365. p[1] = Pt(r.min.x, r.max.y);
  366. p[2] = Pt(r.min.x+i, r.max.y-i);
  367. p[3] = Pt(r.min.x+i, r.min.y+i);
  368. p[4] = Pt(r.max.x-i, r.min.y+i);
  369. p[5] = Pt(r.max.x, r.min.y);
  370. fillpoly(im, p, 6, 0, c[0], sp);
  371. p[0] = r.max;
  372. p[1] = Pt(r.min.x, r.max.y);
  373. p[2] = Pt(r.min.x+i, r.max.y-i);
  374. p[3] = Pt(r.max.x-i, r.max.y-i);
  375. p[4] = Pt(r.max.x-i, r.min.y+i);
  376. p[5] = Pt(r.max.x, r.min.y);
  377. fillpoly(im, p, 6, 0, c[1], sp);
  378. }
  379. void
  380. ellipse3d(Image *im, Point p, int rad, int i, Image **c, Point sp)
  381. {
  382. fillarc(im, p, rad, rad, c[0], sp, 45, 180);
  383. fillarc(im, p, rad, rad, c[1], sp, 45, -180);
  384. fillellipse(im, p, rad-i, rad-i, c[2], sp);
  385. }
  386. void
  387. colarray(Image **c, Image *c0, Image *c1, Image *c2, int checked)
  388. {
  389. if(checked){
  390. c[0] = c0;
  391. c[1] = c1;
  392. }else{
  393. c[0] = c1;
  394. c[1] = c0;
  395. }
  396. c[2] = c2;
  397. }
  398. static char *deffontpaths[] = {
  399. #include "fonts.h"
  400. };
  401. static char *fontpaths[NumFnt];
  402. static Font *fonts[NumFnt];
  403. void
  404. initfontpaths(void)
  405. {
  406. Biobufhdr *bp;
  407. char buf[128];
  408. int i;
  409. /* we don't care if getenv(2) fails */
  410. snprint(buf, sizeof(buf)-1, "%s/lib/abaco.fonts", getenv("home"));
  411. if((bp=Bopen(buf, OREAD)) == nil)
  412. goto Default;
  413. for(i=0; i<NumFnt; i++)
  414. if((fontpaths[i]=Brdstr(bp, '\n', 1)) == nil)
  415. goto Error;
  416. Bterm(bp);
  417. return;
  418. Error:
  419. fprint(2, "abaco: not enough fontpaths in '%s'\n", buf);
  420. Bterm(bp);
  421. for(i--; i>=0; i--)
  422. free(fontpaths[i]);
  423. Default:
  424. for(i=0; i<NumFnt; i++)
  425. fontpaths[i] = deffontpaths[i];
  426. }
  427. Font *
  428. getfont(int i)
  429. {
  430. if(fonts[i] == nil){
  431. fonts[i] = openfont(display, fontpaths[i]);
  432. if(fonts[i] == nil)
  433. error("can't open font file");
  434. }
  435. return fonts[i];
  436. }
  437. typedef struct Color Color;
  438. struct Color {
  439. int rgb;
  440. Image *i;
  441. Color *next;
  442. };
  443. enum {
  444. NHASH = 19,
  445. };
  446. static Color *colortab[NHASH];
  447. Image *
  448. getcolor(int rgb)
  449. {
  450. Color *c;
  451. int h;
  452. if(rgb == 0xFFFFFF)
  453. return display->white;
  454. else if(rgb == 0x000000)
  455. return display->black;
  456. h = rgb%NHASH;
  457. for(c=colortab[h]; c!=nil; c=c->next)
  458. if(c->rgb == rgb){
  459. flushimage(display, 0); /* BUG? */
  460. return c->i;
  461. }
  462. c = emalloc(sizeof(Color));
  463. c->i = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, (rgb<<8)|0xFF);
  464. c->rgb = rgb;
  465. c->next = colortab[h];
  466. colortab[h] = c;
  467. return c->i;
  468. }
  469. int
  470. plumbrunestr(Runestr *rs, char *attr)
  471. {
  472. Plumbmsg *m;
  473. int i;
  474. i = -1;
  475. if(plumbsendfd >= 0){
  476. m = emalloc(sizeof(Plumbmsg));
  477. m->src = estrdup("abaco");
  478. m->dst = nil;
  479. m->wdir = estrdup("/tmp");
  480. m->type = estrdup("text");
  481. if(attr)
  482. m->attr = plumbunpackattr(attr);
  483. else
  484. m->attr = nil;
  485. m->data = smprint("%.*S", rs->nr, rs->r);
  486. m->ndata = -1;
  487. i = plumbsend(plumbsendfd, m);
  488. plumbfree(m);
  489. }
  490. return i;
  491. }
  492. int
  493. hexdigit(int v)
  494. {
  495. if(0<=v && v<=9)
  496. return '0' + v;
  497. else
  498. return 'A' + v - 10;
  499. }
  500. static int
  501. inclass(char c, Rune* cl)
  502. {
  503. int n, ans, negate, i;
  504. n = runestrlen(cl);
  505. if(n == 0)
  506. return 0;
  507. ans = 0;
  508. negate = 0;
  509. if(cl[0] == '^'){
  510. negate = 1;
  511. cl++;
  512. n--;
  513. }
  514. for(i=0; i<n; i++){
  515. if(cl[i]=='-' && i>0 && i<n-1){
  516. if(c>=cl[i - 1] && c<=cl[i+1]){
  517. ans = 1;
  518. break;
  519. }
  520. i++;
  521. }
  522. else if(c == cl[i]){
  523. ans = 1;
  524. break;
  525. }
  526. }
  527. if(negate)
  528. ans = !ans;
  529. return ans;
  530. }
  531. Rune*
  532. ucvt(Rune* s)
  533. {
  534. Rune* u;
  535. char *t;
  536. int i, c, n, j, len;
  537. t = smprint("%S", s);
  538. n = strlen(t);
  539. len = 0;
  540. for(i=0; i<n; i++){
  541. c = t[i];
  542. if(inclass(c, L"- /$_@.!*'(),a-zA-Z0-9"))
  543. len++;
  544. else
  545. len += 3;
  546. }
  547. u = runemalloc(len+1);
  548. j = 0;
  549. for(i=0; i<n; i++){
  550. c = t[i];
  551. if(inclass(c, L"-/$_@.!*'(),a-zA-Z0-9"))
  552. u[j++] = c;
  553. else if(c == ' ')
  554. u[j++] = '+';
  555. else {
  556. u[j++] = '%';
  557. u[j++] = hexdigit((c >> 4)&15);
  558. u[j++] = hexdigit(c&15);
  559. }
  560. }
  561. u[j] = 0;
  562. free(t);
  563. return u;
  564. }
  565. void
  566. reverseimages(Iimage **head)
  567. {
  568. Iimage *r, *c, *n;
  569. r = nil;
  570. for(c=*head; c!=nil; c=n){
  571. n = c->nextimage;
  572. c->nextimage = r;
  573. r = c;
  574. }
  575. *head = r;
  576. }
  577. char urlexpr[] = "^(https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|"
  578. "prospero)://([a-zA-Z0-9_@\\-]+([.:][a-zA-Z0-9_@\\-]+)*)";
  579. Reprog *urlprog;
  580. int
  581. validurl(Rune *r)
  582. {
  583. Resub rs[10];
  584. if(urlprog == nil){
  585. urlprog = regcomp(urlexpr);
  586. if(urlprog == nil)
  587. error("regcomp");
  588. }
  589. memset(rs, 0, sizeof(rs));
  590. if(rregexec(urlprog, r, rs, nelem(rs)) == 0)
  591. return FALSE;
  592. return TRUE;
  593. }
  594. void
  595. execproc(void *v)
  596. {
  597. Channel *sync;
  598. Exec *e;
  599. int p[2], q[2];
  600. char *cmd;
  601. threadsetname("execproc");
  602. e = v;
  603. p[0] = e->p[0];
  604. p[1] = e->p[1];
  605. q[0] = e->q[0];
  606. q[1] = e->q[1];
  607. cmd = e->cmd;
  608. sync = e->sync;
  609. rfork(RFFDG);
  610. free(e);
  611. dup(p[0], 0);
  612. close(p[0]);
  613. close(p[1]);
  614. if(q[0]){
  615. dup(q[1], 1);
  616. close(q[0]);
  617. close(q[1]);
  618. }
  619. if(!procstderr)
  620. close(2);
  621. procexecl(sync, "/bin/rc", "rc", "-c", cmd, 0);
  622. error("can't exec");
  623. }
  624. static void
  625. writeproc(void *v)
  626. {
  627. Channel *sync;
  628. void **a;
  629. char *s;
  630. int32_t np;
  631. int fd, i, n;
  632. threadsetname("writeproc");
  633. a = v;
  634. sync = a[0];
  635. fd = (uintptr)a[1];
  636. s = a[2];
  637. np =(uintptr)a[3];
  638. free(a);
  639. for(i=0; i<np; i+=n){
  640. n = np-i;
  641. if(n > BUFSIZE)
  642. n = BUFSIZE;
  643. if(write(fd, s+i, n) != n)
  644. break;
  645. }
  646. close(fd);
  647. sendul(sync, i);
  648. }
  649. struct {
  650. char *mime;
  651. char *tcs;
  652. }tcstab[] = {
  653. #include "tcs.h"
  654. /* not generated by the script */
  655. "euc_jp", "jis",
  656. "euc_kr", "euc-k",
  657. "windows-874", "tis",
  658. nil, nil,
  659. };
  660. enum {
  661. Winstart = 127,
  662. Winend = 159
  663. };
  664. static int winchars[] = {
  665. 8226, /* 8226 is a bullet */
  666. 8226, 8226, 8218, 402, 8222, 8230, 8224, 8225,
  667. 710, 8240, 352, 8249, 338, 8226, 8226, 8226,
  668. 8226, 8216, 8217, 8220, 8221, 8226, 8211, 8212,
  669. 732, 8482, 353, 8250, 339, 8226, 8226, 376
  670. };
  671. char *
  672. tcs(char *cs, char *s, int32_t *np)
  673. {
  674. Channel *sync;
  675. Exec *e;
  676. Rune r;
  677. int32_t i, n;
  678. void **a;
  679. uint8_t *us;
  680. char buf[BUFSIZE], cmd[50];
  681. char *t, *u;
  682. int p[2], q[2];
  683. if(s==nil || *s=='\0' || *np==0){
  684. werrstr("tcs failed: no data");
  685. return s;
  686. }
  687. if(cs == nil){
  688. werrstr("tcs failed: no charset");
  689. return s;
  690. }
  691. if(cistrncmp(cs, "utf-8", 5)==0 || cistrncmp(cs, "utf8", 4)==0)
  692. return s;
  693. for(i=0; tcstab[i].mime!=nil; i++)
  694. if(cistrncmp(cs, tcstab[i].mime, strlen(tcstab[i].mime)) == 0)
  695. break;
  696. if(tcstab[i].mime == nil){
  697. fprint(2, "abaco: charset: %s not supported\n", cs);
  698. goto latin1;
  699. }
  700. if(cistrcmp(tcstab[i].tcs, "8859-1")==0 || cistrcmp(tcstab[i].tcs, "ascii")==0){
  701. latin1:
  702. n = 0;
  703. for(us=(uint8_t*)s; *us; us++)
  704. n += runelen(*us);
  705. n++;
  706. t = emalloc(n);
  707. for(us=(uint8_t*)s, u=t; *us; us++){
  708. if(*us>=Winstart && *us<=Winend)
  709. *u++ = winchars[*us-Winstart];
  710. else{
  711. r = *us;
  712. u += runetochar(u, &r);
  713. }
  714. }
  715. *u = 0;
  716. free(s);
  717. return t;
  718. }
  719. if(pipe(p)<0 || pipe(q)<0)
  720. error("can't create pipe");
  721. sync = chancreate(sizeof(uint32_t), 0);
  722. if(sync == nil)
  723. error("can't create channel");
  724. snprint(cmd, sizeof cmd, "tcs -f %s", tcstab[i].tcs);
  725. e = emalloc(sizeof(Exec));
  726. e->p[0] = p[0];
  727. e->p[1] = p[1];
  728. e->q[0] = q[0];
  729. e->q[1] = q[1];
  730. e->cmd = cmd;
  731. e->sync = sync;
  732. proccreate(execproc, e, STACK);
  733. recvul(sync);
  734. chanfree(sync);
  735. close(p[0]);
  736. close(q[1]);
  737. /* in case tcs fails */
  738. t = s;
  739. sync = chancreate(sizeof(uint32_t), 0);
  740. if(sync == nil)
  741. error("can't create channel");
  742. a = emalloc(4*sizeof(void *));
  743. a[0] = sync;
  744. a[1] = (void *)p[1];
  745. a[2] = s;
  746. a[3] = (void *)*np;
  747. proccreate(writeproc, a, STACK);
  748. s = nil;
  749. while((n = read(q[0], buf, sizeof(buf))) > 0){
  750. s = erealloc(s, i+n+1);
  751. memmove(s+i, buf, n);
  752. i += n;
  753. s[i] = '\0';
  754. }
  755. n = recvul(sync);
  756. if(n != *np)
  757. fprint(2, "tcs: did not write %ld; wrote %uld\n", *np, n);
  758. *np = i;
  759. chanfree(sync);
  760. close(q[0]);
  761. if(s == nil){
  762. fprint(2, "tcs failed: can't convert charset=%s to %s\n", cs, tcstab[i].tcs);
  763. return t;
  764. }
  765. free(t);
  766. return s;
  767. }
  768. static
  769. int
  770. isspace(char c)
  771. {
  772. return c==' ' || c== '\t' || c=='\r' || c=='\n';
  773. }
  774. static
  775. int
  776. findctype(char *b, int l, char *keyword, char *s)
  777. {
  778. char *p, *e;
  779. int i;
  780. p = cistrstr(s, keyword);
  781. if(!p)
  782. return -1;
  783. p += strlen(keyword);
  784. while(*p && isspace(*p))
  785. p++;
  786. if(*p != '=')
  787. return -1;
  788. p++;
  789. while(*p && isspace(*p))
  790. p++;
  791. if(!*p)
  792. return -1;
  793. if(*p == '"'){
  794. p++;
  795. e = strchr(p, '"');
  796. if(!e)
  797. return -1;
  798. }else
  799. for(e = p; *e < 127 && *e > ' ' ; e++)
  800. ;
  801. i = e-p;
  802. if(i < 1)
  803. return -1;
  804. snprint(b, l, "%.*s", i, p);
  805. return 0;
  806. }
  807. static
  808. int
  809. finddocctype(char *b, int l, char *s)
  810. {
  811. char *p, *e;
  812. p = cistrstr(s, "<meta");
  813. if(!p)
  814. return -1;
  815. p += 5;
  816. e = strchr(s, '>');
  817. if(!e)
  818. return -1;
  819. snprint(b, l, "%.*s", (int)(e-p), p);
  820. return 0;
  821. }
  822. static
  823. int
  824. findxmltype(char *b, int l, char *s)
  825. {
  826. char *p, *e;
  827. p = cistrstr(s, "<?xml ");
  828. if(!p)
  829. return -1;
  830. p += 6;
  831. e = strstr(p, "?>");
  832. if(!e)
  833. return -1;
  834. snprint(b, l, "%.*s", (int)(e-p), p);
  835. return 0;
  836. }
  837. /*
  838. * servers can lie about lie about the charset,
  839. * so we use the charset based on the priority.
  840. */
  841. char *
  842. convert(Runestr ctype, char *s, int32_t *np)
  843. {
  844. char t[25], buf[256];
  845. *t = '\0';
  846. if(ctype.nr){
  847. snprint(buf, sizeof(buf), "%.*S", ctype.nr, ctype.r);
  848. findctype(t, sizeof(t), "charset", buf);
  849. }
  850. if(findxmltype(buf, sizeof(buf), s)==0)
  851. findctype(t, sizeof(t), "encoding", buf);
  852. if(finddocctype(buf, sizeof(buf), s) == 0)
  853. findctype(t, sizeof(t), "charset", buf);
  854. if(*t == '\0')
  855. strcpy(t, charset);
  856. return tcs(t, s, np);
  857. }
  858. int
  859. xtofchar(Rune *s, Font *f, int32_t p)
  860. {
  861. Rune *r;
  862. int q;
  863. if(p == 0)
  864. return 0;
  865. q = 0;
  866. for(r=s; *r!=L'\0'; r++){
  867. p -= runestringnwidth(f, r, 1);
  868. if(p < 0)
  869. break;
  870. q++;
  871. }
  872. return q;
  873. }
  874. int
  875. istextsel(Page *p, Rectangle r, int *q0, int *q1, Rune *s, Font *f)
  876. {
  877. int topinr, botinr;
  878. *q0 = *q1 = 0;
  879. topinr= ptinrect(p->top, r);
  880. if(topinr || (r.min.y>p->top.y && r.max.y<p->bot.y))
  881. p->selecting = TRUE;
  882. botinr = ptinrect(p->bot, r);
  883. if(botinr || r.min.y>p->bot.y)
  884. p->selecting = FALSE;
  885. if(topinr || botinr){
  886. if(topinr)
  887. *q0 = xtofchar(s, f, p->top.x-r.min.x);
  888. if(botinr)
  889. *q1 = xtofchar(s, f, p->bot.x-r.min.x);
  890. if(*q0!=0 || *q1!=0)
  891. return TRUE;
  892. }
  893. return p->selecting;
  894. }
  895. Point
  896. getpt(Page *p, Point xy)
  897. {
  898. xy.x = xy.x-p->r.min.x+p->pos.x;
  899. xy.y = xy.y-p->r.min.y+p->pos.y;
  900. return xy;
  901. }
  902. void
  903. getimage(Cimage *ci, Rune *altr)
  904. {
  905. Rectangle r;
  906. Memimage *mi;
  907. Image *i, *i2;
  908. char buf[128];
  909. uint8_t *bits;
  910. int nbits;
  911. mi = ci->mi;
  912. if(mi == nil){
  913. snprint(buf, sizeof(buf), "[%S]", altr ? altr : L"IMG");
  914. r.min = Pt(0, 0);
  915. r.max.x = 2*Space + stringwidth(font, buf);
  916. r.max.y = 2*Space + font->height;
  917. ci->i = eallocimage(display, r, GREY1, 1, DBlack);
  918. r.min.x += Space;
  919. r.min.y += Space;
  920. string(ci->i, r.min, display->white, ZP, font, buf);
  921. return;
  922. }
  923. nbits = bytesperline(mi->r, mi->depth)*Dy(mi->r);
  924. bits = emalloc(nbits);
  925. unloadmemimage(mi, mi->r, bits, nbits);
  926. /*
  927. /* get rid of alpha channel from transparent gif * /
  928. if(mi->depth == 16){
  929. for(y=1; y<nbits; y+=2)
  930. bits[y>>1] = bits[y];
  931. }
  932. */
  933. i = eallocimage(display, mi->r, mi->chan, 0, DNofill);
  934. loadimage(i, i->r, bits, nbits);
  935. i2 = eallocimage(display, i->r, RGB24, 1, DNofill);
  936. draw(i2, i2->r, display->black, nil, ZP);
  937. draw(i2, i2->r, i, nil, i->r.min);
  938. free(bits);
  939. freememimage(mi);
  940. freeimage(i);
  941. ci->i = i2;
  942. ci->mi = nil;
  943. }
  944. static
  945. void
  946. fixtext1(Item **list)
  947. {
  948. Itext *text, *ntext;
  949. Item *it, *prev;
  950. Rune *s, *s1, *s2;
  951. int n;
  952. if(*list == nil)
  953. return;
  954. prev = nil;
  955. for(it=*list; it!=nil; it=prev->next){
  956. if(it->tag!=Itexttag || forceitem(it))
  957. goto Continue;
  958. text = (Itext *)it;
  959. s = text->s;
  960. while(*s && isspacerune(*s))
  961. s++;
  962. if(!*s){
  963. if(prev == nil)
  964. prev = *list = it->next;
  965. else
  966. prev->next = it->next;
  967. it->next = nil;
  968. freeitems(it);
  969. if(prev == nil)
  970. return;
  971. continue;
  972. }
  973. n = 0;
  974. while(s[n] && !isspacerune(s[n]))
  975. n++;
  976. if(!s[n])
  977. goto Continue;
  978. s1 = runemalloc(n+1);
  979. s1 = runemove(s1, s, n);
  980. s1[n] = L'\0';
  981. s += n;
  982. while(*s && isspacerune(*s))
  983. s++;
  984. if(*s){
  985. n = runestrlen(s);
  986. s2 = runemalloc(n+1);
  987. runemove(s2, s, n);
  988. s2[n] = L'\0';
  989. ntext = emalloc(sizeof(Itext));
  990. ntext->s = s2;
  991. ntext->ascent = text->ascent;
  992. ntext->anchorid = text->anchorid;
  993. ntext->state = text->state&~(IFbrk|IFbrksp|IFnobrk|IFcleft|IFcright);
  994. ntext->tag = text->tag;
  995. ntext->fnt = text->fnt;
  996. ntext->fg = text->fg;
  997. ntext->ul = text->ul;
  998. ntext->next = (Item *)text->next;
  999. text->next = (Item *)ntext;
  1000. }
  1001. free(text->s);
  1002. text->s = s1;
  1003. Continue:
  1004. prev = it;
  1005. }
  1006. }
  1007. void
  1008. fixtext(Page *p)
  1009. {
  1010. Tablecell *c;
  1011. Table *t;
  1012. fixtext1(&p->items);
  1013. for(t=p->doc->tables; t!=nil; t=t->next)
  1014. for(c=t->cells; c!=nil; c=c->next)
  1015. fixtext1(&c->content);
  1016. }
  1017. typedef struct Refresh Refresh;
  1018. struct Refresh
  1019. {
  1020. Page *p;
  1021. Refresh *next;
  1022. };
  1023. static Refresh *refreshs = nil;
  1024. static QLock refreshlock;
  1025. void
  1026. addrefresh(Page *p, char *fmt, ...)
  1027. {
  1028. Refresh *r;
  1029. Rune *s;
  1030. va_list arg;
  1031. if(p->aborting)
  1032. return;
  1033. va_start(arg, fmt);
  1034. s = runevsmprint(fmt, arg);
  1035. va_end(arg);
  1036. if(s == nil)
  1037. error("runevsmprint failed");
  1038. if(p->status){
  1039. free(p->status);
  1040. p->status = nil;
  1041. }
  1042. p->status = s;
  1043. qlock(&refreshlock);
  1044. for(r=refreshs; r!=nil; r=r->next)
  1045. if(r->p == p)
  1046. goto Return;
  1047. incref(p->w); /* flushrefresh will decref */
  1048. r = emalloc(sizeof(Refresh));
  1049. r->p = p;
  1050. r->next = refreshs;
  1051. refreshs = r;
  1052. Return:
  1053. nbsendp(crefresh, nil);
  1054. qunlock(&refreshlock);
  1055. }
  1056. /* called while row is locked */
  1057. void
  1058. flushrefresh(void)
  1059. {
  1060. Refresh *r, *next;
  1061. Page *p;
  1062. qlock(&refreshlock);
  1063. for(r=refreshs; r!=nil; r=next){
  1064. p = r->p;
  1065. if(p->changed==TRUE && p->aborting==FALSE){
  1066. p->changed = FALSE;
  1067. if(p->parent==nil || p->loading==FALSE)
  1068. pagerender(p);
  1069. if(!p->refresh.t)
  1070. pagesetrefresh(p);
  1071. }
  1072. if(p->status){
  1073. winsetstatus(p->w, p->status);
  1074. free(p->status);
  1075. p->status = nil;
  1076. }
  1077. winseturl(p->w);
  1078. winsettag(p->w);
  1079. decref(p->w);
  1080. next = r->next;
  1081. free(r);
  1082. }
  1083. refreshs = nil;
  1084. qunlock(&refreshlock);
  1085. }
  1086. void
  1087. savemouse(Window *w)
  1088. {
  1089. prevmouse = mouse->xy;
  1090. mousew = w;
  1091. }
  1092. void
  1093. restoremouse(Window *w)
  1094. {
  1095. if(mousew!=nil && mousew==w)
  1096. moveto(mousectl, prevmouse);
  1097. mousew = nil;
  1098. }
  1099. void
  1100. clearmouse()
  1101. {
  1102. mousew = nil;
  1103. }
  1104. /*
  1105. * Heuristic city.
  1106. */
  1107. Window*
  1108. makenewwindow(Page *p)
  1109. {
  1110. Column *c;
  1111. Window *w, *bigw, *emptyw;
  1112. Page *emptyp;
  1113. int i, y, el;
  1114. if(activecol)
  1115. c = activecol;
  1116. else if(selpage && selpage->col)
  1117. c = selpage->col;
  1118. else if(p && p->col)
  1119. c = p->col;
  1120. else{
  1121. if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
  1122. error("can't make column");
  1123. c = row.col[row.ncol-1];
  1124. }
  1125. activecol = c;
  1126. if(p==nil || p->w==nil || c->nw==0)
  1127. return coladd(c, nil, nil, -1);
  1128. /* find biggest window and biggest blank spot */
  1129. emptyw = c->w[0];
  1130. bigw = emptyw;
  1131. for(i=1; i<c->nw; i++){
  1132. w = c->w[i];
  1133. /* use >= to choose one near bottom of screen */
  1134. if(Dy(w->page.all) >= Dy(bigw->page.all))
  1135. bigw = w;
  1136. if(w->page.lay==nil && Dy(w->page.all) >= Dy(emptyw->page.all))
  1137. emptyw = w;
  1138. }
  1139. emptyp = &emptyw->page;
  1140. el = Dy(emptyp->all);
  1141. /* if empty space is big, use it */
  1142. if(el>15 || (el>3 && el>(Dy(bigw->page.all)-1)/2))
  1143. y = emptyp->all.max.y;
  1144. else{
  1145. /* if this window is in column and isn't much smaller, split it */
  1146. if(p->col==c && Dy(p->w->r)>2*Dy(bigw->r)/3)
  1147. bigw = p->w;
  1148. y = (bigw->r.min.y + bigw->r.max.y)/2;
  1149. }
  1150. w = coladd(c, nil, nil, y);
  1151. colgrow(w->col, w, 1);
  1152. return w;
  1153. }