conv_gbk.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #ifdef PLAN9
  2. #include <u.h>
  3. #include <libc.h>
  4. #include <bio.h>
  5. #else
  6. #include <stdio.h>
  7. #include <unistd.h>
  8. #include "plan9.h"
  9. #endif
  10. #include "hdr.h"
  11. #include "conv.h"
  12. #include "gbk.h"
  13. static void
  14. gbkproc(int c, Rune **r, long input_loc)
  15. {
  16. static enum { state0, state1 } state = state0;
  17. static int lastc;
  18. long ch, cold = c;
  19. switch(state)
  20. {
  21. case state0: /* idle state */
  22. if(c < 0)
  23. return;
  24. if(c >= 0x80){
  25. lastc = c;
  26. state = state1;
  27. return;
  28. }
  29. emit(c);
  30. return;
  31. case state1: /* seen a font spec */
  32. ch = -1;
  33. c = lastc<<8 | c;
  34. if(c >= GBKMIN && c < GBKMAX)
  35. ch = tabgbk[c - GBKMIN];
  36. if(ch < 0){
  37. nerrors++;
  38. if(squawk)
  39. EPR "%s: bad gbk glyph %d (from 0x%x,0x%lx) near byte %ld in %s\n", argv0, (c & 0xFF), lastc, cold, input_loc, file);
  40. if(!clean)
  41. emit(BADMAP);
  42. state = state0;
  43. return;
  44. }
  45. emit(ch);
  46. state = state0;
  47. }
  48. }
  49. void
  50. gbk_in(int fd, long *notused, struct convert *out)
  51. {
  52. Rune ob[N];
  53. Rune *r, *re;
  54. uchar ibuf[N];
  55. int n, i;
  56. long nin;
  57. USED(notused);
  58. r = ob;
  59. re = ob+N-3;
  60. nin = 0;
  61. while((n = read(fd, ibuf, sizeof ibuf)) > 0){
  62. for(i = 0; i < n; i++){
  63. gbkproc(ibuf[i], &r, nin++);
  64. if(r >= re){
  65. OUT(out, ob, r-ob);
  66. r = ob;
  67. }
  68. }
  69. if(r > ob){
  70. OUT(out, ob, r-ob);
  71. r = ob;
  72. }
  73. }
  74. gbkproc(-1, &r, nin);
  75. if(r > ob)
  76. OUT(out, ob, r-ob);
  77. OUT(out, ob, 0);
  78. }
  79. void
  80. gbk_out(Rune *base, int n, long *notused)
  81. {
  82. char *p;
  83. int i;
  84. Rune r;
  85. static int first = 1;
  86. USED(notused);
  87. if(first){
  88. first = 0;
  89. for(i = 0; i < NRUNE; i++)
  90. tab[i] = -1;
  91. for(i = GBKMIN; i < GBKMAX; i++)
  92. tab[tabgbk[i-GBKMIN]] = i;
  93. }
  94. nrunes += n;
  95. p = obuf;
  96. for(i = 0; i < n; i++){
  97. r = base[i];
  98. if(r < 0x80)
  99. *p++ = r;
  100. else {
  101. if(tab[r] != -1){
  102. r = tab[r];
  103. *p++ = (r>>8) & 0xFF;
  104. *p++ = r & 0xFF;
  105. continue;
  106. }
  107. if(squawk)
  108. EPR "%s: rune 0x%x not in output cs\n", argv0, r);
  109. nerrors++;
  110. if(clean)
  111. continue;
  112. *p++ = BYTEBADMAP;
  113. }
  114. }
  115. noutput += p-obuf;
  116. if(p > obuf)
  117. write(1, obuf, p-obuf);
  118. }