char.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "a.h"
  2. /*
  3. * Translate Unicode to HTML by asking tcs(1).
  4. * This way we don't have yet another table.
  5. */
  6. Rune*
  7. rune2html(Rune r)
  8. {
  9. static Biobuf b;
  10. static int fd = -1;
  11. static Rune **tcscache[256];
  12. int p[2];
  13. char *q;
  14. if(r == '\n')
  15. return L("\n");
  16. if(((uint)r&~0xFFFF) != 0){
  17. /* The cache must grow a lot to handle them */
  18. fprint(2, "%s: can't handle rune '%C'\n", argv0, r);
  19. return L("?");
  20. }
  21. if(tcscache[r>>8] && tcscache[r>>8][r&0xFF])
  22. return tcscache[r>>8][r&0xFF];
  23. if(fd < 0){
  24. if(pipe(p) < 0)
  25. sysfatal("pipe: %r");
  26. switch(fork()){
  27. case -1:
  28. sysfatal("fork: %r");
  29. case 0:
  30. dup(p[0], 0);
  31. dup(p[1], 1);
  32. close(p[0]);
  33. close(p[1]);
  34. execl("/bin/tcs", "tcs", "-t", "html", nil);
  35. _exits(0);
  36. default:
  37. fd = p[1];
  38. Binit(&b, p[0], OREAD);
  39. break;
  40. }
  41. }
  42. /* HACK: extra newlines force rune+\n through tcs now */
  43. fprint(fd, "%C\n\n\n\n", r);
  44. q = Brdline(&b, '\n');
  45. while (q != nil && *q == '\n')
  46. q = Brdline(&b, '\n');
  47. if(q == nil)
  48. sysfatal("tcs: early eof");
  49. q[Blinelen(&b)-1] = 0;
  50. if(tcscache[r>>8] == nil)
  51. tcscache[r>>8] = emalloc(256*sizeof tcscache[0][0]);
  52. tcscache[r>>8][r&0xFF] = erunesmprint("%s", q);
  53. return tcscache[r>>8][r&0xFF];
  54. }
  55. /*
  56. * Translate troff to Unicode by looking in troff's utfmap.
  57. * This way we don't have yet another hard-coded table.
  58. */
  59. typedef struct Trtab Trtab;
  60. struct Trtab
  61. {
  62. char t[UTFmax];
  63. Rune r;
  64. };
  65. static Trtab trtab[200];
  66. int ntrtab;
  67. static Trtab trinit[] =
  68. {
  69. "pl", Upl,
  70. "eq", Ueq,
  71. "em", 0x2014,
  72. "en", 0x2013,
  73. "mi", Umi,
  74. "fm", 0x2032,
  75. };
  76. Rune
  77. troff2rune(Rune *rs)
  78. {
  79. char *file, *f[10], *p, s[3];
  80. int i, nf;
  81. Biobuf *b;
  82. if(rs[0] >= Runeself || rs[1] >= Runeself)
  83. return Runeerror;
  84. s[0] = rs[0];
  85. s[1] = rs[1];
  86. s[2] = 0;
  87. if(ntrtab == 0){
  88. for(i=0; i<nelem(trinit) && ntrtab < nelem(trtab); i++){
  89. trtab[ntrtab] = trinit[i];
  90. ntrtab++;
  91. }
  92. file = "/sys/lib/troff/font/devutf/utfmap";
  93. if((b = Bopen(file, OREAD)) == nil)
  94. sysfatal("open %s: %r", file);
  95. while((p = Brdline(b, '\n')) != nil){
  96. p[Blinelen(b)-1] = 0;
  97. nf = getfields(p, f, nelem(f), 0, "\t");
  98. for(i=0; i+2<=nf && ntrtab<nelem(trtab); i+=2){
  99. chartorune(&trtab[ntrtab].r, f[i]);
  100. memmove(trtab[ntrtab].t, f[i+1], 2);
  101. ntrtab++;
  102. }
  103. }
  104. Bterm(b);
  105. if(ntrtab >= nelem(trtab))
  106. fprint(2, "%s: trtab too small\n", argv0);
  107. }
  108. for(i=0; i<ntrtab; i++)
  109. if(strcmp(s, trtab[i].t) == 0)
  110. return trtab[i].r;
  111. return Runeerror;
  112. }