charset.pas 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2000 by Florian Klaempfl
  4. member of the Free Pascal development team.
  5. This unit implements several classes for charset conversions
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************
  12. }
  13. unit charset;
  14. {$i fpcdefs.inc}
  15. interface
  16. type
  17. tunicodechar = word;
  18. tunicodestring = ^tunicodechar;
  19. tcsconvert = class
  20. // !!!!!!1constructor create;
  21. end;
  22. tunicodecharmappingflag = (umf_noinfo,umf_leadbyte,umf_undefined,
  23. umf_unused);
  24. punicodecharmapping = ^tunicodecharmapping;
  25. tunicodecharmapping = record
  26. unicode : tunicodechar;
  27. flag : tunicodecharmappingflag;
  28. reserved : byte;
  29. end;
  30. punicodemap = ^tunicodemap;
  31. tunicodemap = record
  32. cpname : string[20];
  33. map : punicodecharmapping;
  34. lastchar : longint;
  35. next : punicodemap;
  36. internalmap : boolean;
  37. end;
  38. tcp2unicode = class(tcsconvert)
  39. end;
  40. function loadunicodemapping(const cpname,f : string) : punicodemap;
  41. procedure registermapping(p : punicodemap);
  42. function getmap(const s : string) : punicodemap;
  43. function mappingavailable(const s : string) : boolean;
  44. function getunicode(c : char;p : punicodemap) : tunicodechar;
  45. function getascii(c : tunicodechar;p : punicodemap) : string;
  46. implementation
  47. var
  48. mappings : punicodemap;
  49. function loadunicodemapping(const cpname,f : string) : punicodemap;
  50. var
  51. data : punicodecharmapping;
  52. datasize : longint;
  53. t : text;
  54. s,hs : string;
  55. scanpos,charpos,unicodevalue : longint;
  56. code : integer;
  57. flag : tunicodecharmappingflag;
  58. p : punicodemap;
  59. lastchar : longint;
  60. begin
  61. lastchar:=-1;
  62. loadunicodemapping:=nil;
  63. datasize:=256;
  64. getmem(data,sizeof(tunicodecharmapping)*datasize);
  65. assign(t,f);
  66. {$I-}
  67. reset(t);
  68. {$I+}
  69. if ioresult<>0 then
  70. begin
  71. freemem(data,sizeof(tunicodecharmapping)*datasize);
  72. exit;
  73. end;
  74. while not(eof(t)) do
  75. begin
  76. readln(t,s);
  77. if (s[1]='0') and (s[2]='x') then
  78. begin
  79. flag:=umf_unused;
  80. scanpos:=3;
  81. hs:='$';
  82. while s[scanpos] in ['0'..'9','A'..'F','a'..'f'] do
  83. begin
  84. hs:=hs+s[scanpos];
  85. inc(scanpos);
  86. end;
  87. val(hs,charpos,code);
  88. if code<>0 then
  89. begin
  90. freemem(data,sizeof(tunicodecharmapping)*datasize);
  91. close(t);
  92. exit;
  93. end;
  94. while not(s[scanpos] in ['0','#']) do
  95. inc(scanpos);
  96. if s[scanpos]='#' then
  97. begin
  98. { special char }
  99. unicodevalue:=$ffff;
  100. hs:=copy(s,scanpos,length(s)-scanpos+1);
  101. if hs='#DBCS LEAD BYTE' then
  102. flag:=umf_leadbyte;
  103. end
  104. else
  105. begin
  106. { C hex prefix }
  107. inc(scanpos,2);
  108. hs:='$';
  109. while s[scanpos] in ['0'..'9','A'..'F','a'..'f'] do
  110. begin
  111. hs:=hs+s[scanpos];
  112. inc(scanpos);
  113. end;
  114. val(hs,unicodevalue,code);
  115. if code<>0 then
  116. begin
  117. freemem(data,sizeof(tunicodecharmapping)*datasize);
  118. close(t);
  119. exit;
  120. end;
  121. if charpos>datasize then
  122. begin
  123. { allocate 1024 bytes more because }
  124. { if we need more than 256 entries it's }
  125. { probably a mbcs with a lot of }
  126. { entries }
  127. datasize:=charpos+1024;
  128. reallocmem(data,sizeof(tunicodecharmapping)*datasize);
  129. end;
  130. flag:=umf_noinfo;
  131. end;
  132. data[charpos].flag:=flag;
  133. data[charpos].unicode:=unicodevalue;
  134. if charpos>lastchar then
  135. lastchar:=charpos;
  136. end;
  137. end;
  138. close(t);
  139. new(p);
  140. p^.lastchar:=lastchar;
  141. p^.cpname:=cpname;
  142. p^.internalmap:=false;
  143. p^.next:=nil;
  144. p^.map:=data;
  145. loadunicodemapping:=p;
  146. end;
  147. procedure registermapping(p : punicodemap);
  148. begin
  149. p^.next:=mappings;
  150. mappings:=p;
  151. end;
  152. function getmap(const s : string) : punicodemap;
  153. var
  154. hp : punicodemap;
  155. const
  156. mapcachep : punicodemap = nil;
  157. begin
  158. if assigned(mapcachep) and
  159. (mapcachep^.cpname=s) then
  160. begin
  161. getmap:=mapcachep;
  162. exit;
  163. end;
  164. hp:=mappings;
  165. while assigned(hp) do
  166. begin
  167. if hp^.cpname=s then
  168. begin
  169. getmap:=hp;
  170. mapcachep:=hp;
  171. exit;
  172. end;
  173. hp:=hp^.next;
  174. end;
  175. getmap:=nil;
  176. end;
  177. function mappingavailable(const s : string) : boolean;
  178. begin
  179. mappingavailable:=getmap(s)<>nil;
  180. end;
  181. function getunicode(c : char;p : punicodemap) : tunicodechar;
  182. begin
  183. if ord(c)<=p^.lastchar then
  184. getunicode:=p^.map[ord(c)].unicode
  185. else
  186. getunicode:=0;
  187. end;
  188. function getascii(c : tunicodechar;p : punicodemap) : string;
  189. var
  190. i : longint;
  191. begin
  192. { at least map to space }
  193. getascii:=#32;
  194. for i:=0 to p^.lastchar do
  195. if p^.map[i].unicode=c then
  196. begin
  197. if i<256 then
  198. getascii:=chr(i)
  199. else
  200. getascii:=chr(i div 256)+chr(i mod 256);
  201. exit;
  202. end;
  203. end;
  204. var
  205. hp : punicodemap;
  206. initialization
  207. mappings:=nil;
  208. finalization
  209. while assigned(mappings) do
  210. begin
  211. hp:=mappings^.next;
  212. if not(mappings^.internalmap) then
  213. begin
  214. freemem(mappings^.map);
  215. dispose(mappings);
  216. end;
  217. mappings:=hp;
  218. end;
  219. end.