widestr.pas 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. This unit contains basic functions for unicode support in the
  4. compiler, this unit is mainly necessary to bootstrap widestring
  5. support ...
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit widestr;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. charset,globtype
  24. ;
  25. type
  26. tcompilerwidechar = word;
  27. tcompilerwidecharptr = ^tcompilerwidechar;
  28. pcompilerwidechar = ^tcompilerwidechar;
  29. pcompilerwidestring = ^_tcompilerwidestring;
  30. _tcompilerwidestring = record
  31. data : pcompilerwidechar;
  32. maxlen,len : SizeInt;
  33. end;
  34. procedure initwidestring(out r : pcompilerwidestring);
  35. procedure donewidestring(var r : pcompilerwidestring);
  36. procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
  37. function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
  38. procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
  39. procedure concatwidestrings(s1,s2 : pcompilerwidestring);
  40. function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
  41. procedure copywidestring(s,d : pcompilerwidestring);
  42. function asciichar2unicode(c : char) : tcompilerwidechar;
  43. function unicode2asciichar(c : tcompilerwidechar) : char;
  44. procedure ascii2unicode(p : pchar;l : SizeInt;r : pcompilerwidestring);
  45. procedure unicode2ascii(r : pcompilerwidestring;p : pchar);
  46. function hasnonasciichars(const p: pcompilerwidestring): boolean;
  47. function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
  48. function cpavailable(const s : string) : boolean;
  49. implementation
  50. uses
  51. cp8859_1,cp850,cp437,
  52. { cyrillic code pages }
  53. cp1251,cp866,cp8859_5,
  54. globals,cutils;
  55. procedure initwidestring(out r : pcompilerwidestring);
  56. begin
  57. new(r);
  58. r^.data:=nil;
  59. r^.len:=0;
  60. r^.maxlen:=0;
  61. end;
  62. procedure donewidestring(var r : pcompilerwidestring);
  63. begin
  64. if assigned(r^.data) then
  65. freemem(r^.data);
  66. dispose(r);
  67. r:=nil;
  68. end;
  69. function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
  70. begin
  71. getcharwidestring:=r^.data[l];
  72. end;
  73. function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
  74. begin
  75. getlengthwidestring:=r^.len;
  76. end;
  77. procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
  78. begin
  79. if r^.maxlen>=l then
  80. exit;
  81. if assigned(r^.data) then
  82. reallocmem(r^.data,sizeof(tcompilerwidechar)*l)
  83. else
  84. getmem(r^.data,sizeof(tcompilerwidechar)*l);
  85. r^.maxlen:=l;
  86. end;
  87. procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
  88. begin
  89. if r^.len>=r^.maxlen then
  90. setlengthwidestring(r,r^.len+16);
  91. r^.data[r^.len]:=c;
  92. inc(r^.len);
  93. end;
  94. procedure concatwidestrings(s1,s2 : pcompilerwidestring);
  95. begin
  96. setlengthwidestring(s1,s1^.len+s2^.len);
  97. move(s2^.data^,s1^.data[s1^.len],s2^.len*sizeof(tcompilerwidechar));
  98. inc(s1^.len,s2^.len);
  99. end;
  100. procedure copywidestring(s,d : pcompilerwidestring);
  101. begin
  102. setlengthwidestring(d,s^.len);
  103. d^.len:=s^.len;
  104. move(s^.data^,d^.data^,s^.len*sizeof(tcompilerwidechar));
  105. end;
  106. function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
  107. var
  108. maxi,temp : SizeInt;
  109. begin
  110. if pointer(s1)=pointer(s2) then
  111. begin
  112. comparewidestrings:=0;
  113. exit;
  114. end;
  115. maxi:=s1^.len;
  116. temp:=s2^.len;
  117. if maxi>temp then
  118. maxi:=Temp;
  119. temp:=compareword(s1^.data^,s2^.data^,maxi);
  120. if temp=0 then
  121. temp:=s1^.len-s2^.len;
  122. comparewidestrings:=temp;
  123. end;
  124. function asciichar2unicode(c : char) : tcompilerwidechar;
  125. var
  126. m : punicodemap;
  127. begin
  128. if (current_settings.sourcecodepage <> 'utf8') then
  129. begin
  130. m:=getmap(current_settings.sourcecodepage);
  131. asciichar2unicode:=getunicode(c,m);
  132. end
  133. else
  134. result:=tcompilerwidechar(c);
  135. end;
  136. function unicode2asciichar(c : tcompilerwidechar) : char;
  137. begin
  138. if word(c)<128 then
  139. unicode2asciichar:=char(word(c))
  140. else
  141. unicode2asciichar:='?';
  142. end;
  143. procedure ascii2unicode(p : pchar;l : SizeInt;r : pcompilerwidestring);
  144. var
  145. source : pchar;
  146. dest : tcompilerwidecharptr;
  147. i : SizeInt;
  148. m : punicodemap;
  149. begin
  150. m:=getmap(current_settings.sourcecodepage);
  151. setlengthwidestring(r,l);
  152. source:=p;
  153. r^.len:=l;
  154. dest:=tcompilerwidecharptr(r^.data);
  155. if (current_settings.sourcecodepage <> 'utf8') then
  156. begin
  157. for i:=1 to l do
  158. begin
  159. dest^:=getunicode(source^,m);
  160. inc(dest);
  161. inc(source);
  162. end;
  163. end
  164. else
  165. begin
  166. for i:=1 to l do
  167. begin
  168. dest^:=tcompilerwidechar(source^);
  169. inc(dest);
  170. inc(source);
  171. end;
  172. end;
  173. end;
  174. procedure unicode2ascii(r : pcompilerwidestring;p:pchar);
  175. (*
  176. var
  177. m : punicodemap;
  178. i : longint;
  179. begin
  180. m:=getmap(current_settings.sourcecodepage);
  181. { should be a very good estimation :) }
  182. setlengthwidestring(r,length(s));
  183. // !!!! MBCS
  184. for i:=1 to length(s) do
  185. begin
  186. end;
  187. end;
  188. *)
  189. var
  190. source : tcompilerwidecharptr;
  191. dest : pchar;
  192. i : longint;
  193. begin
  194. { This routine must work the same as the
  195. the routine in the RTL to have the same compile time (for constant strings)
  196. and runtime conversion (for variables) }
  197. source:=tcompilerwidecharptr(r^.data);
  198. dest:=p;
  199. for i:=1 to r^.len do
  200. begin
  201. if word(source^)<128 then
  202. dest^:=char(word(source^))
  203. else
  204. dest^:='?';
  205. inc(dest);
  206. inc(source);
  207. end;
  208. end;
  209. function hasnonasciichars(const p: pcompilerwidestring): boolean;
  210. var
  211. source : tcompilerwidecharptr;
  212. i : longint;
  213. begin
  214. source:=tcompilerwidecharptr(p^.data);
  215. result:=true;
  216. for i:=1 to p^.len do
  217. begin
  218. if word(source^)>=128 then
  219. exit;
  220. inc(source);
  221. end;
  222. result:=false;
  223. end;
  224. function cpavailable(const s : string) : boolean;
  225. begin
  226. cpavailable:=mappingavailable(lower(s));
  227. end;
  228. end.