widestr.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. {$ifdef VER2_2}ccharset{$else VER2_2}charset{$endif VER2_2},globtype;
  24. type
  25. tcompilerwidechar = word;
  26. tcompilerwidecharptr = ^tcompilerwidechar;
  27. pcompilerwidechar = ^tcompilerwidechar;
  28. pcompilerwidestring = ^_tcompilerwidestring;
  29. _tcompilerwidestring = record
  30. data : pcompilerwidechar;
  31. maxlen,len : SizeInt;
  32. end;
  33. procedure initwidestring(out r : pcompilerwidestring);
  34. procedure donewidestring(var r : pcompilerwidestring);
  35. procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
  36. function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
  37. procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
  38. procedure concatwidestrings(s1,s2 : pcompilerwidestring);
  39. function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
  40. procedure copywidestring(s,d : pcompilerwidestring);
  41. function asciichar2unicode(c : char) : tcompilerwidechar;
  42. function unicode2asciichar(c : tcompilerwidechar) : char;
  43. procedure ascii2unicode(p : pchar;l : SizeInt;r : pcompilerwidestring;codepagetranslation : boolean = true);
  44. procedure unicode2ascii(r : pcompilerwidestring;p : pchar);
  45. function hasnonasciichars(const p: pcompilerwidestring): boolean;
  46. function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
  47. function cpavailable(const s : string) : boolean;
  48. implementation
  49. uses
  50. cp8859_1,cp850,cp437,
  51. { cyrillic code pages }
  52. cp1251,cp866,cp8859_5,
  53. globals,cutils;
  54. procedure initwidestring(out r : pcompilerwidestring);
  55. begin
  56. new(r);
  57. r^.data:=nil;
  58. r^.len:=0;
  59. r^.maxlen:=0;
  60. end;
  61. procedure donewidestring(var r : pcompilerwidestring);
  62. begin
  63. if assigned(r^.data) then
  64. freemem(r^.data);
  65. dispose(r);
  66. r:=nil;
  67. end;
  68. function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
  69. begin
  70. getcharwidestring:=r^.data[l];
  71. end;
  72. function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
  73. begin
  74. getlengthwidestring:=r^.len;
  75. end;
  76. procedure growwidestring(r : pcompilerwidestring;l : SizeInt);
  77. begin
  78. if r^.maxlen>=l then
  79. exit;
  80. if assigned(r^.data) then
  81. reallocmem(r^.data,sizeof(tcompilerwidechar)*l)
  82. else
  83. getmem(r^.data,sizeof(tcompilerwidechar)*l);
  84. r^.maxlen:=l;
  85. end;
  86. procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
  87. begin
  88. r^.len:=l;
  89. if l>r^.maxlen then
  90. growwidestring(r,l);
  91. end;
  92. procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
  93. begin
  94. if r^.len>=r^.maxlen then
  95. growwidestring(r,r^.len+16);
  96. r^.data[r^.len]:=c;
  97. inc(r^.len);
  98. end;
  99. procedure concatwidestrings(s1,s2 : pcompilerwidestring);
  100. begin
  101. growwidestring(s1,s1^.len+s2^.len);
  102. move(s2^.data^,s1^.data[s1^.len],s2^.len*sizeof(tcompilerwidechar));
  103. inc(s1^.len,s2^.len);
  104. end;
  105. procedure copywidestring(s,d : pcompilerwidestring);
  106. begin
  107. setlengthwidestring(d,s^.len);
  108. move(s^.data^,d^.data^,s^.len*sizeof(tcompilerwidechar));
  109. end;
  110. function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
  111. var
  112. maxi,temp : SizeInt;
  113. begin
  114. if pointer(s1)=pointer(s2) then
  115. begin
  116. comparewidestrings:=0;
  117. exit;
  118. end;
  119. maxi:=s1^.len;
  120. temp:=s2^.len;
  121. if maxi>temp then
  122. maxi:=Temp;
  123. temp:=compareword(s1^.data^,s2^.data^,maxi);
  124. if temp=0 then
  125. temp:=s1^.len-s2^.len;
  126. comparewidestrings:=temp;
  127. end;
  128. function asciichar2unicode(c : char) : tcompilerwidechar;
  129. var
  130. m : punicodemap;
  131. begin
  132. if (current_settings.sourcecodepage <> 'utf8') then
  133. begin
  134. m:=getmap(current_settings.sourcecodepage);
  135. asciichar2unicode:=getunicode(c,m);
  136. end
  137. else
  138. result:=tcompilerwidechar(c);
  139. end;
  140. function unicode2asciichar(c : tcompilerwidechar) : char;
  141. begin
  142. if word(c)<128 then
  143. unicode2asciichar:=char(word(c))
  144. else
  145. unicode2asciichar:='?';
  146. end;
  147. procedure ascii2unicode(p : pchar;l : SizeInt;r : pcompilerwidestring;codepagetranslation : boolean = true);
  148. var
  149. source : pchar;
  150. dest : tcompilerwidecharptr;
  151. i : SizeInt;
  152. m : punicodemap;
  153. begin
  154. m:=getmap(current_settings.sourcecodepage);
  155. setlengthwidestring(r,l);
  156. source:=p;
  157. dest:=tcompilerwidecharptr(r^.data);
  158. if (current_settings.sourcecodepage <> 'utf8') and
  159. codepagetranslation then
  160. begin
  161. for i:=1 to l do
  162. begin
  163. dest^:=getunicode(source^,m);
  164. inc(dest);
  165. inc(source);
  166. end;
  167. end
  168. else
  169. begin
  170. for i:=1 to l do
  171. begin
  172. dest^:=tcompilerwidechar(source^);
  173. inc(dest);
  174. inc(source);
  175. end;
  176. end;
  177. end;
  178. procedure unicode2ascii(r : pcompilerwidestring;p:pchar);
  179. (*
  180. var
  181. m : punicodemap;
  182. i : longint;
  183. begin
  184. m:=getmap(current_settings.sourcecodepage);
  185. { should be a very good estimation :) }
  186. setlengthwidestring(r,length(s));
  187. // !!!! MBCS
  188. for i:=1 to length(s) do
  189. begin
  190. end;
  191. end;
  192. *)
  193. var
  194. source : tcompilerwidecharptr;
  195. dest : pchar;
  196. i : longint;
  197. begin
  198. { This routine must work the same as the
  199. the routine in the RTL to have the same compile time (for constant strings)
  200. and runtime conversion (for variables) }
  201. source:=tcompilerwidecharptr(r^.data);
  202. dest:=p;
  203. for i:=1 to r^.len do
  204. begin
  205. if word(source^)<128 then
  206. dest^:=char(word(source^))
  207. else
  208. dest^:='?';
  209. inc(dest);
  210. inc(source);
  211. end;
  212. end;
  213. function hasnonasciichars(const p: pcompilerwidestring): boolean;
  214. var
  215. source : tcompilerwidecharptr;
  216. i : longint;
  217. begin
  218. source:=tcompilerwidecharptr(p^.data);
  219. result:=true;
  220. for i:=1 to p^.len do
  221. begin
  222. if word(source^)>=128 then
  223. exit;
  224. inc(source);
  225. end;
  226. result:=false;
  227. end;
  228. function cpavailable(const s : string) : boolean;
  229. begin
  230. cpavailable:=mappingavailable(lower(s));
  231. end;
  232. end.