zeoslib  UNKNOWN
 All Files
ZCompatibility.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { Compatibility Classes and Functions }
5 { }
6 { Originally written by Sergey Seroukhov }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
20 { }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
39 { }
40 { }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZCompatibility;
53 
54 interface
55 
56 {$I ZCore.inc}
57 
58 uses
59  Variants,
60 {$IFDEF FPC}
61  {$IFDEF UNIX}
62  dynlibs,
63  {$endif}
64 {$ENDIF}
65  {$IFDEF WITH_WIDESTRUTILS}
66  WideStrUtils,
67  {$ENDIF}
68  {$If defined(MSWINDOWS) and not defined(FPC)}
69  Windows,
70  {$IFEND}
71  Classes,
72  {$IFDEF MSEgui}mclasses,{$ENDIF}
73  {$IFDEF WITH_LCONVENCODING} LConvEncoding,{$ENDIF}
74  Types,
75  SysUtils;
76 
77 type
78 {$IFDEF FPC}
79  ULong = {$IFDEF WIN64}LongWord{$ELSE}PTRUINT{$ENDIF};
80  // EgonHugeist: Use always a 4Byte Integer as long the PlainDriver dll's are 32Bit for Windows64
81  //on the other hand MySQL64 and FB64 have problems on Win64!
82  ULongLong = QWord;
83  NativeInt = PtrInt;
84  NativeUInt = PtrUInt;
85  PNativeUInt = ^NativeUInt;
86 {$ELSE}
87  {$IFNDEF DELPHI16_UP}
88  NativeInt = Integer;
89  NativeUInt = LongWord;
90  PNativeUInt = ^NativeUInt;
91  PWord = ^Word; // M.A.
92  {$ENDIF}
93  ULong = LongWord;
94  ULongLong = {$IFDEF WITH_UINT64}Uint64{$ELSE}Int64{$ENDIF}; //delphi donĀ“t have Unsigned Int64 type
95 {$ENDIF}
96  PULong = ^ULong;
97  PULongLong = ^ULongLong;
98 
99  UInt = LongWord;
100  PUInt = ^UInt;
101  ZPPWideChar = ^PWideChar;//BCB issue: PPWideChar is not part of system
102 
103  TObjectDynArray = array of TObject;
104 {$IFDEF FPC}
105 type
106  TDBScreenCursor = (dcrDefault, dcrHourGlass, dcrSQLWait, dcrOther);
107 
108  IDBScreen = interface
109  ['{29A1C508-6ADC-44CD-88DE-4F51B25D5995}']
110  function GetCursor: TDBScreenCursor;
111  procedure SetCursor(Cursor: TDBScreenCursor);
112 
113  property Cursor: TDBScreenCursor read GetCursor write SetCursor;
114  end;
115 
116 var
117  LoginDialogProc: function (const ADatabaseName: string; var AUserName,
118  APassword: string): Boolean;
119  DBScreen: IDBScreen;
120 {$ENDIF}
121 
122 {$IFNDEF FPC} //delphi and windows
123 const
124  LineEnding = #13#10;
125  Brackets = ['(',')','[',']','{','}'];
126  StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
127 
128 function Hash(S : AnsiString) : LongWord;
129 function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
130 
131 {$ENDIF}
132 
133 {$IFDEF WINDOWS}
134 const SharedSuffix='.dll';
135 {$ELSE}
136  {$IFDEF DARWIN}
137  const SharedSuffix='.dylib';
138  {$ELSE}
139  {$IFDEF UNIX}
140  const SharedSuffix='.so';
141  {$ELSE}
142  const SharedSuffix='.dll'; //Delphi
143  {$ENDIF}
144  {$ENDIF}
145 {$ENDIF}
146 
147 {$IFDEF UNIX}
148  {$IFDEF FPC}
149 const
150  RTLD_GLOBAL = $101;
151  INVALID_HANDLE_VALUE = 0;
152 
153 type
154  HMODULE = PtrInt;
155 
156 function LoadLibrary(ModuleName: PChar): HMODULE;
157 function FreeLibrary(Module: HMODULE): LongBool;
158 function GetProcAddress(Module: HMODULE; Proc: PChar): Pointer;
159  {$ENDIF}
160 {$ENDIF}
161 
162 {EgonHugeist:}
163 type
164  {$IFNDEF WITH_RAWBYTESTRING}
165  RawByteString = AnsiString;
166  {$ENDIF}
167 
168  ZWideString = {$IFDEF PWIDECHAR_IS_PUNICODECHAR}UnicodeString{$ELSE}WideString{$ENDIF};
169 
170 type
171  {declare move or converter functions for the String Types}
172  TZAnsiToRaw = function (const Src: AnsiString; const RawCP: Word): RawByteString;
173  TZRawToAnsi = function (const Src: RawByteString; const RawCP: Word): AnsiString;
174  TZAnsiToUTF8 = function (const Src: AnsiString): UTF8String;
175  TZUTF8ToAnsi = function (const Src: UTF8String): AnsiString;
176  TZRawToUTF8 = function (const Src: RawByteString; const CP: Word): UTF8String;
177  TZUTF8ToRaw = function (const Src: UTF8String; const CP: Word): RawByteString;
178  TZRawToString = function (const Src: RawByteString; const RawCP, StringCP: Word): String;
179  TZStringToRaw = function (const Src: String; const StringCP, RawCP: Word): RawByteString;
180  TZUTF8ToString = function (const Src: UTF8String; const StringCP: Word): String;
181  TZStringToUTF8 = function (const Src: String; const StringCP: Word): UTF8String;
182  TZAnsiToString = function (const Src: AnsiString; const StringCP: Word): String;
183  TZStringToAnsi = function (const Src: String; const StringCP: Word): AnsiString;
184  TZRawToUnicode = function (const S: RawByteString; const CP: Word): ZWideString;
185  TZUnicodeToRaw = function (const US: ZWideString; CP: Word): RawByteString;
186  TZUnicodeToString = function (const Src: ZWideString; const StringCP: Word): String;
187  TZStringToUnicode = function (const Src: String; const StringCP: Word): ZWideString;
188 
189  {** Defines the Target Ansi codepages for the Controls }
190  TZControlsCodePage = ({$IFDEF UNICODE}cCP_UTF16, cCP_UTF8, cGET_ACP{$ELSE}{$IFDEF FPC}cCP_UTF8, cCP_UTF16, cGET_ACP{$ELSE}cGET_ACP, cCP_UTF8, cCP_UTF16{$ENDIF}{$ENDIF});
191 
192  TZCharEncoding = (
193  ceDefault, //Internal switch for the two Functions below do not use it as a CodePage-declaration!
194  ceAnsi, //Base Ansi-String: prefered CodePage
195  ceUTF8, //UTF8_Unicode: 1-4Byte/Char
196  ceUTF16, //Wide or Unicode string encoding for Field-mapping
197  ceUTF32); //reserved
198 
199  {Here it's possible to add some more, to handle the Ansi->Unicode-Translations}
200 
201  PZCodePage = ^TZCodePage;
202  TZCodePage = record
203  Name: String; //Name of Client-CharacterSet
204  ID: Integer; //may be an ordinal value of predefined Types or the database used id}
205  CharWidth: Integer; //count of Bytes per char
206  Encoding: TZCharEncoding; //The Type of String-Translation handling
207  CP: Word; //The CodePage the AnsiString must have to
208  ZAlias: String; //A possible (saver?) CharacterSet which is more Zeos compatible... If it's empty it will be ignored!!!
209  IsStringFieldCPConsistent: Boolean; //Is the current client characterset codepage consistent for all codepages?
210  end;
211 
212  TConvertEncodingFunctions = record
213  ZAnsiToUTF8: TZAnsiToUTF8;
214  ZUTF8ToAnsi: TZUTF8ToAnsi;
215  ZUTF8ToString: TZUTF8ToString;
216  ZStringToUTF8: TZStringToUTF8;
217  ZAnsiToRaw: TZAnsiToRaw;
218  ZRawToAnsi: TZRawToAnsi;
219  ZRawToUTF8: TZRawToUTF8;
220  ZUTF8ToRaw: TZUTF8ToRaw;
221  ZStringToRaw: TZStringToRaw;
222  ZRawToString: TZRawToString;
223  ZAnsiToString: TZAnsiToString;
224  ZStringToAnsi: TZStringToAnsi;
225  ZUnicodeToRaw: TZUnicodeToRaw;
226  ZRawToUnicode: TZRawToUnicode;
227  ZUnicodeToString: TZUnicodeToString;
228  ZStringToUnicode: TZStringToUnicode;
229  end;
230 
231  PZConSettings = ^TZConSettings;
232  TZConSettings = record
233  AutoEncode: Boolean; //Check Encoding and or convert string with FromCP ToCP
234  CPType: TZControlsCodePage; //the CP-Settings type the controls do expect
235  CTRL_CP: Word; //Target CP of string conversion (CP_ACP/CP_UPF8)
236  ConvFuncs: TConvertEncodingFunctions; //a rec for the Convert functions used by the objects
237  ClientCodePage: PZCodePage; //The codepage informations of the current characterset
238  DateFormat: String;
239  {$IFDEF WITH_LCONVENCODING}
240  PlainConvertFunc: TConvertEncodingFunction;
241  DbcConvertFunc: TConvertEncodingFunction;
242  {$ENDIF}
243  end;
244 
245  TZCodePagedObject = Class(TInterfacedObject)
246  private
247  FConSettings: PZConSettings;
248  protected
249  function ZDbcString(const Ansi: RawByteString; ConSettings: PZConSettings): String; overload;
250  function ZDbcString(const Ansi: RawByteString; FromCP: Word): String; overload;
251  function ZDbcString(const Ansi: RawByteString; const Encoding: TZCharEncoding = ceDefault): String; overload;
252  function ZDbcString(const AStr: ZWideString; const Encoding: TZCharEncoding = ceDefault): String; overload;
253  function ZDbcUnicodeString(const AStr: RawByteString): ZWideString; overload;
254  function ZDbcUnicodeString(const AStr: RawByteString; const FromCP: Word): ZWideString; overload;
255  {$IFDEF WITH_RAWBYTESTRING}
256  function ZDbcUnicodeString(const AStr: String; const FromCP: Word): ZWideString; overload;
257  {$ENDIF}
258  function ZPlainString(const AStr: String; ConSettings: PZConSettings): RawByteString; overload;
259  function ZPlainString(const AStr: String; ConSettings: PZConSettings; const ToCP: Word): RawByteString; overload;
260  function ZPlainString(const AStr: String; const Encoding: TZCharEncoding = ceDefault): RawByteString; overload;
261  function ZPlainString(const AStr: WideString; const Encoding: TZCharEncoding = ceDefault): RawByteString; overload;
262  function ZPlainString(const AStr: WideString; ConSettings: PZConSettings): RawByteString; overload;
263  function ZPlainString(const AStr: WideString; ConSettings: PZConSettings; const ToCP: Word): RawByteString; overload;
264  function ZPlainUnicodeString(const AStr: String): WideString;
265  procedure SetConSettingsFromInfo(Info: TStrings);
266  property ConSettings: PZConSettings read FConSettings write FConSettings;
267  public
268  destructor Destroy; override;
269  end;
270 
271  {$IFDEF WITH_LCONVENCODING}
272  function NoConvert(const s: string): string;
273  {$ENDIF}
274 
275 
276 {$IF not Declared(DetectUTF8Encoding)}
277 {$DEFINE ZDetectUTF8Encoding}
278 Type
279  TEncodeType = (etUSASCII, etUTF8, etANSI);
280 
281 function DetectUTF8Encoding(Ansi: RawByteString): TEncodeType;
282 {$IFEND}
283 
284 {$IFNDEF WITH_CHARINSET}
285 function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean; overload;
286 function CharInSet(C: WideChar; const CharSet: TSysCharSet): Boolean; overload;
287 {$ENDIF}
288 
289 {$IF not Declared(UTF8ToString)}
290 {$DEFINE ZUTF8ToString}
291 function UTF8ToString(const s: RawByteString): ZWideString;
292 {$IFEND}
293 
294 var
295  ClientCodePageDummy: TZCodepage =
296  (Name: ''; ID: 0; CharWidth: 1; Encoding: ceAnsi;
297  CP: $ffff; ZAlias: '');
298 
299  ConSettingsDummy: TZConSettings =
300  (AutoEncode: False;
301  CPType: {$IFDEF DELPHI}{$IFDEF UNICODE}cCP_UTF16{$ELSE}cGET_ACP{$ENDIF}{$ELSE}cCP_UTF8{$ENDIF};
302  ClientCodePage: @ClientCodePageDummy;
303  {$IFDEF WITH_LCONVENCODING}
304  PlainConvertFunc: @NoConvert;
305  DbcConvertFunc: @NoConvert;
306  {$ENDIF}
307  );
308 
309 implementation
310 
311 uses ZEncoding;
312 
313 {$IFDEF ZDetectUTF8Encoding}
314 function DetectUTF8Encoding(Ansi: RawByteString): TEncodeType; //EgonHugeist: Detect a valid UTF8Sequence
315 var
316  I, Len: Integer;
317  Source: PAnsiChar;
318 
319  function P(Pos: Integer = 0): Byte;
320  begin
321  Result := Byte(Source[Pos]);
322  end;
323 
324  procedure IncPos(X: Integer = 1);
325  begin
326  inc(Source, X);
327  inc(i, X);
328  end;
329 begin
330  Result := etUSASCII;
331  if Ansi = '' then Exit;
332 
333  Len := Length(Ansi);
334  Source := PAnsiChar(Ansi);
335 
336  // skip US-ASCII Chars they are allways valid.
337  I := 0;
338  while ( I <= Len ) do
339  begin
340  if P >= $80 then break;
341  IncPos;
342  end;
343 
344  if i > Len then exit; //US ACII
345 
346  //No US-Ascii at all.
347  while I < Len do
348  begin
349  case p of
350  $00..$7F: //Ascii
351  IncPos;
352 
353  $C2..$DF: // non-overlong 2-byte
354  if (I+1 < Len)
355  and (P(1) in [$80..$BF]) then
356  IncPos(2)
357  else
358  break;
359 
360  $E0: // excluding overlongs
361  if (I+2 < Len)
362  and (P(1) in [$A0..$BF])
363  and (P(2) in [$80..$BF]) then
364  IncPos(3)
365  else
366  break;
367 
368  $E1..$EF: // straight 3-byte & excluding surrogates
369  if (i+2 < Len)
370  and (P(1) in [$80..$BF])
371  and (P(2) in [$80..$BF]) then
372  IncPos(3)
373  else
374  break;
375 
376  $F0: // planes 1-3
377  if (i+3 < Len)
378  and (P(1) in [$90..$BF])
379  and (P(2) in [$80..$BF])
380  and (P(3) in [$80..$BF]) then
381  IncPos(4)
382  else
383  break;
384 
385  $F1..$F3: // planes 4-15
386  if (i+3 < Len)
387  and (P(1) in [$80..$BF])
388  and (P(2) in [$80..$BF])
389  and (P(3) in [$80..$BF]) then
390  IncPos(4)
391  else
392  break;
393 
394  $F4: // plane 16
395  if (i+3 < Len)
396  and (P(1) in [$80..$8F])
397  and (P(2) in [$80..$BF])
398  and (P(3) in [$80..$BF]) then
399  IncPos(4)
400  else
401  break;
402  else
403  break;
404  end;
405  end;
406 
407  if i = Len then
408  Result := etUTF8 //UTF8
409  else
410  Result := etANSI; //Ansi
411 end;
412 {$ENDIF}
413 
414 {**
415  EgonHugeist:
416  Now use the new Functions to get encoded Strings instead of
417  hard-coded Compiler-Directives or UTF8Encode/Decode:
418 
419  function ZDbcString(const Ansi: AnsiString; const Encoding: TZCharEncoding = ceDefault): String;
420  function ZPlainString(const Str: String; const Encoding: TZCharEncoding = ceDefault): AnsiString;
421 
422  These functions do auto arrange the in/out-coming AnsiStrings in
423  dependency of the used CharacterSet and the used Compiler whithout
424  String-DataLoss!!.
425  So my thouths where use only these two function for all
426  String/Ansi/Unicode-handlings of DBC-layer. Which means in full effect
427  no more directives in Zeos Source-Code then here to do this handling.
428  @param Ansi: the String which has to be handled.
429  @param Encoding is set to Default-Character-Set we've choosen bevor (on conecting)
430  Change this if you need some Transtations to a specified Encoding.
431  Example: CharacterSet was set to Latin1 and some "special"-String MUST BE
432  UTF8 instead of Latin1. (SSL-Keys eventualy)
433  @param Convert ignored for Delphi means if the Chararacters should be propper
434  to the specified codepage
435 
436 
437  IS there a need for it? AnsiEncoded adaps automaticaly to WideString
438  So what about coming UTF16/32????
439 }
440 function TZCodePagedObject.ZDbcString(const Ansi: RawByteString;
441  ConSettings: PZConSettings): String;
442 {$IFDEF WITH_FPC_STRING_CONVERSATION}
443 var TempAnsi: RawByteString;
444 {$ENDIF}
445 begin
446  {$IFNDEF UNICODE}
447  if not ConSettings^.AutoEncode then
448  Result := Ansi
449  else
450  {$ENDIF}
451  case ConSettings^.ClientCodePage^.Encoding of
452  ceUTF8:
453  {$IFDEF UNICODE}
454  Result := UTF8ToString(Ansi);
455  {$ELSE}
456  if ( ConSettings^.CPType in [cCP_UTF8, cCP_UTF16] ) then
457  Result := Ansi
458  else
459  {$IFDEF WITH_LCONVENCODING}
460  Result := ConSettings.DbcConvertFunc(Ansi);
461  {$ELSE}
462  {$IFDEF WITH_FPC_STRING_CONVERSATION}
463  begin
464  //avoid string conversion -> move memory
465  TempAnsi := AnsiToStringEx(Ansi, ConSettings^.ClientCodePage^.CP, ConSettings^.CTRL_CP);
466  SetLength(Result, Length(TempAnsi));
467  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
468  end;
469  {$ELSE}
470  Result := AnsiToStringEx(Ansi, ConSettings^.ClientCodePage^.CP, ConSettings^.CTRL_CP);
471  {$ENDIF}
472  {$ENDIF}
473  {$ENDIF}
474  else
475  {$IFDEF UNICODE}
476  Result := AnsiToStringEx(Ansi, ConSettings^.ClientCodePage^.CP);
477  {$ELSE}
478  if ConSettings.AutoEncode then
479  if ConSettings^.ClientCodePage^.CP = zCP_NONE then //that's not nice it slows down the incoming strings! Find a way to determine allways the current server CP
480  case DetectUTF8Encoding(Ansi) of
481  etUSASCII: Result := Ansi;
482  etAnsi:
483  if ConSettings^.CTRL_CP = zCP_UTF8 then
484  {$IFDEF WITH_FPC_STRING_CONVERSATION}
485  begin
486  //avoid string conversion -> move memory
487  TempAnsi := AnsiToUTF8(Ansi); //hope we've compatible results ))):
488  SetLength(Result, Length(TempAnsi));
489  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
490  end
491  {$ELSE}
492  Result := AnsiToUTF8(Ansi) //hope we've compatible results ))):
493  {$ENDIF}
494  else
495  Result := Ansi;
496  else
497  if ConSettings^.CTRL_CP = zCP_UTF8 then
498  Result := Ansi
499  else
500  {$IFDEF WITH_FPC_STRING_CONVERSATION}
501  begin
502  //avoid string conversion -> move memory
503  TempAnsi := AnsiToStringEx(Ansi, zCP_UTF8, ConSettings.CTRL_CP);
504  SetLength(Result, Length(TempAnsi));
505  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
506  end;
507  {$ELSE}
508  {$IFDEF WITH_LCONVENCODING}
509  Result := Ansi;
510  {$ELSE}
511  Result := AnsiToStringEx(Ansi, zCP_UTF8, ConSettings.CTRL_CP);
512  {$ENDIF}
513  {$ENDIF}
514  end
515  else
516  {$IFDEF WITH_LCONVENCODING}
517  Result := ConSettings.DbcConvertFunc(Ansi)
518  {$ELSE}
519  {$IFDEF WITH_FPC_STRING_CONVERSATION}
520  begin
521  //avoid string conversion -> move memory
522  TempAnsi := AnsiToStringEx(Ansi, ConSettings.ClientCodePage.CP, ConSettings.CTRL_CP);
523  SetLength(Result, Length(TempAnsi));
524  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
525  end
526  {$ELSE}
527  Result := AnsiToStringEx(Ansi, ConSettings.ClientCodePage.CP, ConSettings.CTRL_CP)
528  {$ENDIF}
529  {$ENDIF}
530  else
531  Result := Ansi;
532  {$ENDIF}
533  end;
534 end;
535 
536 function TZCodePagedObject.ZDbcString(const Ansi: RawByteString; FromCP: Word): String;
537 var
538  CurrentCP: Word;
539  CurrentEncoding: TZCharEncoding;
540 begin
541  if FromCP = FConsettings.ClientCodePage.CP then
542  Result := ZDbcString(Ansi, ConSettings)
543  else
544  begin
545  CurrentCP := FConsettings.ClientCodePage.CP;
546  CurrentEncoding := FConSettings.ClientCodePage.Encoding;
547  if ( FromCP = zCP_UTF8 ) then
548  FConSettings.ClientCodePage.Encoding := ceUTF8
549  else
550  FConSettings.ClientCodePage.Encoding := ceAnsi;
551  FConsettings.ClientCodePage.CP := FromCP;
552  Result := ZDbcString(Ansi, FConSettings);
553  FConsettings.ClientCodePage.CP := CurrentCP;
554  FConSettings.ClientCodePage.Encoding := CurrentEncoding;
555  end;
556 end;
557 
558 function TZCodePagedObject.ZDbcString(const Ansi: RawByteString;
559  const Encoding: TZCharEncoding = ceDefault): String;
560 var
561  TempEncoding, UseEncoding: TZCharEncoding;
562 begin
563  if Encoding = ceDefault then
564  if not Assigned(FConSettings.ClientCodePage) then
565  raise Exception.Create('CodePage-Informations not Assigned!')
566  else
567  UseEncoding := FConSettings.ClientCodePage^.Encoding
568  else
569  UseEncoding := Encoding;
570 
571  {$IFNDEF UNICODE}
572  if not FConSettings.AutoEncode and ( FConSettings.ClientCodePage^.Encoding = UseEncoding ) then
573  Result := Ansi
574  else
575  {$ENDIF}
576  begin
577  TempEncoding := FConSettings^.ClientCodePage^.Encoding;
578  FConSettings.ClientCodePage^.Encoding := UseEncoding;
579  Result := ZDbcString(Ansi, FConSettings);
580  FConSettings^.ClientCodePage^.Encoding := TempEncoding;
581  end;
582 end;
583 
584 function TZCodePagedObject.ZDbcUnicodeString(const AStr: RawByteString): ZWideString;
585 begin
586  {$IFNDEF WITH_LCONVENCODING}
587  Result := ZRawToUnicode(AStr, FConSettings.ClientCodePage.CP);
588  {$ELSE}
589  case Consettings.ClientCodePage.Encoding of
590  ceAnsi:
591  Result := UTF8Decode(ConSettings.DbcConvertFunc(AStr)); //!!!!SLOW, Job down twice (Ansi up to wide to UTF8 to Wide)
592  else
593  Result := UTF8ToString(AStr)
594  end;
595  {$ENDIF}
596 end;
597 
598 function TZCodePagedObject.ZDbcString(const AStr: ZWideString; const Encoding: TZCharEncoding = ceDefault): String;
599 {$IFDEF WITH_FPC_STRING_CONVERSATION}
600 var
601  TempAnsi: RawByteString;
602 {$ENDIF}
603 begin
604  {$IFDEF UNICODE}
605  Result := AStr;
606  {$ELSE}
607  if not ConSettings.AutoEncode then
608  Result := String(AStr)
609  else
610  {$IFDEF WITH_LCONVENCODING}
611  Result := UTF8Encode(AStr);
612  {$ELSE}
613  {$IFDEF WITH_FPC_STRING_CONVERSATION}
614  begin
615  //avoid string conversion -> move memory
616  TempAnsi := ZUnicodeToRaw(AStr, FConSettings.CTRL_CP);
617  SetLength(Result, Length(TempAnsi));
618  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
619  end
620  {$ELSE}
621  Result := ZUnicodeToRaw(AStr, FConSettings.CTRL_CP);
622  {$ENDIF}
623  {$ENDIF}
624  {$ENDIF}
625 end;
626 
627 function TZCodePagedObject.ZDbcUnicodeString(const AStr: RawByteString;
628  const FromCP: Word): ZWideString;
629 begin
630  {$IFNDEF WITH_LCONVENCODING}
631  Result := ZRawToUnicode(AStr, FromCP);
632  {$ELSE}
633  if FromCP = zCP_UTF8 then
634  Result := UTF8Decode(AStr)
635  else
636  if FromCP = ConSettings.ClientCodePage.CP then
637  Result := UTF8Decode(ConSettings.DbcConvertFunc(AStr))
638  else
639  Result := WideString(AStr); //default WideString cast, can't convert
640  {$ENDIF}
641 end;
642 
643 {$IFDEF WITH_RAWBYTESTRING}
644 function TZCodePagedObject.ZDbcUnicodeString(const AStr: String; const FromCP: Word): ZWideString;
645 begin
646  {$IFDEF UNICODE}
647  Result := AStr;
648  {$ELSE}
649  {$IFNDEF WITH_LCONVENCODING}
650  Result := ZRawToUnicode(AStr, FromCP);
651  {$ELSE}
652  if FromCP = zCP_UTF8 then
653  Result := UTF8Decode(AStr)
654  else
655  if FromCP = ConSettings.ClientCodePage.CP then
656  Result := UTF8Decode(ConSettings.DbcConvertFunc(AStr))
657  else
658  Result := WideString(AStr); //default WideString cast, can't convert
659  {$ENDIF}
660  {$ENDIF}
661 end;
662 {$ENDIF}
663 
664 {**
665 EgonHugeist:
666  Now use the new Functions to get encoded Strings instead of
667  hard-Coded Compiler-Directives or UTF8Encode/Decode:
668 
669  function ZPlainString(const Str: String; const Encoding: TZCharEncoding = ceDefault): AnsiString;
670 
671  These functions do auto arrange the in/out-coming AnsiStrings in
672  dependency of the used CharacterSet and the database uses whithout
673  String-DataLoss!! (if possible -> UTF8 is save).
674  @param AStr: the String which has to be handled.
675  @param Encoding is set to Default-Character-Set we've choosen bevor (on conecting)
676  Change this if you need some Transtations to a specified Encoding.
677  Example: CharacterSet was set to Latin1 and some "special"-String MUST BE
678  UTF8 instead of Latin1. (SSL-Keys eventualy)
679 }
680 function TZCodePagedObject.ZPlainString(const AStr: String;
681  ConSettings: PZConSettings): RawByteString;
682 {$IFDEF WITH_FPC_STRING_CONVERSATION}
683 var
684  TempAnsi: RawByteString;
685 {$ENDIF}
686 begin
687  case ConSettings.ClientCodePage.Encoding of
688  ceUTF8:
689  {$IFDEF UNICODE}
690  Result := UTF8Encode(AStr);
691  {$ELSE}
692  if ConSettings.AutoEncode then
693  if DetectUTF8Encoding(AStr) in [etUTF8, etUSASCII] then
694  Result := AStr
695  else
696  if ( ConSettings.CTRL_CP = zCP_UTF8 ) or (ConSettings.CTRL_CP = zCP_UTF8) then //avoid "no success" for expected Codepage UTF8 of the Controls
697  {$IFDEF WITH_FPC_STRING_CONVERSATION}
698  begin
699  //avoid string conversion -> move memory
700  TempAnsi := AnsiToUTF8(AStr);
701  SetLength(Result, Length(TempAnsi));
702  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
703  end
704  {$ELSE}
705  Result := AnsiToUTF8(AStr)
706  {$ENDIF}
707  else
708  {$IFDEF WITH_FPC_STRING_CONVERSATION}
709  begin
710  //avoid string conversion -> move memory
711  TempAnsi := StringToAnsiEx(AStr, ConSettings.CTRL_CP, zCP_UTF8);
712  SetLength(Result, Length(TempAnsi));
713  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
714  end
715  {$ELSE}
716  {$IFDEF WITH_LCONVENCODING}
717  Result := AnsiToUTF8(AStr)
718  {$ELSE}
719  Result := StringToAnsiEx(AStr, ConSettings.CTRL_CP, zCP_UTF8)
720  {$ENDIF}
721  {$ENDIF}
722  else
723  Result := AStr;
724  {$ENDIF}
725  else
726  begin
727  {$IFDEF UNICODE}
728  Result := StringToAnsiEx(AStr, ConSettings.ClientCodePage.CP);
729  {$ELSE}
730  if ConSettings.AutoEncode then
731  case DetectUTF8Encoding(AStr) of
732  etUSASCII: Result := AStr;
733  etAnsi:
734  {$IFDEF WITH_LCONVENCODING}
735  if ConSettings.CTRL_CP = ConSettings.ClientCodePage.CP then
736  Result := AStr
737  else
738  Result := ConSettings.PlainConvertFunc(AnsiToUTF8(AStr));
739  {$ELSE}
740  Result := Astr;
741  {$ENDIF}
742  else
743  {$IFDEF WITH_LCONVENCODING}
744  Result := ConSettings.PlainConvertFunc(AStr);
745  {$ELSE}
746  {$IFDEF WITH_FPC_STRING_CONVERSATION}
747  begin
748  if ConSettings.ClientCodePage.CP = zCP_NONE then
749  TempAnsi := UTF8ToAnsi(AStr) //hope it's compatible we don't know the server CP here!!
750  else
751  TempAnsi := StringToAnsiEx(AStr, zCP_UTF8, ConSettings.ClientCodePage.CP);
752  //avoid string conversion -> move memory
753  SetLength(Result, Length(TempAnsi));
754  Move(PAnsiChar(TempAnsi)^, PAnsiChar(Result)^, Length(TempAnsi));
755  end;
756  {$ELSE}
757  if ConSettings.ClientCodePage.CP = zCP_NONE then
758  Result := UTF8ToAnsi(AStr) //hope it's compatible we don't know the server CP here!!
759  else
760  Result := StringToAnsiEx(AStr, zCP_UTF8, ConSettings.ClientCodePage.CP);
761  {$ENDIF}
762  {$ENDIF}
763  end
764  else
765  Result := AStr;
766  {$ENDIF}
767  end;
768  end;
769 end;
770 
771 function TZCodePagedObject.ZPlainString(const AStr: String; ConSettings: PZConSettings; const ToCP: Word): RawByteString;
772 var
773  CurrentCP: Word;
774  CurrentEncoding: TZCharEncoding;
775 begin
776  if ToCP = ConSettings.ClientCodePage.CP then
777  Result := ZPlainString(AStr, ConSettings)
778  else
779  begin
780  CurrentCP := ConSettings.ClientCodePage.CP;
781  CurrentEncoding := ConSettings.ClientCodePage.Encoding;
782  ConSettings.ClientCodePage.CP := ToCP;
783  if ( ToCP = zCP_UTF8 ) then
784  ConSettings.ClientCodePage.Encoding := ceUTF8
785  else
786  ConSettings.ClientCodePage.Encoding := ceAnsi;
787  Result := ZPlainString(AStr, ConSettings);
788  ConSettings.ClientCodePage.CP := CurrentCP;
789  ConSettings.ClientCodePage.Encoding := CurrentEncoding;
790  end;
791 end;
792 
793 function TZCodePagedObject.ZPlainString(const AStr: String;
794  const Encoding: TZCharEncoding = ceDefault): RawByteString;
795 var
796  TempEncoding, UseEncoding: TZCharEncoding;
797 begin
798  if Encoding = ceDefault then
799  if not Assigned(FConSettings.ClientCodePage) then
800  raise Exception.Create('CodePage-Informations not Assigned!')
801  else
802  UseEncoding := FConSettings.ClientCodePage^.Encoding
803  else
804  UseEncoding := Encoding;
805 
806  {$IFNDEF UNICODE}
807  if not FConSettings.AutoEncode and ( FConSettings.ClientCodePage^.Encoding = UseEncoding ) then
808  Result := AStr
809  else
810  {$ENDIF}
811  begin
812  TempEncoding := FConSettings.ClientCodePage.Encoding;
813  FConSettings.ClientCodePage.Encoding := UseEncoding;
814  Result := ZPlainString(AStr, FConSettings);
815  FConSettings.ClientCodePage.Encoding := TempEncoding;
816  end;
817 end;
818 
819 function TZCodePagedObject.ZPlainString(const AStr: WideString;
820  const Encoding: TZCharEncoding = ceDefault): RawByteString;
821 var
822  TempEncoding, UseEncoding: TZCharEncoding;
823 begin
824  if Encoding = ceDefault then
825  if not Assigned(FConSettings.ClientCodePage) then
826  raise Exception.Create('CodePage-Informations not Assigned!')
827  else
828  UseEncoding := FConSettings.ClientCodePage^.Encoding
829  else
830  UseEncoding := Encoding;
831 
832  TempEncoding := FConSettings.ClientCodePage.Encoding;
833  FConSettings.ClientCodePage.Encoding := UseEncoding;
834  Result := ZPlainString(AStr, FConSettings);
835  FConSettings.ClientCodePage.Encoding := TempEncoding;
836 end;
837 
838 function TZCodePagedObject.ZPlainString(const AStr: WideString;
839  ConSettings: PZConSettings): RawByteString;
840 begin
841  {$IFDEF WITH_LCONVENCODING}
842  Result := ConSettings.PlainConvertFunc(UTF8Encode(AStr));
843  {$ELSE}
844  Result := ZUnicodeToRaw(AStr, ConSettings^.ClientCodePage^.CP);
845  {$ENDIF}
846 end;
847 
848 function TZCodePagedObject.ZPlainString(const AStr: WideString; ConSettings: PZConSettings; const ToCP: Word): RawByteString;
849 var
850  CurrentCP: Word;
851  CurrentEncoding: TZCharEncoding;
852 begin
853  if ToCP = ConSettings.ClientCodePage.CP then
854  Result := ZPlainString(AStr, ConSettings)
855  else
856  begin
857  CurrentCP := ConSettings.ClientCodePage.CP;
858  CurrentEncoding := ConSettings.ClientCodePage.Encoding;
859  ConSettings.ClientCodePage.CP := ToCP;
860  if ( ToCP = zCP_UTF8 ) then
861  ConSettings.ClientCodePage.Encoding := ceUTF8
862  else
863  ConSettings.ClientCodePage.Encoding := ceAnsi;
864  Result := ZPlainString(AStr, ConSettings);
865  ConSettings.ClientCodePage.CP := CurrentCP;
866  ConSettings.ClientCodePage.Encoding := CurrentEncoding;
867  end;
868 end;
869 
870 function TZCodePagedObject.ZPlainUnicodeString(const AStr: String): WideString;
871 begin
872  {$IFDEF UNICODE}
873  Result := AStr;
874  {$ELSE}
875  if FConSettings.AutoEncode then
876  case DetectUTF8Encoding(AStr) of
877  etUTF8, etUSASCII: Result := UTF8Decode(AStr);
878  else
879  Result := WideString(AStr);
880  end
881  else
882  {$IFDEF WITH_LCONVENCODING}
883  Result := UTF8ToString(AStr);
884  {$ELSE}
885  Result := ZRawToUnicode(AStr, FConSettings.CTRL_CP);
886  {$ENDIF}
887  {$ENDIF}
888 end;
889 
890 procedure TZCodePagedObject.SetConSettingsFromInfo(Info: TStrings);
891 begin
892  if Assigned(Info) and Assigned(FConSettings) then
893  begin
894  {$IFDEF UNICODE}
895  ConSettings.CTRL_CP := ZDefaultSystemCodePage;
896  if Info.values['controls_cp'] = 'GET_ACP' then
897  ConSettings.CPType := cGET_ACP
898  else
899  ConSettings.CPType := cCP_UTF16;
900  ConSettings.AutoEncode := True;
901  {$ELSE}
902  {$IF defined(MSWINDOWS) or defined(FPC_HAS_BUILTIN_WIDESTR_MANAGER) or defined(WITH_LCONVENCODING)}
903  ConSettings.AutoEncode := Info.Values['AutoEncodeStrings'] = 'ON'; //compatibitity Option for existing Applications;
904  {$ELSE}
905  ConSettings.AutoEncode := False;
906  {$IFEND}
907  if Info.values['controls_cp'] = 'GET_ACP' then
908  begin
909  ConSettings.CPType := cGET_ACP;
910  ConSettings.CTRL_CP := ZDefaultSystemCodePage;
911  end
912  else
913  if Info.values['controls_cp'] = 'CP_UTF8' then
914  begin
915  ConSettings.CPType := cCP_UTF8;
916  ConSettings.CTRL_CP := zCP_UTF8;
917  end
918  else
919  if Info.values['controls_cp'] = 'CP_UTF16' then
920  begin
921  {$IF defined(MSWINDOWS) or defined(FPC_HAS_BUILTIN_WIDESTR_MANAGER) or defined(WITH_LCONVENCODING)}
922  ConSettings.CPType := {$IFDEF WITH_WIDEFIELDS}cCP_UTF16{$ELSE}cCP_UTF8{$ENDIF};
923  ConSettings.CTRL_CP := ZDefaultSystemCodePage;
924  ConSettings.AutoEncode := True;
925  {$ELSE}
926  if ConSettings.ClientCodePage.Encoding = ceUTF8 then
927  begin
928  ConSettings.CPType := {$IFDEF WITH_WIDEFIELDS}cCP_UTF16{$ELSE}cCP_UTF8{$ENDIF};
929  ConSettings.CTRL_CP := zCP_UTF8;
930  ConSettings.AutoEncode := True;
931  end
932  else
933  begin
934  ConSettings.CPType := cCP_UTF8;
935  ConSettings.CTRL_CP := zCP_UTF8;
936  ConSettings.AutoEncode := False;
937  end;
938  {$IFEND}
939  end
940  else // nothing was found set defaults
941  begin
942  {$IFDEF FPC}
943  ConSettings.CPType := cCP_UTF8;
944  ConSettings.CTRL_CP := zCP_UTF8;
945  {$ELSE}
946  ConSettings.CPType := cGET_ACP;
947  ConSettings.CTRL_CP := GetACP;
948  {$ENDIF}
949  end;
950  {$ENDIF}
951  end;
952 end;
953 
954 destructor TZCodePagedObject.Destroy;
955 begin
956  inherited Destroy;
957 end;
958 
959 {$IFDEF WITH_LCONVENCODING}
960 function NoConvert(const s: string): string;
961 begin
962  Result := S;
963 end;
964 {$ENDIF}
965 
966 
967 {$IFDEF UNIX}
968  {$IFDEF FPC}
969 function LoadLibrary(ModuleName: PChar): HMODULE;
970 begin
971  Result := dynlibs.LoadLibrary(ModuleName);
972 end;
973 
974 function FreeLibrary(Module: HMODULE): LongBool;
975 begin
976  Result := dynlibs.FreeLibrary(Module);
977 end;
978 
979 function GetProcAddress(Module: HMODULE; Proc: PChar): Pointer;
980 begin
981  Result := dynlibs.GetProcAddress(Module,Proc)
982 end;
983  {$ENDIF}
984 {$ENDIF}
985 
986 {$IFNDEF FPC}
987 function Hash(S : AnsiString) : LongWord;
988 Var
989  thehash,g,I : LongWord;
990 begin
991  thehash:=0;
992  For I:=1 to Length(S) do { 0 terminated }
993  begin
994  thehash:=thehash shl 4;
995  {$IFOPT Q+}
996  {$DEFINE OverFlowCheckEnabled}
997  {$OVERFLOWCHECKS OFF}
998  {$ENDIF}
999  inc(theHash,Ord(S[i]));
1000  {$IFDEF OverFlowCheckEnabled}
1001  {$OVERFLOWCHECKS ON}
1002  {$ENDIF}
1003  g:=thehash and LongWord($f shl 28);
1004  if g<>0 then
1005  begin
1006  thehash:=thehash xor (g shr 24);
1007  thehash:=thehash xor g;
1008  end;
1009  end;
1010  If theHash=0 then
1011  Hash:=$ffffffff
1012  else
1013  Hash:=TheHash;
1014 end;
1015 
1016 function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
1017 var
1018  P,PE : PChar;
1019 
1020 begin
1021  Result:=AnsiLowerCase(S);
1022  P:=PChar(pointer(Result));
1023  PE:=P+Length(Result);
1024  while (P<PE) do
1025  begin
1026  while (P<PE) and CharInSet(P^, WordDelims) do
1027  inc(P);
1028  if (P<PE) then
1029  P^:=UpCase(P^);
1030  while (P<PE) and not (CharInSet(P^, WordDelims)) do
1031  inc(P);
1032  end;
1033 end;
1034 {$ENDIF}
1035 
1036 {$IFNDEF WITH_CHARINSET}
1037 function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
1038 begin
1039  result := C in Charset;
1040 end;
1041 
1042 function CharInSet(C: WideChar; const CharSet: TSysCharSet): Boolean;
1043 begin
1044  result := Char(C) in Charset;
1045 end;
1046 {$ENDIF}
1047 
1048 {$IFDEF ZUTF8ToString}
1049 function UTF8ToString(const s: RawByteString): ZWideString;
1050 begin
1051  Result := UTF8Decode(s);
1052 end;
1053 {$UNDEF ZUTF8ToString}
1054 {$ENDIF}
1055 
1056 
1057 initialization
1058  case ConSettingsDummy.CPType of
1059  cCP_UTF16, cGET_ACP: ConSettingsDummy.CTRL_CP := ZDefaultSystemCodePage;
1060  cCP_UTF8: ConSettingsDummy.CTRL_CP := zCP_UTF8;
1061  end;
1062  SetConvertFunctions(@ConSettingsDummy);
1063 
1064 end.
1065 
1066 
1067 
1068