html.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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. /*
  10. * Emit html. Keep track of tags so that user doesn't have to.
  11. */
  12. #include "a.h"
  13. typedef struct Tag Tag;
  14. struct Tag
  15. {
  16. Tag *next;
  17. Rune *id;
  18. Rune *open;
  19. Rune *close;
  20. };
  21. Tag *tagstack;
  22. Tag *tagset;
  23. int hidingset;
  24. static Rune*
  25. closingtag(Rune *s)
  26. {
  27. Rune *t;
  28. Rune *p0, *p;
  29. t = runemalloc(sizeof(Rune));
  30. if(s == nil)
  31. return t;
  32. for(p=s; *p; p++){
  33. if(*p == Ult){
  34. p++;
  35. if(*p == '/'){
  36. while(*p && *p != Ugt)
  37. p++;
  38. goto close;
  39. }
  40. p0 = p;
  41. while(*p && !isspacerune(*p) && *p != Uspace && *p != Ugt)
  42. p++;
  43. t = runerealloc(t, 1+(p-p0)+2+runestrlen(t)+1);
  44. runemove(t+(p-p0)+3, t, runestrlen(t)+1);
  45. t[0] = Ult;
  46. t[1] = '/';
  47. runemove(t+2, p0, p-p0);
  48. t[2+(p-p0)] = Ugt;
  49. }
  50. if(*p == Ugt && p>s && *(p-1) == '/'){
  51. close:
  52. for(p0=t+1; *p0 && *p0 != Ult; p0++)
  53. ;
  54. runemove(t, p0, runestrlen(p0)+1);
  55. }
  56. }
  57. return t;
  58. }
  59. void
  60. html(Rune *id, Rune *s)
  61. {
  62. Rune *es;
  63. Tag *t, *tt, *next;
  64. br();
  65. hideihtml(); /* br already did, but be paranoid */
  66. for(t=tagstack; t; t=t->next){
  67. if(runestrcmp(t->id, id) == 0){
  68. for(tt=tagstack;; tt=next){
  69. next = tt->next;
  70. free(tt->id);
  71. free(tt->open);
  72. out(tt->close);
  73. outrune('\n');
  74. free(tt->close);
  75. free(tt);
  76. if(tt == t){
  77. tagstack = next;
  78. goto cleared;
  79. }
  80. }
  81. }
  82. }
  83. cleared:
  84. if(s == nil || s[0] == 0)
  85. return;
  86. out(s);
  87. outrune('\n');
  88. es = closingtag(s);
  89. if(es[0] == 0){
  90. free(es);
  91. return;
  92. }
  93. if(runestrcmp(id, L("-")) == 0){
  94. out(es);
  95. outrune('\n');
  96. free(es);
  97. return;
  98. }
  99. t = emalloc(sizeof *t);
  100. t->id = erunestrdup(id);
  101. t->close = es;
  102. t->next = tagstack;
  103. tagstack = t;
  104. }
  105. void
  106. closehtml(void)
  107. {
  108. Tag *t, *next;
  109. br();
  110. hideihtml();
  111. for(t=tagstack; t; t=next){
  112. next = t->next;
  113. out(t->close);
  114. outrune('\n');
  115. free(t->id);
  116. free(t->close);
  117. free(t);
  118. }
  119. }
  120. static void
  121. rshow(Tag *t, Tag *end)
  122. {
  123. if(t == nil || t == end)
  124. return;
  125. rshow(t->next, end);
  126. out(t->open);
  127. }
  128. void
  129. ihtml(Rune *id, Rune *s)
  130. {
  131. Tag *t, *tt, **l;
  132. for(t=tagset; t; t=t->next){
  133. if(runestrcmp(t->id, id) == 0){
  134. if(s && t->open && runestrcmp(t->open, s) == 0)
  135. return;
  136. for(l=&tagset; (tt=*l); l=&tt->next){
  137. if(!hidingset)
  138. out(tt->close);
  139. if(tt == t)
  140. break;
  141. }
  142. *l = t->next;
  143. free(t->id);
  144. free(t->close);
  145. free(t->open);
  146. free(t);
  147. if(!hidingset)
  148. rshow(tagset, *l);
  149. goto cleared;
  150. }
  151. }
  152. cleared:
  153. if(s == nil || s[0] == 0)
  154. return;
  155. t = emalloc(sizeof *t);
  156. t->id = erunestrdup(id);
  157. t->open = erunestrdup(s);
  158. t->close = closingtag(s);
  159. if(!hidingset)
  160. out(s);
  161. t->next = tagset;
  162. tagset = t;
  163. }
  164. void
  165. hideihtml(void)
  166. {
  167. Tag *t;
  168. if(hidingset)
  169. return;
  170. hidingset = 1;
  171. for(t=tagset; t; t=t->next)
  172. out(t->close);
  173. }
  174. void
  175. showihtml(void)
  176. {
  177. if(!hidingset)
  178. return;
  179. hidingset = 0;
  180. rshow(tagset, nil);
  181. }
  182. int
  183. e_lt(void)
  184. {
  185. return Ult;
  186. }
  187. int
  188. e_gt(void)
  189. {
  190. return Ugt;
  191. }
  192. int
  193. e_at(void)
  194. {
  195. return Uamp;
  196. }
  197. int
  198. e_tick(void)
  199. {
  200. return Utick;
  201. }
  202. int
  203. e_btick(void)
  204. {
  205. return Ubtick;
  206. }
  207. int
  208. e_minus(void)
  209. {
  210. return Uminus;
  211. }
  212. void
  213. r_html(Rune *name)
  214. {
  215. Rune *id, *line, *p;
  216. id = copyarg();
  217. line = readline(HtmlMode);
  218. for(p=line; *p; p++){
  219. switch(*p){
  220. case '<':
  221. *p = Ult;
  222. break;
  223. case '>':
  224. *p = Ugt;
  225. break;
  226. case '&':
  227. *p = Uamp;
  228. break;
  229. case ' ':
  230. *p = Uspace;
  231. break;
  232. }
  233. }
  234. if(name[0] == 'i')
  235. ihtml(id, line);
  236. else
  237. html(id, line);
  238. free(id);
  239. free(line);
  240. }
  241. char defaultfont[] =
  242. ".ihtml f1\n"
  243. ".ihtml f\n"
  244. ".ihtml f <span style=\"font-size: \\n(.spt\">\n"
  245. ".if \\n(.f==2 .ihtml f1 <i>\n"
  246. ".if \\n(.f==3 .ihtml f1 <b>\n"
  247. ".if \\n(.f==4 .ihtml f1 <b><i>\n"
  248. ".if \\n(.f==5 .ihtml f1 <tt>\n"
  249. ".if \\n(.f==6 .ihtml f1 <tt><i>\n"
  250. "..\n"
  251. ;
  252. void
  253. htmlinit(void)
  254. {
  255. addraw(L("html"), r_html);
  256. addraw(L("ihtml"), r_html);
  257. addesc('<', e_lt, CopyMode);
  258. addesc('>', e_gt, CopyMode);
  259. addesc('\'', e_tick, CopyMode);
  260. addesc('`', e_btick, CopyMode);
  261. addesc('-', e_minus, CopyMode);
  262. addesc('@', e_at, CopyMode);
  263. ds(L("font"), L(defaultfont));
  264. }