ソースを参照

--- Merging r29430 into '.':
U packages/fcl-db/src/sqldb/mssql/mssqlconn.pp
--- Merging r29442 into '.':
U packages/fcl-db/src/base/bufdataset.pas
U packages/fcl-db/src/sqldb/sqldb.pp
--- Merging r29443 into '.':
G packages/fcl-db/src/sqldb/mssql/mssqlconn.pp
G packages/fcl-db/src/sqldb/sqldb.pp
G packages/fcl-db/src/base/bufdataset.pas
U packages/fcl-db/src/base/db.pas
U packages/fcl-db/tests/testsqldb.pas
--- Merging r29448 into '.':
U packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp
U packages/fcl-db/src/sqldb/mysql/mysqlconn.inc
--- Merging r29451 into '.':
G packages/fcl-db/tests/testsqldb.pas
--- Merging r29462 into '.':
G packages/fcl-db/tests/testsqldb.pas
--- Merging r29479 into '.':
U packages/fcl-db/src/sqldb/postgres/pqconnection.pp
--- Merging r29480 into '.':
G packages/fcl-db/tests/testsqldb.pas
--- Merging r29507 into '.':
G packages/fcl-db/src/sqldb/postgres/pqconnection.pp
--- Merging r29624 into '.':
G packages/fcl-db/src/base/db.pas
U packages/fcl-db/src/base/fields.inc
--- Merging r29638 into '.':
U packages/rtl-unicode/fpmake.pp
U packages/rtl-unicode/src/inc/cpbuildu.pp
A packages/rtl-unicode/src/inc/cp895.pas
A rtl/ucmaps/cp895.txt
--- Merging r29662 into '.':
U packages/fcl-db/src/sqldb/mssql/readme.txt
--- Merging r29679 into '.':
U packages/fcl-db/src/base/dsparams.inc
U packages/fcl-db/src/base/datasource.inc
G packages/fcl-db/tests/testsqldb.pas

# revisions: 29430,29442,29443,29448,29451,29462,29479,29480,29507,29624,29638,29662,29679

git-svn-id: branches/fixes_3_0@29682 -

marco 10 年 前
コミット
15c3cb35df

+ 2 - 0
.gitattributes

@@ -6787,6 +6787,7 @@ packages/rtl-unicode/src/collations/collation_sv_le.inc svneol=native#text/pasca
 packages/rtl-unicode/src/collations/collation_zh.pas svneol=native#text/pascal
 packages/rtl-unicode/src/collations/collation_zh_be.inc svneol=native#text/pascal
 packages/rtl-unicode/src/collations/collation_zh_le.inc svneol=native#text/pascal
+packages/rtl-unicode/src/inc/cp895.pas svneol=native#text/plain
 packages/rtl-unicode/src/inc/cp932.pas svneol=native#text/pascal
 packages/rtl-unicode/src/inc/cp936.pas svneol=native#text/pascal
 packages/rtl-unicode/src/inc/cp949.pas svneol=native#text/pascal
@@ -9207,6 +9208,7 @@ rtl/ucmaps/cp1258.txt svneol=native#text/plain
 rtl/ucmaps/cp852.txt svneol=native#text/plain
 rtl/ucmaps/cp856.txt svneol=native#text/plain
 rtl/ucmaps/cp874.txt svneol=native#text/plain
+rtl/ucmaps/cp895.txt svneol=native#text/plain
 rtl/ucmaps/cp932.txt svneol=native#text/plain
 rtl/ucmaps/cp936.txt svneol=native#text/plain
 rtl/ucmaps/cp949.txt svneol=native#text/plain

+ 11 - 10
packages/fcl-db/src/base/bufdataset.pas

@@ -546,7 +546,7 @@ type
     procedure SetFilterText(const Value: String); override; {virtual;}
     procedure SetFiltered(Value: Boolean); override; {virtual;}
     procedure InternalRefresh; override;
-    procedure DataEvent(Event: TDataEvent; Info: Ptrint); override;
+    procedure DataEvent(Event: TDataEvent; Info: PtrInt); override;
     // virtual or methods, which can be used by descendants
     function GetNewBlobBuffer : PBlobBuffer;
     function GetNewWriteBlobBuffer : PBlobBuffer;
@@ -2104,9 +2104,10 @@ end;
 function TCustomBufDataset.GetCurrentBuffer: TRecordBuffer;
 begin
   case State of
-    dsFilter:     Result := FFilterBuffer;
-    dsCalcFields: Result := CalcBuffer;
-    else          Result := ActiveBuffer;
+    dsFilter:        Result := FFilterBuffer;
+    dsCalcFields:    Result := CalcBuffer;
+    dsRefreshFields: Result := FCurrentIndex.CurrentBuffer
+    else             Result := ActiveBuffer;
   end;
 end;
 
@@ -2144,7 +2145,7 @@ begin
     begin
     if GetFieldIsNull(pbyte(CurrBuff),Field.FieldNo-1) then
       Exit;
-    if assigned(buffer) then
+    if assigned(Buffer) then
       begin
       inc(CurrBuff,FFieldBufPositions[Field.FieldNo-1]);
       Move(CurrBuff^, Buffer^, GetFieldSize(FieldDefs[Field.FieldNo-1]));
@@ -2155,7 +2156,7 @@ begin
     begin
     Inc(CurrBuff, GetRecordSize + Field.Offset);
     Result := Boolean(CurrBuff^);
-    if result and assigned(Buffer) then
+    if Result and assigned(Buffer) then
       begin
       inc(CurrBuff);
       Move(CurrBuff^, Buffer^, Field.DataSize);
@@ -2180,7 +2181,7 @@ begin
   CurrBuff := GetCurrentBuffer;
   If Field.FieldNo > 0 then // If =-1, then calculated/lookup field or =0 unbound field
     begin
-    if Field.ReadOnly and not (State in [dsSetKey, dsFilter]) then
+    if Field.ReadOnly and not (State in [dsSetKey, dsFilter, dsRefreshFields]) then
       DatabaseErrorFmt(SReadOnlyField, [Field.DisplayName]);	
     if State in [dsEdit, dsInsert, dsNewValue] then
       Field.Validate(Buffer);	
@@ -2204,7 +2205,7 @@ begin
       Move(Buffer^, CurrBuff^, Field.DataSize);
     end;
   if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
-    DataEvent(deFieldChange, Ptrint(Field));
+    DataEvent(deFieldChange, PtrInt(Field));
 end;
 
 procedure TCustomBufDataset.InternalDelete;
@@ -2374,7 +2375,7 @@ begin
       if not ((FUpdateBuffer[r].UpdateKind=ukDelete) and not (assigned(FUpdateBuffer[r].OldValuesBuffer))) then
         begin
         FCurrentIndex.GotoBookmark(@FUpdateBuffer[r].BookmarkData);
-        // Synchronise the Currentbuffer to the ActiveBuffer
+        // Synchronise the CurrentBuffer to the ActiveBuffer
         CurrentRecordToBuffer(ActiveBuffer);
         Response := rrApply;
         try
@@ -3247,7 +3248,7 @@ begin
   // Do nothing
 end;
 
-procedure TCustomBufDataset.DataEvent(Event: TDataEvent; Info: Ptrint);
+procedure TCustomBufDataset.DataEvent(Event: TDataEvent; Info: PtrInt);
 begin
   if Event = deUpdateState then
     // Save DataSet.State set by DataSet.SetState (filter out State set by DataSet.SetTempState)

+ 9 - 9
packages/fcl-db/src/base/datasource.inc

@@ -360,12 +360,12 @@ Procedure TMasterDataLink.ActiveChanged;
 begin
   FFields.Clear;
   if Active then
-  try
-    DataSet.GetFieldList(FFields, FFieldNames);
-  except
-    FFields.Clear;
-    raise;
-  end;
+    try
+      DataSet.GetFieldList(FFields, FFieldNames);
+    except
+      FFields.Clear;
+      raise;
+    end;
   if FDetailDataSet.Active and not (csDestroying in FDetailDataSet.ComponentState) then
     if Active and (FFields.Count > 0) then
       DoMasterChange
@@ -502,8 +502,8 @@ Procedure TMasterParamsDataLink.DoMasterDisable;
 
 begin
   Inherited;
-  If Assigned(DetailDataset) and DetailDataset.Active then
-    DetailDataset.Close;
+  // If master dataset is closing, leave detail dataset intact (Delphi compatible behavior)
+  // If master dataset is reopened, relationship will be reestablished
 end;
 
 Procedure TMasterParamsDataLink.DoMasterChange; 
@@ -667,7 +667,7 @@ begin
     else
       FState:=dsInactive;
     // Don't do events if nothing changed.
-    If FState=FlastState then
+    If FState=FLastState then
       exit;
     end
   else

+ 13 - 11
packages/fcl-db/src/base/db.pas

@@ -22,7 +22,7 @@ unit db;
 
 interface
 
-uses Classes,Sysutils,Variants,FmtBCD,MaskUtils;
+uses Classes,SysUtils,Variants,FmtBCD,MaskUtils;
 
 const
 
@@ -48,7 +48,7 @@ type
 
   TDataSetState = (dsInactive, dsBrowse, dsEdit, dsInsert, dsSetKey,
     dsCalcFields, dsFilter, dsNewValue, dsOldValue, dsCurValue, dsBlockRead,
-    dsInternalCalc, dsOpening);
+    dsInternalCalc, dsOpening, dsRefreshFields);
 
   TDataEvent = (deFieldChange, deRecordChange, deDataSetChange,
     deDataSetScroll, deLayoutChange, deUpdateRecord, deUpdateState,
@@ -328,7 +328,7 @@ type
     function GetAsBoolean: Boolean; virtual;
     function GetAsBytes: TBytes; virtual;
     function GetAsCurrency: Currency; virtual;
-    function GetAsLargeInt: LargeInt; virtual;
+    function GetAsLargeInt: Largeint; virtual;
     function GetAsDateTime: TDateTime; virtual;
     function GetAsFloat: Double; virtual;
     function GetAsLongint: Longint; virtual;
@@ -359,7 +359,7 @@ type
     procedure SetAsFloat(AValue: Double); virtual;
     procedure SetAsLongint(AValue: Longint); virtual;
     procedure SetAsInteger(AValue: Longint); virtual;
-    procedure SetAsLargeint(AValue: Largeint); virtual;
+    procedure SetAsLargeInt(AValue: Largeint); virtual;
     procedure SetAsVariant(const AValue: variant); virtual;
     procedure SetAsString(const AValue: string); virtual;
     procedure SetAsWideString(const AValue: WideString); virtual;
@@ -462,6 +462,7 @@ type
     function GetAsDateTime: TDateTime; override;
     function GetAsFloat: Double; override;
     function GetAsInteger: Longint; override;
+    function GetAsLargeInt: Largeint; override;
     function GetAsString: string; override;
     function GetAsVariant: variant; override;
     function GetDataSize: Integer; override;
@@ -472,6 +473,7 @@ type
     procedure SetAsDateTime(AValue: TDateTime); override;
     procedure SetAsFloat(AValue: Double); override;
     procedure SetAsInteger(AValue: Longint); override;
+    procedure SetAsLargeInt(AValue: Largeint); override;
     procedure SetAsString(const AValue: string); override;
     procedure SetVarValue(const AValue: Variant); override;
   public
@@ -552,8 +554,8 @@ type
     procedure SetAsInteger(AValue: Longint); override;
     procedure SetAsString(const AValue: string); override;
     procedure SetVarValue(const AValue: Variant); override;
-    function GetAsLargeint: Largeint; override;
-    procedure SetAsLargeint(AValue: Largeint); override;
+    function GetAsLargeInt: Largeint; override;
+    procedure SetAsLargeInt(AValue: Largeint); override;
   public
     constructor Create(AOwner: TComponent); override;
     Function CheckRange(AValue : Longint) : Boolean;
@@ -577,7 +579,7 @@ type
   protected
     function GetAsFloat: Double; override;
     function GetAsInteger: Longint; override;
-    function GetAsLargeint: Largeint; override;
+    function GetAsLargeInt: Largeint; override;
     function GetAsString: string; override;
     function GetAsVariant: variant; override;
     function GetDataSize: Integer; override;
@@ -585,13 +587,13 @@ type
     function GetValue(var AValue: Largeint): Boolean;
     procedure SetAsFloat(AValue: Double); override;
     procedure SetAsInteger(AValue: Longint); override;
-    procedure SetAsLargeint(AValue: Largeint); override;
+    procedure SetAsLargeInt(AValue: Largeint); override;
     procedure SetAsString(const AValue: string); override;
     procedure SetVarValue(const AValue: Variant); override;
   public
     constructor Create(AOwner: TComponent); override;
-    Function CheckRange(AValue : largeint) : Boolean;
-    property Value: Largeint read GetAsLargeint write SetAsLargeint;
+    Function CheckRange(AValue : Largeint) : Boolean;
+    property Value: Largeint read GetAsLargeInt write SetAsLargeInt;
   published
     property MaxValue: Largeint read FMaxValue write SetMaxValue default 0;
     property MinValue: Largeint read FMinValue write SetMinValue default 0;
@@ -2157,7 +2159,7 @@ const
 
   dsEditModes = [dsEdit, dsInsert, dsSetKey];
   dsWriteModes = [dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter,
-    dsNewValue, dsInternalCalc];
+                  dsNewValue, dsInternalCalc, dsRefreshFields];
   // Correct list of all field types that are BLOB types.
   // Please use this instead of checking TBlobType which will give
   // incorrect results

+ 5 - 3
packages/fcl-db/src/base/dsparams.inc

@@ -1148,7 +1148,7 @@ begin
 end;
 
 
-Procedure TParams.CopyParamValuesFromDataset(ADataset: TDataset;
+Procedure TParams.CopyParamValuesFromDataset(ADataSet: TDataSet;
   CopyBound: Boolean);
 
 Var
@@ -1157,13 +1157,15 @@ Var
   F : TField;
 
 begin
-  If (ADataSet<>Nil) then
+  If assigned(ADataSet) then
     For I:=0 to Count-1 do
      begin
      P:=Items[i];
      if CopyBound or (not P.Bound) then
        begin
-       F:=ADataset.FieldByName(P.Name);
+       // Master dataset must be active and unbound parameters must have fields
+       // with same names in master dataset (Delphi compatible behavior)
+       F:=ADataSet.FieldByName(P.Name);
        P.AssignField(F);
        If Not CopyBound then
          P.Bound:=False;

+ 30 - 21
packages/fcl-db/src/base/fields.inc

@@ -814,7 +814,7 @@ begin
   raise AccessError(SInteger);
 end;
 
-procedure TField.SetAsLargeint(AValue: Largeint);
+procedure TField.SetAsLargeInt(AValue: Largeint);
 begin
   Raise AccessError(SLargeInt);
 end;
@@ -1068,6 +1068,12 @@ begin
   Result:=StrToInt(GetAsString);
 end;
 
+function TStringField.GetAsLargeInt: Largeint;
+
+begin
+  Result:=StrToInt64(GetAsString);
+end;
+
 function TStringField.GetAsString: string;
 
 begin
@@ -1169,7 +1175,13 @@ end;
 procedure TStringField.SetAsInteger(AValue: Longint);
 
 begin
-  SetAsString(intToStr(AValue));
+  SetAsString(IntToStr(AValue));
+end;
+
+procedure TStringField.SetAsLargeInt(AValue: Largeint);
+
+begin
+  SetAsString(IntToStr(AValue));
 end;
 
 procedure TStringField.SetAsString(const AValue: string);
@@ -1385,7 +1397,7 @@ begin
   Result:=GetAsInteger;
 end;
 
-function TLongintField.GetAsLargeint: Largeint;
+function TLongintField.GetAsLargeInt: Largeint;
 begin
   Result:=GetAsInteger;
 end;
@@ -1459,7 +1471,7 @@ begin
     end;
 end;
 
-procedure TLongintField.SetAsLargeint(AValue: Largeint);
+procedure TLongintField.SetAsLargeInt(AValue: Largeint);
 begin
   if (AValue>=FMinRange) and (AValue<=FMaxRange) then
     SetAsInteger(AValue)
@@ -1552,10 +1564,10 @@ end;
 function TLargeintField.GetAsFloat: Double;
 
 begin
-  Result:=GetAsLargeint;
+  Result:=GetAsLargeInt;
 end;
 
-function TLargeintField.GetAsLargeint: Largeint;
+function TLargeintField.GetAsLargeInt: Largeint;
 
 begin
   If Not GetValue(Result) then
@@ -1576,7 +1588,7 @@ end;
 function TLargeintField.GetAsInteger: Longint;
 
 begin
-  Result:=GetAsLargeint;
+  Result:=GetAsLargeInt;
 end;
 
 function TLargeintField.GetAsString: string;
@@ -1598,7 +1610,7 @@ end;
 
 procedure TLargeintField.GetText(var AText: string; ADisplayText: Boolean);
 
-var l : largeint;
+var l : Largeint;
     fmt : string;
 
 begin
@@ -1616,9 +1628,6 @@ end;
 
 function TLargeintField.GetValue(var AValue: Largeint): Boolean;
 
-type
-  PLargeint = ^Largeint;
-
 var P : PLargeint;
 
 begin
@@ -1629,10 +1638,10 @@ end;
 procedure TLargeintField.SetAsFloat(AValue: Double);
 
 begin
-  SetAsLargeint(Round(AValue));
+  SetAsLargeInt(Round(AValue));
 end;
 
-procedure TLargeintField.SetAsLargeint(AValue: Largeint);
+procedure TLargeintField.SetAsLargeInt(AValue: Largeint);
 
 begin
   If CheckRange(AValue) then
@@ -1644,13 +1653,13 @@ end;
 procedure TLargeintField.SetAsInteger(AValue: Longint);
 
 begin
-  SetAsLargeint(AValue);
+  SetAsLargeInt(AValue);
 end;
 
 procedure TLargeintField.SetAsString(const AValue: string);
 
-var L     : largeint;
-    code  : longint;
+var L     : Largeint;
+    code  : Longint;
 
 begin
   If length(AValue)=0 then
@@ -1659,7 +1668,7 @@ begin
     begin
     Val(AValue,L,Code);
     If Code=0 then
-      SetAsLargeint(L)
+      SetAsLargeInt(L)
     else
       DatabaseErrorFmt(SNotAnInteger,[AValue]);
     end;
@@ -1667,10 +1676,10 @@ end;
 
 procedure TLargeintField.SetVarValue(const AValue: Variant);
 begin
-  SetAsLargeint(AValue);
+  SetAsLargeInt(AValue);
 end;
 
-Function TLargeintField.CheckRange(AValue : largeint) : Boolean;
+Function TLargeintField.CheckRange(AValue : Largeint) : Boolean;
 
 begin
   if (FMinValue<>0) or (FMaxValue<>0) then
@@ -1679,7 +1688,7 @@ begin
     Result := (AValue>=FMinRange) and (AValue<=FMaxRange);
 end;
 
-Procedure TLargeintField.SetMaxValue (AValue : largeint);
+Procedure TLargeintField.SetMaxValue (AValue : Largeint);
 
 begin
   If (AValue>=FMinRange) and (AValue<=FMaxRange) then
@@ -1688,7 +1697,7 @@ begin
     RangeError(AValue,FMinRange,FMaxRange);
 end;
 
-Procedure TLargeintField.SetMinValue (AValue : largeint);
+Procedure TLargeintField.SetMinValue (AValue : Largeint);
 
 begin
   If (AValue>=FMinRange) and (AValue<=FMaxRange) then

+ 18 - 2
packages/fcl-db/src/sqldb/mssql/mssqlconn.pp

@@ -96,6 +96,7 @@ type
     // - Statement execution
     procedure Execute(cursor:TSQLCursor; ATransaction:TSQLTransaction; AParams:TParams); override;
     function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
+    function RefreshLastInsertID(Query : TCustomSQLQuery; Field : TField): boolean; override;
     // - Result retrieving
     procedure AddFieldDefs(cursor:TSQLCursor; FieldDefs:TFieldDefs); override;
     function Fetch(cursor:TSQLCursor):boolean; override;
@@ -315,7 +316,7 @@ end;
 constructor TMSSQLConnection.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
-  FConnOptions := FConnOptions + [sqSupportEmptyDatabaseName, sqEscapeRepeat];
+  FConnOptions := [sqSupportEmptyDatabaseName, sqEscapeRepeat, sqImplicitTransaction, sqLastInsertID];
   //FieldNameQuoteChars:=DoubleQuotes; //default
   Ftds := DBTDS_UNKNOWN;
 end;
@@ -540,7 +541,7 @@ end;
 
 function TMSSQLConnection.Rollback(trans: TSQLHandle): boolean;
 begin
-  Execute('ROLLBACK');
+  Execute('IF @@TRANCOUNT>0 ROLLBACK');
   Result:=true;
 end;
 
@@ -659,6 +660,21 @@ begin
     Result := inherited RowsAffected(cursor);
 end;
 
+function TMSSQLConnection.RefreshLastInsertID(Query: TCustomSQLQuery; Field: TField): boolean;
+var Identity: int64;
+begin
+  // global variable @@IDENTITY is NUMERIC(38,0)
+  Result:=False;
+  if dbcmd(FDBProc, 'SELECT @@IDENTITY') = FAIL then Exit;
+  if dbsqlexec(FDBProc) = FAIL then Exit;
+  if dbresults(FDBProc) = FAIL then Exit;
+  if dbnextrow(FDBProc) = FAIL then Exit;
+  if dbconvert(FDBProc, dbcoltype(FDBProc,1), dbdata(FDBProc,1), -1, SYBINT8, @Identity, sizeof(Identity)) = -1 then Exit;
+  // by default identity columns are ReadOnly
+  Field.AsLargeInt := Identity;
+  Result:=True;
+end;
+
 function TMSSQLConnection.TranslateFldType(SQLDataType: integer): TFieldType;
 begin
   case SQLDataType of

+ 3 - 2
packages/fcl-db/src/sqldb/mssql/readme.txt

@@ -27,9 +27,10 @@ Compiling FreeTDS DB-Lib with MS Visual C++ 2005/2008/2010:
      Note: To avoid dependency on msvc*.dll you can set in C/C++ / Code Generation / Runtime Library : "Multi-threaded (/MT)" in all projects
 
      To build dblib.dll under MS Visual C++ 2010 Express for Win64 you must:
-     - download and install Microsoft Windows Software Development Kit 7.1
+     - download and install Microsoft Windows Software Development Kit 7.1 (install before Visual Studio 2010 SP1 !)
+     - if you upgrade to Visual Studio 2010 SP1 then you must install Microsoft Visual C++ 2010 Service Pack 1 Compiler Update for the Windows SDK 7.1 (http://support.microsoft.com/kb/2519277/en-us)
      - setup FreeTDS project to target 64-bit platform (http://msdn.microsoft.com/en-us/library/9yb4317s.aspx)
-     - Right-click on project "dblib_dll" and select "Properties".
+     - Right-click on project "dblib" and select "Properties".
        Linker / General / Additional Library Directories add path to "Microsoft SDKs\Windows\v7.1\Lib\x64"
 
 

+ 1 - 1
packages/fcl-db/src/sqldb/mysql/mysqlconn.inc

@@ -1130,7 +1130,7 @@ constructor TConnectionName.Create(AOwner: TComponent);
 const SingleBackQoutes: TQuoteChars = ('`','`');
 begin
   inherited Create(AOwner);
-  FConnOptions := FConnOptions + [sqEscapeRepeat, sqEscapeSlash, sqImplicitTransaction, sqLastInsertID];
+  FConnOptions := [sqEscapeRepeat, sqEscapeSlash, sqImplicitTransaction, sqLastInsertID];
   FieldNameQuoteChars:=SingleBackQoutes;
   FMySQL := Nil;
 end;

+ 84 - 78
packages/fcl-db/src/sqldb/postgres/pqconnection.pp

@@ -21,10 +21,10 @@ type
 
   TPQTrans = Class(TSQLHandle)
   protected
-    PGConn        : PPGConn;
-    FList : TThreadList;
-    Procedure RegisterCursor(S : TPQCursor);
-    Procedure UnRegisterCursor(S : TPQCursor);
+    PGConn : PPGConn;
+    FList  : TThreadList;
+    Procedure RegisterCursor(Cursor : TPQCursor);
+    Procedure UnRegisterCursor(Cursor : TPQCursor);
   Public
     Constructor Create;
     Destructor Destroy; override;
@@ -60,6 +60,8 @@ type
     Destructor Destroy; override;
   end;
 
+  { EPQDatabaseError }
+
   EPQDatabaseError = class(EDatabaseError)
     public
       SEVERITY:string;
@@ -70,6 +72,8 @@ type
       STATEMENT_POSITION:string;
   end;
 
+  { TPQTranConnection }
+
   TPQTranConnection = class
   protected
     FPGConn        : PPGConn;
@@ -125,7 +129,7 @@ type
     function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
   public
     constructor Create(AOwner : TComponent); override;
-    destructor destroy; override;
+    destructor Destroy; override;
     function GetConnectionInfo(InfoType:TConnInfoType): string; override;
     procedure CreateDB; override;
     procedure DropDB; override;
@@ -189,23 +193,12 @@ const Oid_Bool     = 16;
       oid_numeric   = 1700;
       Oid_uuid      = 2950;
 
-{ TPQTrans }
 
-procedure TPQTrans.RegisterCursor(S: TPQCursor);
-begin
-  FList.Add(S);
-  S.tr:=Self;
-end;
-
-procedure TPQTrans.UnRegisterCursor(S: TPQCursor);
-begin
-  S.tr:=Nil;
-  FList.Remove(S);
-end;
+{ TPQTrans }
 
 constructor TPQTrans.Create;
 begin
-  Flist:=TThreadList.Create;
+  FList:=TThreadList.Create;
   FList.Duplicates:=dupIgnore;
 end;
 
@@ -216,19 +209,39 @@ Var
   I : integer;
 
 begin
-  L:=Flist.LockList;
+  L:=FList.LockList;
   try
     For I:=0 to L.Count-1 do
       TPQCursor(L[i]).tr:=Nil;
   finally
-    Flist.UnlockList;
+    FList.UnlockList;
   end;
   FreeAndNil(FList);
   inherited Destroy;
 end;
 
+procedure TPQTrans.RegisterCursor(Cursor: TPQCursor);
+begin
+  FList.Add(Cursor);
+  Cursor.tr:=Self;
+end;
+
+procedure TPQTrans.UnRegisterCursor(Cursor: TPQCursor);
+begin
+  Cursor.tr:=Nil;
+  FList.Remove(Cursor);
+end;
+
+
 { TPQCursor }
 
+destructor TPQCursor.Destroy;
+begin
+  if Assigned(tr) then
+    tr.UnRegisterCursor(Self);
+  inherited Destroy;
+end;
+
 function TPQCursor.GetFieldBinding(F: TFieldDef): PFieldBinding;
 
 Var
@@ -252,13 +265,8 @@ begin
     end;
 end;
 
-destructor TPQCursor.Destroy;
-begin
-  if Assigned(tr) then
-    Tr.UnRegisterCursor(Self);
-  inherited Destroy;
-end;
 
+{ TPQConnection }
 
 constructor TPQConnection.Create(AOwner : TComponent);
 
@@ -270,7 +278,7 @@ begin
   FConnectionPool:=TThreadlist.Create;
 end;
 
-destructor TPQConnection.destroy;
+destructor TPQConnection.Destroy;
 begin
   // We must disconnect here. If it is done in inherited, then connection pool is gone.
   Connected:=False;
@@ -432,6 +440,7 @@ var
 begin
   result := false;
   tr := trans as TPQTrans;
+  // unprepare statements associated with given transaction
   L:=tr.FList.LockList;
   try
     For I:=0 to L.Count-1 do
@@ -441,8 +450,9 @@ begin
       end;
     L.Clear;
   finally
-    tr.flist.UnlockList;
+    tr.FList.UnlockList;
   end;
+
   res := PQexec(tr.PGConn, 'ROLLBACK');
   CheckResultError(res,tr.PGConn,SErrRollbackFailed);
   PQclear(res);
@@ -465,22 +475,50 @@ begin
   result := true;
 end;
 
-function TPQConnection.StartImplicitTransaction(trans : TSQLHandle; AParams : string) : boolean;
+procedure TPQConnection.RollBackRetaining(trans : TSQLHandle);
 var
+  res : PPGresult;
   tr  : TPQTrans;
-  i   : Integer;
-  t : TPQTranConnection;
-  L : TList;
 begin
-  result:=false;
   tr := trans as TPQTrans;
+  res := PQexec(tr.PGConn, 'ROLLBACK');
+  CheckResultError(res,tr.PGConn,SErrRollbackFailed);
 
+  PQclear(res);
+  res := PQexec(tr.PGConn, 'BEGIN');
+  CheckResultError(res,tr.PGConn,sErrTransactionFailed);
+
+  PQclear(res);
+end;
+
+procedure TPQConnection.CommitRetaining(trans : TSQLHandle);
+var
+  res : PPGresult;
+  tr  : TPQTrans;
+begin
+  tr := trans as TPQTrans;
+  res := PQexec(tr.PGConn, 'COMMIT');
+  CheckResultError(res,tr.PGConn,SErrCommitFailed);
+
+  PQclear(res);
+  res := PQexec(tr.PGConn, 'BEGIN');
+  CheckResultError(res,tr.PGConn,sErrTransactionFailed);
+
+  PQclear(res);
+end;
+
+function TPQConnection.StartImplicitTransaction(trans : TSQLHandle; AParams : string) : boolean;
+var
+  i : Integer;
+  T : TPQTranConnection;
+  L : TList;
+begin
   //find an unused connection in the pool
   i:=0;
-  t:=Nil;
+  T:=Nil;
   L:=FConnectionPool.LockList;
   try
-    while (I<L.Count) do
+    while (i<L.Count) do
       begin
       T:=TPQTranConnection(L[i]);
       if (T.FPGConn=nil) or not T.FTranActive then
@@ -496,55 +534,24 @@ begin
   finally
     FConnectionPool.UnLockList;
   end;
+
   if (T=Nil) then
     begin
     T:=TPQTranConnection.Create;
     T.FTranActive:=True;
     AddConnection(T);
     end;
-  if (T.FPGConn<>nil) then
-    tr.PGConn:=T.FPGConn
-  else
+
+  if (T.FPGConn=nil) then
     begin
-    tr.PGConn := PQconnectdb(pchar(FConnectString));
-    T.FPGConn:=tr.PGConn;
-    CheckConnectionStatus(tr.PGConn);
+    T.FPGConn := PQconnectdb(pchar(FConnectString));
+    CheckConnectionStatus(T.FPGConn);
     if CharSet <> '' then
-      PQsetClientEncoding(tr.PGConn, pchar(CharSet));
+      PQsetClientEncoding(T.FPGConn, pchar(CharSet));
     end;
-  result := true;
-end;
 
-procedure TPQConnection.RollBackRetaining(trans : TSQLHandle);
-var
-  res : PPGresult;
-  tr  : TPQTrans;
-begin
-  tr := trans as TPQTrans;
-  res := PQexec(tr.PGConn, 'ROLLBACK');
-  CheckResultError(res,tr.PGConn,SErrRollbackFailed);
-
-  PQclear(res);
-  res := PQexec(tr.PGConn, 'BEGIN');
-  CheckResultError(res,tr.PGConn,sErrTransactionFailed);
-
-  PQclear(res);
-end;
-
-procedure TPQConnection.CommitRetaining(trans : TSQLHandle);
-var
-  res : PPGresult;
-  tr  : TPQTrans;
-begin
-  tr := trans as TPQTrans;
-  res := PQexec(tr.PGConn, 'COMMIT');
-  CheckResultError(res,tr.PGConn,SErrCommitFailed);
-
-  PQclear(res);
-  res := PQexec(tr.PGConn, 'BEGIN');
-  CheckResultError(res,tr.PGConn,sErrTransactionFailed);
-
-  PQclear(res);
+  TPQTrans(trans).PGConn := T.FPGConn;
+  Result := true;
 end;
 
 function TPQConnection.StartDBTransaction(trans: TSQLHandle;
@@ -866,7 +873,6 @@ var
   i : integer;
   P : TParam;
   PQ : TSQLDBParam;
-  r          : PPGresult;
 
 begin
   with (cursor as TPQCursor) do
@@ -947,7 +953,7 @@ begin
     res:=nil;
     if FPrepared then
       begin
-      if PQtransactionStatus(tr.PGConn) <> PQTRANS_INERROR then
+      if assigned(tr) and (PQtransactionStatus(tr.PGConn) <> PQTRANS_INERROR) then
         begin
         res := PQexec(tr.PGConn,pchar('deallocate '+StmtName));
         CheckResultError(res,nil,SErrUnPrepareFailed);
@@ -1029,7 +1035,7 @@ begin
       end
     else
       begin
-      // Registercursor sets tr
+      // RegisterCursor sets tr
       TPQTrans(aTransaction.Handle).RegisterCursor(Cursor as TPQCursor);
 
       if Assigned(AParams) and (AParams.Count > 0) then
@@ -1119,7 +1125,7 @@ begin
             end
         else
           if ErrorOnUnknownType then
-            DatabaseError('unhandled field type :'+FB^.TypeName,Self);
+            DatabaseError('Unhandled field type :'+FB^.TypeName,Self);
         end;
         end;
       end;

+ 20 - 17
packages/fcl-db/src/sqldb/sqldb.pp

@@ -472,7 +472,6 @@ type
   public
     constructor Create(AOwner : TComponent); override;
     destructor Destroy; override;
-    Procedure ApplyUpdates(MaxErrors: Integer); override; overload;
     procedure Prepare; virtual;
     procedure UnPrepare; virtual;
     procedure ExecSQL; virtual;
@@ -482,6 +481,8 @@ type
     Property Prepared : boolean read IsPrepared;
     Property SQLConnection : TSQLConnection Read GetSQLConnection Write SetSQLConnection;
     Property SQLTransaction: TSQLTransaction Read GetSQLTransaction Write SetSQLTransaction;
+    // overriden TBufDataSet methods
+    Procedure ApplyUpdates(MaxErrors: Integer); override; overload;
     // overriden TDataSet methods
     Procedure Post; override;
     Procedure Delete; override;
@@ -2086,10 +2087,10 @@ begin
   F.FQuery:=Self;
   FStatement:=F;
 
-  FUpdateSQL := TStringList.Create;
-  FUpdateSQL.OnChange := @OnChangeModifySQL;
   FInsertSQL := TStringList.Create;
   FInsertSQL.OnChange := @OnChangeModifySQL;
+  FUpdateSQL := TStringList.Create;
+  FUpdateSQL.OnChange := @OnChangeModifySQL;
   FDeleteSQL := TStringList.Create;
   FDeleteSQL.OnChange := @OnChangeModifySQL;
   FRefreshSQL := TStringList.Create;
@@ -2116,24 +2117,13 @@ begin
   UnPrepare;
   FreeAndNil(FStatement);
   FreeAndNil(FInsertSQL);
-  FreeAndNil(FDeleteSQL);
   FreeAndNil(FUpdateSQL);
+  FreeAndNil(FDeleteSQL);
   FreeAndNil(FRefreshSQL);
   FServerIndexDefs.Free;
   inherited Destroy;
 end;
 
-Procedure TCustomSQLQuery.ApplyUpdates(MaxErrors: Integer);
-begin
-  inherited ApplyUpdates(MaxErrors);
-  If sqoAutoCommit in Options then
-    begin
-    // Retrieve rows affected for last update.
-    FStatement.RowsAffected;
-    SQLTransaction.Commit;
-    end;
-end;
-
 function TCustomSQLQuery.ParamByName(Const AParamName: String): TParam;
 
 begin
@@ -2544,6 +2534,17 @@ begin
   end;
 end;
 
+Procedure TCustomSQLQuery.ApplyUpdates(MaxErrors: Integer);
+begin
+  inherited ApplyUpdates(MaxErrors);
+  If sqoAutoCommit in Options then
+    begin
+    // Retrieve rows affected for last update.
+    FStatement.RowsAffected;
+    SQLTransaction.Commit;
+    end;
+end;
+
 Procedure TCustomSQLQuery.Post;
 begin
   inherited Post;
@@ -2643,7 +2644,9 @@ begin
   DoRefresh:=(UpdateKind in [ukModify,ukInsert]) and NeedRefreshRecord(UpdateKind);
   if assigned(LastIDField) or DoRefresh then
     begin
-    S:=SetTempState(dsNewValue);
+    // updates fields directly in record buffer of TBufDataSet
+    //   TDataSet buffers are resynchronized at end of ApplyUpdates process
+    S:=SetTempState(dsRefreshFields);
     try
       RecordRefreshed:=False;
       if assigned(LastIDField) then
@@ -2655,7 +2658,7 @@ begin
     end;
     if RecordRefreshed then
       // Active buffer is updated, move to record.
-      ActiveBufferToRecord;
+      //ActiveBufferToRecord;
     end;
 end;
 

+ 1 - 1
packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp

@@ -294,7 +294,7 @@ end;
 constructor TSQLite3Connection.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
-  FConnOptions := FConnOptions + [sqEscapeRepeat,sqEscapeSlash,sqLastInsertID];
+  FConnOptions := [sqEscapeRepeat, sqEscapeSlash, sqImplicitTransaction, sqLastInsertID];
   FieldNameQuoteChars:=DoubleQuotes;
 end;
 

+ 97 - 101
packages/fcl-db/tests/testsqldb.pas

@@ -31,9 +31,8 @@ type
   private
     FMyQ: TSQLQuery;
     procedure DoAfterPost(DataSet: TDataSet);
-    Procedure Allow;
     Procedure DoApplyUpdates;
-    Procedure SetQueryOptions;
+    Procedure TrySetQueryOptions;
     Procedure TrySetPacketRecords;
   Protected
     Procedure Setup; override;
@@ -87,14 +86,10 @@ implementation
 
 { TTestTSQLQuery }
 
-procedure TTestTSQLQuery.DoAfterPost(DataSet: TDataSet);
-begin
-  AssertTrue('Have modifications in after post',FMyq.UpdateStatus=usModified)
-end;
-
-Procedure TTestTSQLQuery.Allow;
+Procedure TTestTSQLQuery.Setup;
 begin
-
+  inherited Setup;
+  SQLDBConnector.Connection.Options:=[];
 end;
 
 procedure TTestTSQLQuery.TestMasterDetail;
@@ -115,6 +110,9 @@ begin
     CheckEquals('TestName1', DetailQuery.Fields[0].AsString);
     MasterQuery.MoveBy(3);
     CheckEquals('TestName4', DetailQuery.Fields[0].AsString);
+
+    MasterQuery.Close;
+    CheckTrue(DetailQuery.Active, 'Detail dataset should remain intact, when master dataset is closed');
   finally
     MasterSource.Free;
   end;
@@ -191,20 +189,21 @@ begin
   // Test also that an edit still works.
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdiscon');
-    ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
     Transaction.Commit;
     for I:=1 to 20 do
-      ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[i,i]));
+      ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
     Transaction.Commit;
+
     Q := SQLDBConnector.Query;
-    Q.SQL.Text:='select * from testdiscon';
+    Q.SQL.Text:='select * from FPDEV2';
     Q.Options:=[sqoKeepOpenOnCommit];
     AssertEquals('PacketRecords forced to -1',-1,Q.PacketRecords);
     Q.Open;
     AssertEquals('Got all records',20,Q.RecordCount);
     Q.SQLTransaction.Commit;
     AssertTrue('Still open after transaction',Q.Active);
+
     // Now check editing
     Q.Locate('id',20,[]);
     Q.Edit;
@@ -214,7 +213,7 @@ begin
     Q.ApplyUpdates;
     AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
     Q.Close;
-    Q.SQL.Text:='select * from testdiscon where (id=20) and (a=''abc'')';
+    Q.SQL.Text:='select * from FPDEV2 where (id=20) and (a=''abc'')';
     Q.Open;
     AssertTrue('Have modified data record in database', not (Q.EOF AND Q.BOF));
     end;
@@ -225,12 +224,6 @@ begin
   FMyQ.PacketRecords:=10;
 end;
 
-Procedure TTestTSQLQuery.Setup;
-begin
-  inherited Setup;
-  SQLDBConnector.Connection.Options:=[];
-end;
-
 Procedure TTestTSQLQuery.TestKeepOpenOnCommitPacketRecords;
 begin
   with SQLDBConnector do
@@ -241,7 +234,7 @@ begin
     end;
 end;
 
-Procedure TTestTSQLQuery.SetQueryOptions;
+Procedure TTestTSQLQuery.TrySetQueryOptions;
 begin
   FMyQ.Options:=[sqoKeepOpenOnCommit];
 end;
@@ -251,19 +244,23 @@ begin
   // Check that we can only set QueryOptions when the query is inactive.
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdiscon');
-    ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
-    Transaction.COmmit;
-     ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[1,1]));
-    Transaction.COmmit;
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
+    Transaction.Commit;
+    ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[1,1]));
+    Transaction.Commit;
     FMyQ := SQLDBConnector.Query;
-    FMyQ.SQL.Text:='select * from testdiscon';
+    FMyQ.SQL.Text:='select * from FPDEV2';
     FMyQ := SQLDBConnector.Query;
-    FMyQ.OPen;
-    AssertException('Cannot set packetrecords when sqoDisconnected is active',EDatabaseError,@SetQueryOptions);
+    FMyQ.Open;
+    AssertException('Cannot set Options when query is active',EDatabaseError,@TrySetQueryOptions);
     end;
 end;
 
+procedure TTestTSQLQuery.DoAfterPost(DataSet: TDataSet);
+begin
+  AssertTrue('Have modifications in after post',FMyq.UpdateStatus=usModified)
+end;
+
 Procedure TTestTSQLQuery.TestAutoApplyUpdatesPost;
 var Q: TSQLQuery;
     I: Integer;
@@ -272,15 +269,14 @@ begin
   // Test also that POST afterpost event is backwards compatible.
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdiscon');
-    ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
     Transaction.COmmit;
     for I:=1 to 2 do
-      ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[i,i]));
+      ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
     Transaction.COmmit;
     Q := SQLDBConnector.Query;
     FMyQ:=Q; // so th event handler can reach it.
-    Q.SQL.Text:='select * from testdiscon';
+    Q.SQL.Text:='select * from FPDEV2';
     Q.Options:=[sqoAutoApplyUpdates];
     // We must test that in AfterPost, the modification is still there, for backwards compatibilty
     Q.AfterPost:=@DoAfterPost;
@@ -293,7 +289,7 @@ begin
     Q.Post;
     AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
     Q.Close;
-    Q.SQL.Text:='select * from testdiscon where (id=2) and (a=''abc'')';
+    Q.SQL.Text:='select * from FPDEV2 where (id=2) and (a=''abc'')';
     Q.Open;
     AssertTrue('Have modified data record in database',not (Q.EOF AND Q.BOF));
     end;
@@ -308,15 +304,14 @@ begin
   // Test that if sqoAutoApplyUpdates is in QueryOptions, then Delete automatically does an ApplyUpdates
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdiscon');
-    ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
     Transaction.COmmit;
     for I:=1 to 2 do
-      ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[i,i]));
+      ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
     Transaction.COmmit;
     Q := SQLDBConnector.Query;
     FMyQ:=Q; // so th event handler can reach it.
-    Q.SQL.Text:='select * from testdiscon';
+    Q.SQL.Text:='select * from FPDEV2';
     Q.Options:=[sqoAutoApplyUpdates];
     // We must test that in AfterPost, the modification is still there, for backwards compatibilty
     Q.AfterPost:=@DoAfterPost;
@@ -327,7 +322,7 @@ begin
     Q.Delete;
     AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
     Q.Close;
-    Q.SQL.Text:='select * from testdiscon where (id=2)';
+    Q.SQL.Text:='select * from FPDEV2 where (id=2)';
     Q.Open;
     AssertTrue('Data record is deleted in database', (Q.EOF AND Q.BOF));
     end;
@@ -346,22 +341,21 @@ begin
   // Test that if sqoAutoApplyUpdates is in QueryOptions, then Delete automatically does an ApplyUpdates
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdiscon');
-    ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
     Transaction.COmmit;
     for I:=1 to 2 do
-      ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[i,i]));
+      ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
     Transaction.COmmit;
     SQLDBConnector.Connection.Options:=[scoApplyUpdatesChecksRowsAffected];
     Q := SQLDBConnector.Query;
-    Q.SQL.Text:='select * from testdiscon';
-    Q.DeleteSQL.Text:='delete from testdiscon';
+    Q.SQL.Text:='select * from FPDEV2';
+    Q.DeleteSQL.Text:='delete from FPDEV2';
     Q.Open;
     AssertEquals('Got all records',2,Q.RecordCount);
     // Now check editing
     Q.Delete;
     FMyQ:=Q;
-    AssertException('Rowsaffected > 1 raises exception',EUpdateError,@DoApplyUpdates);
+    AssertException('RowsAffected > 1 raises exception',EUpdateError,@DoApplyUpdates);
     end;
 end;
 
@@ -371,15 +365,14 @@ var
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdiscon');
-    ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
     if Transaction.Active then
       Transaction.Commit;
 
     Query.Options:=[sqoAutoCommit];
     for I:=1 to 2 do
       begin
-      Query.SQL.Text:=Format('INSERT INTO testdiscon values (%d,''%.6d'');',[i,i]);
+      Query.SQL.Text:=Format('INSERT INTO FPDEV2 values (%d,''%.6d'');',[i,i]);
       Query.Prepare;
       Query.ExecSQL;
       // We do not commit anything explicitly.
@@ -390,7 +383,7 @@ begin
     Connection.Close;
     Connection.Open;
 
-    Query.SQL.Text:='SELECT COUNT(*) from testdiscon';
+    Query.SQL.Text:='SELECT COUNT(*) from FPDEV2';
     Query.Open;
     AssertEquals('Records haven''t been committed to database', 2, Query.Fields[0].AsInteger);
     end;
@@ -403,23 +396,32 @@ var
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdefval');
-    ExecuteDirect('create table testdefval (id integer not null, a varchar(10) default ''abcde'', constraint pk_testdefval primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null primary key, a varchar(5) default ''abcde'', b integer default 1)');
     if Transaction.Active then
       Transaction.Commit;
     end;
   Q:=SQLDBConnector.Query;
-  Q.SQL.Text:='select * from testdefval';
-  Q.InsertSQL.Text:='insert into testdefval (id) values (:id)';
-  Q.RefreshSQL.Text:='SELECT a FROM testdefval WHERE (id=:id)';
+  Q.SQL.Text:='select * from FPDEV2';
+  Q.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
+  Q.RefreshSQL.Text:='SELECT a,b FROM FPDEV2 WHERE (id=:id)';
   Q.Open;
-  Q.Insert;
+  Q.Insert;  // #1 record
   Q.FieldByName('id').AsInteger:=1;
   Q.Post;
-  AssertTrue('field value has not been fetched after post',Q.FieldByName('a').IsNull);
+  Q.Append;  // #2 record
+  Q.FieldByName('id').AsInteger:=2;
+  Q.Post;
+  AssertTrue('Field value has not been fetched after Post', Q.FieldByName('a').IsNull);
   Q.ApplyUpdates(0);
-  AssertEquals('Still on correc field',1,Q.FieldByName('id').AsInteger);
-  AssertEquals('field value has been fetched from the database ','abcde',Q.FieldByName('a').AsString);
+  // #2 record:
+  AssertEquals('Still on correct field', 2, Q.FieldByName('id').AsInteger);
+  AssertEquals('Field value has been fetched from the database', 'abcde', Q.FieldByName('a').AsString);
+  AssertEquals('Field value has been fetched from the database', 1, Q.FieldByName('b').AsInteger);
+  Q.Prior;
+  // #1 record:
+  AssertEquals('Still on correct field', 1, Q.FieldByName('id').AsInteger);
+  AssertEquals('Field value has been fetched from the database', 'abcde', Q.FieldByName('a').AsString);
+  AssertEquals('Field value has been fetched from the database', 1, Q.FieldByName('b').AsInteger);
 end;
 
 Procedure TTestTSQLQuery.TestGeneratedRefreshSQL;
@@ -430,14 +432,13 @@ var
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdefval');
-    ExecuteDirect('create table testdefval (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint pk_testdefval primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
     if Transaction.Active then
       Transaction.Commit;
     end;
   Q:=SQLDBConnector.Query;
-  Q.SQL.Text:='select * from testdefval';
-  Q.InsertSQL.Text:='insert into testdefval (id) values (:id)';
+  Q.SQL.Text:='select * from FPDEV2';
+  Q.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
   Q.Open;
   With Q.FieldByName('id') do
     ProviderFlags:=ProviderFlags+[pfInKey];
@@ -448,11 +449,11 @@ begin
   Q.Insert;
   Q.FieldByName('id').AsInteger:=1;
   Q.Post;
-  AssertTrue('field value has not been fetched after post',Q.FieldByName('a').IsNull);
+  AssertTrue('Field value has not been fetched after post',Q.FieldByName('a').IsNull);
   Q.ApplyUpdates(0);
-  AssertEquals('Still on correc field',1,Q.FieldByName('id').AsInteger);
-  AssertEquals('field value has been fetched from the database ','abcde',Q.FieldByName('a').AsString);
-  AssertEquals('field value has been fetched from the database ','fgh',Q.FieldByName('b').AsString);
+  AssertEquals('Still on correct field',1,Q.FieldByName('id').AsInteger);
+  AssertEquals('Field value has been fetched from the database ','abcde',Q.FieldByName('a').AsString);
+  AssertEquals('Field value has been fetched from the database ','fgh',Q.FieldByName('b').AsString);
 end;
 
 Procedure TTestTSQLQuery.TestGeneratedRefreshSQL1Field;
@@ -462,14 +463,13 @@ var
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdefval');
-    ExecuteDirect('create table testdefval (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint pk_testdefval primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
     if Transaction.Active then
       Transaction.Commit;
     end;
   Q:=SQLDBConnector.Query;
-  Q.SQL.Text:='select * from testdefval';
-  Q.InsertSQL.Text:='insert into testdefval (id) values (:id)';
+  Q.SQL.Text:='select * from FPDEV2';
+  Q.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
   Q.Open;
   With Q.FieldByName('id') do
     ProviderFlags:=ProviderFlags+[pfInKey];
@@ -478,25 +478,24 @@ begin
   Q.Insert;
   Q.FieldByName('id').AsInteger:=1;
   Q.Post;
-  AssertTrue('field value has not been fetched after post',Q.FieldByName('a').IsNull);
+  AssertTrue('Field value has not been fetched after post',Q.FieldByName('a').IsNull);
   Q.ApplyUpdates(0);
-  AssertEquals('Still on correc field',1,Q.FieldByName('id').AsInteger);
-  AssertEquals('field value a has been fetched from the database ','abcde',Q.FieldByName('a').AsString);
-  AssertEquals('field value b has NOT been fetched from the database ','',Q.FieldByName('b').AsString);
+  AssertEquals('Still on correct field',1,Q.FieldByName('id').AsInteger);
+  AssertEquals('Field value a has been fetched from the database ','abcde',Q.FieldByName('a').AsString);
+  AssertEquals('Field value b has NOT been fetched from the database ','',Q.FieldByName('b').AsString);
 end;
 
 Procedure TTestTSQLQuery.TestGeneratedRefreshSQLNoKey;
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdefval');
-    ExecuteDirect('create table testdefval (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint pk_testdefval primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
     if Transaction.Active then
       Transaction.Commit;
     end;
   FMyQ:=SQLDBConnector.Query;
-  FMyQ.SQL.Text:='select * from testdefval';
-  FMyQ.InsertSQL.Text:='insert into testdefval (id) values (:id)';
+  FMyQ.SQL.Text:='select * from FPDEV2';
+  FMyQ.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
   FMyQ.Open;
   With FMyQ.FieldByName('id') do
     ProviderFlags:=ProviderFlags-[pfInKey];
@@ -513,18 +512,17 @@ Procedure TTestTSQLQuery.TestRefreshSQLMultipleRecords;
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdefval');
-    ExecuteDirect('create table testdefval (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint pk_testdefval primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
     if Transaction.Active then
       Transaction.Commit;
-    ExecuteDirect('insert into testdefval (id) values (123)');
+    ExecuteDirect('insert into FPDEV2 (id) values (123)');
     if Transaction.Active then
       Transaction.Commit;
     end;
   FMyQ:=SQLDBConnector.Query;
-  FMyQ.SQL.Text:='select * from testdefval';
-  FMyQ.InsertSQL.Text:='insert into testdefval (id) values (:id)';
-  FMyQ.RefreshSQL.Text:='select * from testdefval';
+  FMyQ.SQL.Text:='select * from FPDEV2';
+  FMyQ.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
+  FMyQ.RefreshSQL.Text:='select * from FPDEV2';
   FMyQ.Open;
   With FMyQ.FieldByName('id') do
     ProviderFlags:=ProviderFlags+[pfInKey];
@@ -540,18 +538,17 @@ Procedure TTestTSQLQuery.TestRefreshSQLNoRecords;
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdefval');
-    ExecuteDirect('create table testdefval (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint pk_testdefval primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
     if Transaction.Active then
       Transaction.Commit;
-    ExecuteDirect('insert into testdefval (id) values (123)');
+    ExecuteDirect('insert into FPDEV2 (id) values (123)');
     if Transaction.Active then
       Transaction.Commit;
     end;
   FMyQ:=SQLDBConnector.Query;
-  FMyQ.SQL.Text:='select * from testdefval';
-  FMyQ.InsertSQL.Text:='insert into testdefval (id) values (:id)';
-  FMyQ.RefreshSQL.Text:='select * from testdefval where 1=2';
+  FMyQ.SQL.Text:='select * from FPDEV2';
+  FMyQ.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
+  FMyQ.RefreshSQL.Text:='select * from FPDEV2 where 1=2';
   FMyQ.Open;
   With FMyQ.FieldByName('id') do
     ProviderFlags:=ProviderFlags+[pfInKey];
@@ -560,7 +557,7 @@ begin
   FMyQ.Insert;
   FMyQ.FieldByName('id').AsInteger:=1;
   FMyQ.Post;
-  AssertException('Multiple records returned by RefreshSQL gives an error',EUpdateError,@DoApplyUpdates);
+  AssertException('No records returned by RefreshSQL gives an error',EUpdateError,@DoApplyUpdates);
 end;
 
 Procedure TTestTSQLQuery.TestFetchAutoInc;
@@ -574,12 +571,13 @@ begin
     case SQLServerType of
       ssMySQL:
         datatype := 'integer auto_increment';
+      ssMSSQL, ssSybase:
+        datatype := 'integer identity';
       ssSQLite:
         datatype := 'integer';
       else
         Ignore(STestNotApplicable);
     end;
-    TryDropIfExist('FPDEV2');
     ExecuteDirect('create table FPDEV2 (id '+datatype+' primary key, f varchar(5))');
     CommitDDL;
     end;
@@ -590,18 +588,18 @@ begin
     Open;
     Insert;
     FieldByName('f').AsString:='a';
-    Post;
+    Post;  // #1 record
     Append;
     FieldByName('f').AsString:='b';
-    Post;
+    Post;  // #2 record
     AssertTrue('ID field is not null after Post', FieldByName('id').IsNull);
-    First;
+    First; // #1 record
     ApplyUpdates(0);
     AssertTrue('ID field is still null after ApplyUpdates', Not FieldByName('id').IsNull);
     // Should be 1 after the table was created, but this is not guaranteed... So we just test positive values.
     id := FieldByName('id').AsLargeInt;
     AssertTrue('ID field has not positive value', id>0);
-    Next;
+    Next;  // #2 record
     AssertTrue('Next ID value is not greater than previous', FieldByName('id').AsLargeInt>id);
     end;
 end;
@@ -655,7 +653,6 @@ end;
 
 procedure TTestTSQLConnection.TestImplicitTransactionOK;
 
-
 var
   Q : TSQLQuery;
   T : TSQLTransaction;
@@ -663,8 +660,7 @@ var
 begin
   with SQLDBConnector do
     begin
-    TryDropIfExist('testdiscon');
-    ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
+    ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
     if Transaction.Active then
       Transaction.Commit;
     end;
@@ -672,7 +668,7 @@ begin
   Q:=SQLDBConnector.Query;
   for I:=1 to 2 do
     begin
-    Q.SQL.Text:=Format('INSERT INTO testdiscon values (%d,''%.6d'');',[i,i]);
+    Q.SQL.Text:=Format('INSERT INTO FPDEV2 values (%d,''%.6d'');',[i,i]);
     Q.Prepare;
     Q.ExecSQL;
     // We do not commit anything explicitly.
@@ -685,7 +681,7 @@ begin
     Q.Transaction:=T;
     Q.Database:=SQLDBConnector.Connection;
     T.Database:=SQLDBConnector.Connection;
-    Q.SQL.text:='SELECT COUNT(*) from testdiscon';
+    Q.SQL.text:='SELECT COUNT(*) from FPDEV2';
     Q.Open;
     AssertEquals('Records have been committed to database',2,Q.Fields[0].AsInteger);
   finally

+ 2 - 0
packages/rtl-unicode/fpmake.pp

@@ -112,11 +112,13 @@ begin
     T.Install:=False;
     with T.Dependencies do
       begin
+        AddUnit('cp895',CPUnits);
         AddUnit('cp932',CPUnits);
         AddUnit('cp936',CPUnits);
         AddUnit('cp949',CPUnits);
         AddUnit('cp950',CPUnits);
       end;
+    T:=P.Targets.AddImplicitUnit('cp895.pas',CPUnits);
     T:=P.Targets.AddImplicitUnit('cp932.pas',CPUnits);
     T:=P.Targets.AddImplicitUnit('cp936.pas',CPUnits);
     T:=P.Targets.AddImplicitUnit('cp949.pas',CPUnits);

+ 543 - 0
packages/rtl-unicode/src/inc/cp895.pas

@@ -0,0 +1,543 @@
+{ This is an automatically created file, so don't edit it }
+unit cp895;
+
+  interface
+
+  implementation
+
+  uses
+     charset;
+
+  const
+     map : array[0..255] of tunicodecharmapping = (
+       (unicode : 0; flag : umf_noinfo; reserved: 0),
+       (unicode : 1; flag : umf_noinfo; reserved: 0),
+       (unicode : 2; flag : umf_noinfo; reserved: 0),
+       (unicode : 3; flag : umf_noinfo; reserved: 0),
+       (unicode : 4; flag : umf_noinfo; reserved: 0),
+       (unicode : 5; flag : umf_noinfo; reserved: 0),
+       (unicode : 6; flag : umf_noinfo; reserved: 0),
+       (unicode : 7; flag : umf_noinfo; reserved: 0),
+       (unicode : 8; flag : umf_noinfo; reserved: 0),
+       (unicode : 9; flag : umf_noinfo; reserved: 0),
+       (unicode : 10; flag : umf_noinfo; reserved: 0),
+       (unicode : 11; flag : umf_noinfo; reserved: 0),
+       (unicode : 12; flag : umf_noinfo; reserved: 0),
+       (unicode : 13; flag : umf_noinfo; reserved: 0),
+       (unicode : 14; flag : umf_noinfo; reserved: 0),
+       (unicode : 15; flag : umf_noinfo; reserved: 0),
+       (unicode : 16; flag : umf_noinfo; reserved: 0),
+       (unicode : 17; flag : umf_noinfo; reserved: 0),
+       (unicode : 18; flag : umf_noinfo; reserved: 0),
+       (unicode : 19; flag : umf_noinfo; reserved: 0),
+       (unicode : 20; flag : umf_noinfo; reserved: 0),
+       (unicode : 21; flag : umf_noinfo; reserved: 0),
+       (unicode : 22; flag : umf_noinfo; reserved: 0),
+       (unicode : 23; flag : umf_noinfo; reserved: 0),
+       (unicode : 24; flag : umf_noinfo; reserved: 0),
+       (unicode : 25; flag : umf_noinfo; reserved: 0),
+       (unicode : 26; flag : umf_noinfo; reserved: 0),
+       (unicode : 27; flag : umf_noinfo; reserved: 0),
+       (unicode : 28; flag : umf_noinfo; reserved: 0),
+       (unicode : 29; flag : umf_noinfo; reserved: 0),
+       (unicode : 30; flag : umf_noinfo; reserved: 0),
+       (unicode : 31; flag : umf_noinfo; reserved: 0),
+       (unicode : 32; flag : umf_noinfo; reserved: 0),
+       (unicode : 33; flag : umf_noinfo; reserved: 0),
+       (unicode : 34; flag : umf_noinfo; reserved: 0),
+       (unicode : 35; flag : umf_noinfo; reserved: 0),
+       (unicode : 36; flag : umf_noinfo; reserved: 0),
+       (unicode : 37; flag : umf_noinfo; reserved: 0),
+       (unicode : 38; flag : umf_noinfo; reserved: 0),
+       (unicode : 39; flag : umf_noinfo; reserved: 0),
+       (unicode : 40; flag : umf_noinfo; reserved: 0),
+       (unicode : 41; flag : umf_noinfo; reserved: 0),
+       (unicode : 42; flag : umf_noinfo; reserved: 0),
+       (unicode : 43; flag : umf_noinfo; reserved: 0),
+       (unicode : 44; flag : umf_noinfo; reserved: 0),
+       (unicode : 45; flag : umf_noinfo; reserved: 0),
+       (unicode : 46; flag : umf_noinfo; reserved: 0),
+       (unicode : 47; flag : umf_noinfo; reserved: 0),
+       (unicode : 48; flag : umf_noinfo; reserved: 0),
+       (unicode : 49; flag : umf_noinfo; reserved: 0),
+       (unicode : 50; flag : umf_noinfo; reserved: 0),
+       (unicode : 51; flag : umf_noinfo; reserved: 0),
+       (unicode : 52; flag : umf_noinfo; reserved: 0),
+       (unicode : 53; flag : umf_noinfo; reserved: 0),
+       (unicode : 54; flag : umf_noinfo; reserved: 0),
+       (unicode : 55; flag : umf_noinfo; reserved: 0),
+       (unicode : 56; flag : umf_noinfo; reserved: 0),
+       (unicode : 57; flag : umf_noinfo; reserved: 0),
+       (unicode : 58; flag : umf_noinfo; reserved: 0),
+       (unicode : 59; flag : umf_noinfo; reserved: 0),
+       (unicode : 60; flag : umf_noinfo; reserved: 0),
+       (unicode : 61; flag : umf_noinfo; reserved: 0),
+       (unicode : 62; flag : umf_noinfo; reserved: 0),
+       (unicode : 63; flag : umf_noinfo; reserved: 0),
+       (unicode : 64; flag : umf_noinfo; reserved: 0),
+       (unicode : 65; flag : umf_noinfo; reserved: 0),
+       (unicode : 66; flag : umf_noinfo; reserved: 0),
+       (unicode : 67; flag : umf_noinfo; reserved: 0),
+       (unicode : 68; flag : umf_noinfo; reserved: 0),
+       (unicode : 69; flag : umf_noinfo; reserved: 0),
+       (unicode : 70; flag : umf_noinfo; reserved: 0),
+       (unicode : 71; flag : umf_noinfo; reserved: 0),
+       (unicode : 72; flag : umf_noinfo; reserved: 0),
+       (unicode : 73; flag : umf_noinfo; reserved: 0),
+       (unicode : 74; flag : umf_noinfo; reserved: 0),
+       (unicode : 75; flag : umf_noinfo; reserved: 0),
+       (unicode : 76; flag : umf_noinfo; reserved: 0),
+       (unicode : 77; flag : umf_noinfo; reserved: 0),
+       (unicode : 78; flag : umf_noinfo; reserved: 0),
+       (unicode : 79; flag : umf_noinfo; reserved: 0),
+       (unicode : 80; flag : umf_noinfo; reserved: 0),
+       (unicode : 81; flag : umf_noinfo; reserved: 0),
+       (unicode : 82; flag : umf_noinfo; reserved: 0),
+       (unicode : 83; flag : umf_noinfo; reserved: 0),
+       (unicode : 84; flag : umf_noinfo; reserved: 0),
+       (unicode : 85; flag : umf_noinfo; reserved: 0),
+       (unicode : 86; flag : umf_noinfo; reserved: 0),
+       (unicode : 87; flag : umf_noinfo; reserved: 0),
+       (unicode : 88; flag : umf_noinfo; reserved: 0),
+       (unicode : 89; flag : umf_noinfo; reserved: 0),
+       (unicode : 90; flag : umf_noinfo; reserved: 0),
+       (unicode : 91; flag : umf_noinfo; reserved: 0),
+       (unicode : 92; flag : umf_noinfo; reserved: 0),
+       (unicode : 93; flag : umf_noinfo; reserved: 0),
+       (unicode : 94; flag : umf_noinfo; reserved: 0),
+       (unicode : 95; flag : umf_noinfo; reserved: 0),
+       (unicode : 96; flag : umf_noinfo; reserved: 0),
+       (unicode : 97; flag : umf_noinfo; reserved: 0),
+       (unicode : 98; flag : umf_noinfo; reserved: 0),
+       (unicode : 99; flag : umf_noinfo; reserved: 0),
+       (unicode : 100; flag : umf_noinfo; reserved: 0),
+       (unicode : 101; flag : umf_noinfo; reserved: 0),
+       (unicode : 102; flag : umf_noinfo; reserved: 0),
+       (unicode : 103; flag : umf_noinfo; reserved: 0),
+       (unicode : 104; flag : umf_noinfo; reserved: 0),
+       (unicode : 105; flag : umf_noinfo; reserved: 0),
+       (unicode : 106; flag : umf_noinfo; reserved: 0),
+       (unicode : 107; flag : umf_noinfo; reserved: 0),
+       (unicode : 108; flag : umf_noinfo; reserved: 0),
+       (unicode : 109; flag : umf_noinfo; reserved: 0),
+       (unicode : 110; flag : umf_noinfo; reserved: 0),
+       (unicode : 111; flag : umf_noinfo; reserved: 0),
+       (unicode : 112; flag : umf_noinfo; reserved: 0),
+       (unicode : 113; flag : umf_noinfo; reserved: 0),
+       (unicode : 114; flag : umf_noinfo; reserved: 0),
+       (unicode : 115; flag : umf_noinfo; reserved: 0),
+       (unicode : 116; flag : umf_noinfo; reserved: 0),
+       (unicode : 117; flag : umf_noinfo; reserved: 0),
+       (unicode : 118; flag : umf_noinfo; reserved: 0),
+       (unicode : 119; flag : umf_noinfo; reserved: 0),
+       (unicode : 120; flag : umf_noinfo; reserved: 0),
+       (unicode : 121; flag : umf_noinfo; reserved: 0),
+       (unicode : 122; flag : umf_noinfo; reserved: 0),
+       (unicode : 123; flag : umf_noinfo; reserved: 0),
+       (unicode : 124; flag : umf_noinfo; reserved: 0),
+       (unicode : 125; flag : umf_noinfo; reserved: 0),
+       (unicode : 126; flag : umf_noinfo; reserved: 0),
+       (unicode : 127; flag : umf_noinfo; reserved: 0),
+       (unicode : 268; flag : umf_noinfo; reserved: 0),
+       (unicode : 252; flag : umf_noinfo; reserved: 0),
+       (unicode : 233; flag : umf_noinfo; reserved: 0),
+       (unicode : 271; flag : umf_noinfo; reserved: 0),
+       (unicode : 228; flag : umf_noinfo; reserved: 0),
+       (unicode : 270; flag : umf_noinfo; reserved: 0),
+       (unicode : 356; flag : umf_noinfo; reserved: 0),
+       (unicode : 269; flag : umf_noinfo; reserved: 0),
+       (unicode : 283; flag : umf_noinfo; reserved: 0),
+       (unicode : 282; flag : umf_noinfo; reserved: 0),
+       (unicode : 313; flag : umf_noinfo; reserved: 0),
+       (unicode : 205; flag : umf_noinfo; reserved: 0),
+       (unicode : 318; flag : umf_noinfo; reserved: 0),
+       (unicode : 314; flag : umf_noinfo; reserved: 0),
+       (unicode : 196; flag : umf_noinfo; reserved: 0),
+       (unicode : 193; flag : umf_noinfo; reserved: 0),
+       (unicode : 201; flag : umf_noinfo; reserved: 0),
+       (unicode : 382; flag : umf_noinfo; reserved: 0),
+       (unicode : 381; flag : umf_noinfo; reserved: 0),
+       (unicode : 244; flag : umf_noinfo; reserved: 0),
+       (unicode : 246; flag : umf_noinfo; reserved: 0),
+       (unicode : 211; flag : umf_noinfo; reserved: 0),
+       (unicode : 367; flag : umf_noinfo; reserved: 0),
+       (unicode : 218; flag : umf_noinfo; reserved: 0),
+       (unicode : 253; flag : umf_noinfo; reserved: 0),
+       (unicode : 214; flag : umf_noinfo; reserved: 0),
+       (unicode : 220; flag : umf_noinfo; reserved: 0),
+       (unicode : 352; flag : umf_noinfo; reserved: 0),
+       (unicode : 317; flag : umf_noinfo; reserved: 0),
+       (unicode : 221; flag : umf_noinfo; reserved: 0),
+       (unicode : 344; flag : umf_noinfo; reserved: 0),
+       (unicode : 357; flag : umf_noinfo; reserved: 0),
+       (unicode : 225; flag : umf_noinfo; reserved: 0),
+       (unicode : 237; flag : umf_noinfo; reserved: 0),
+       (unicode : 243; flag : umf_noinfo; reserved: 0),
+       (unicode : 250; flag : umf_noinfo; reserved: 0),
+       (unicode : 328; flag : umf_noinfo; reserved: 0),
+       (unicode : 327; flag : umf_noinfo; reserved: 0),
+       (unicode : 366; flag : umf_noinfo; reserved: 0),
+       (unicode : 212; flag : umf_noinfo; reserved: 0),
+       (unicode : 353; flag : umf_noinfo; reserved: 0),
+       (unicode : 345; flag : umf_noinfo; reserved: 0),
+       (unicode : 341; flag : umf_noinfo; reserved: 0),
+       (unicode : 340; flag : umf_noinfo; reserved: 0),
+       (unicode : 188; flag : umf_noinfo; reserved: 0),
+       (unicode : 167; flag : umf_noinfo; reserved: 0),
+       (unicode : 171; flag : umf_noinfo; reserved: 0),
+       (unicode : 187; flag : umf_noinfo; reserved: 0),
+       (unicode : 9617; flag : umf_noinfo; reserved: 0),
+       (unicode : 9618; flag : umf_noinfo; reserved: 0),
+       (unicode : 9619; flag : umf_noinfo; reserved: 0),
+       (unicode : 9474; flag : umf_noinfo; reserved: 0),
+       (unicode : 9508; flag : umf_noinfo; reserved: 0),
+       (unicode : 9569; flag : umf_noinfo; reserved: 0),
+       (unicode : 9570; flag : umf_noinfo; reserved: 0),
+       (unicode : 9558; flag : umf_noinfo; reserved: 0),
+       (unicode : 9557; flag : umf_noinfo; reserved: 0),
+       (unicode : 9571; flag : umf_noinfo; reserved: 0),
+       (unicode : 9553; flag : umf_noinfo; reserved: 0),
+       (unicode : 9559; flag : umf_noinfo; reserved: 0),
+       (unicode : 9565; flag : umf_noinfo; reserved: 0),
+       (unicode : 9564; flag : umf_noinfo; reserved: 0),
+       (unicode : 9563; flag : umf_noinfo; reserved: 0),
+       (unicode : 9488; flag : umf_noinfo; reserved: 0),
+       (unicode : 9492; flag : umf_noinfo; reserved: 0),
+       (unicode : 9524; flag : umf_noinfo; reserved: 0),
+       (unicode : 9516; flag : umf_noinfo; reserved: 0),
+       (unicode : 9500; flag : umf_noinfo; reserved: 0),
+       (unicode : 9472; flag : umf_noinfo; reserved: 0),
+       (unicode : 9532; flag : umf_noinfo; reserved: 0),
+       (unicode : 9566; flag : umf_noinfo; reserved: 0),
+       (unicode : 9567; flag : umf_noinfo; reserved: 0),
+       (unicode : 9562; flag : umf_noinfo; reserved: 0),
+       (unicode : 9556; flag : umf_noinfo; reserved: 0),
+       (unicode : 9577; flag : umf_noinfo; reserved: 0),
+       (unicode : 9574; flag : umf_noinfo; reserved: 0),
+       (unicode : 9568; flag : umf_noinfo; reserved: 0),
+       (unicode : 9552; flag : umf_noinfo; reserved: 0),
+       (unicode : 9580; flag : umf_noinfo; reserved: 0),
+       (unicode : 9575; flag : umf_noinfo; reserved: 0),
+       (unicode : 9576; flag : umf_noinfo; reserved: 0),
+       (unicode : 9572; flag : umf_noinfo; reserved: 0),
+       (unicode : 9573; flag : umf_noinfo; reserved: 0),
+       (unicode : 9561; flag : umf_noinfo; reserved: 0),
+       (unicode : 9560; flag : umf_noinfo; reserved: 0),
+       (unicode : 9554; flag : umf_noinfo; reserved: 0),
+       (unicode : 9555; flag : umf_noinfo; reserved: 0),
+       (unicode : 9579; flag : umf_noinfo; reserved: 0),
+       (unicode : 9578; flag : umf_noinfo; reserved: 0),
+       (unicode : 9496; flag : umf_noinfo; reserved: 0),
+       (unicode : 9484; flag : umf_noinfo; reserved: 0),
+       (unicode : 9608; flag : umf_noinfo; reserved: 0),
+       (unicode : 9604; flag : umf_noinfo; reserved: 0),
+       (unicode : 9612; flag : umf_noinfo; reserved: 0),
+       (unicode : 9616; flag : umf_noinfo; reserved: 0),
+       (unicode : 9600; flag : umf_noinfo; reserved: 0),
+       (unicode : 945; flag : umf_noinfo; reserved: 0),
+       (unicode : 223; flag : umf_noinfo; reserved: 0),
+       (unicode : 915; flag : umf_noinfo; reserved: 0),
+       (unicode : 960; flag : umf_noinfo; reserved: 0),
+       (unicode : 931; flag : umf_noinfo; reserved: 0),
+       (unicode : 963; flag : umf_noinfo; reserved: 0),
+       (unicode : 181; flag : umf_noinfo; reserved: 0),
+       (unicode : 964; flag : umf_noinfo; reserved: 0),
+       (unicode : 934; flag : umf_noinfo; reserved: 0),
+       (unicode : 920; flag : umf_noinfo; reserved: 0),
+       (unicode : 937; flag : umf_noinfo; reserved: 0),
+       (unicode : 948; flag : umf_noinfo; reserved: 0),
+       (unicode : 8734; flag : umf_noinfo; reserved: 0),
+       (unicode : 966; flag : umf_noinfo; reserved: 0),
+       (unicode : 949; flag : umf_noinfo; reserved: 0),
+       (unicode : 8745; flag : umf_noinfo; reserved: 0),
+       (unicode : 8801; flag : umf_noinfo; reserved: 0),
+       (unicode : 177; flag : umf_noinfo; reserved: 0),
+       (unicode : 8805; flag : umf_noinfo; reserved: 0),
+       (unicode : 8804; flag : umf_noinfo; reserved: 0),
+       (unicode : 8992; flag : umf_noinfo; reserved: 0),
+       (unicode : 8993; flag : umf_noinfo; reserved: 0),
+       (unicode : 247; flag : umf_noinfo; reserved: 0),
+       (unicode : 8776; flag : umf_noinfo; reserved: 0),
+       (unicode : 176; flag : umf_noinfo; reserved: 0),
+       (unicode : 8729; flag : umf_noinfo; reserved: 0),
+       (unicode : 183; flag : umf_noinfo; reserved: 0),
+       (unicode : 8730; flag : umf_noinfo; reserved: 0),
+       (unicode : 8319; flag : umf_noinfo; reserved: 0),
+       (unicode : 178; flag : umf_noinfo; reserved: 0),
+       (unicode : 9632; flag : umf_noinfo; reserved: 0),
+       (unicode : 160; flag : umf_noinfo; reserved: 0)
+     );
+
+     reversemap : array[0..255] of treversecharmapping = (
+       (unicode : 0; char1 : 0; char2 : 0),
+       (unicode : 1; char1 : 1; char2 : 0),
+       (unicode : 2; char1 : 2; char2 : 0),
+       (unicode : 3; char1 : 3; char2 : 0),
+       (unicode : 4; char1 : 4; char2 : 0),
+       (unicode : 5; char1 : 5; char2 : 0),
+       (unicode : 6; char1 : 6; char2 : 0),
+       (unicode : 7; char1 : 7; char2 : 0),
+       (unicode : 8; char1 : 8; char2 : 0),
+       (unicode : 9; char1 : 9; char2 : 0),
+       (unicode : 10; char1 : 10; char2 : 0),
+       (unicode : 11; char1 : 11; char2 : 0),
+       (unicode : 12; char1 : 12; char2 : 0),
+       (unicode : 13; char1 : 13; char2 : 0),
+       (unicode : 14; char1 : 14; char2 : 0),
+       (unicode : 15; char1 : 15; char2 : 0),
+       (unicode : 16; char1 : 16; char2 : 0),
+       (unicode : 17; char1 : 17; char2 : 0),
+       (unicode : 18; char1 : 18; char2 : 0),
+       (unicode : 19; char1 : 19; char2 : 0),
+       (unicode : 20; char1 : 20; char2 : 0),
+       (unicode : 21; char1 : 21; char2 : 0),
+       (unicode : 22; char1 : 22; char2 : 0),
+       (unicode : 23; char1 : 23; char2 : 0),
+       (unicode : 24; char1 : 24; char2 : 0),
+       (unicode : 25; char1 : 25; char2 : 0),
+       (unicode : 26; char1 : 26; char2 : 0),
+       (unicode : 27; char1 : 27; char2 : 0),
+       (unicode : 28; char1 : 28; char2 : 0),
+       (unicode : 29; char1 : 29; char2 : 0),
+       (unicode : 30; char1 : 30; char2 : 0),
+       (unicode : 31; char1 : 31; char2 : 0),
+       (unicode : 32; char1 : 32; char2 : 0),
+       (unicode : 33; char1 : 33; char2 : 0),
+       (unicode : 34; char1 : 34; char2 : 0),
+       (unicode : 35; char1 : 35; char2 : 0),
+       (unicode : 36; char1 : 36; char2 : 0),
+       (unicode : 37; char1 : 37; char2 : 0),
+       (unicode : 38; char1 : 38; char2 : 0),
+       (unicode : 39; char1 : 39; char2 : 0),
+       (unicode : 40; char1 : 40; char2 : 0),
+       (unicode : 41; char1 : 41; char2 : 0),
+       (unicode : 42; char1 : 42; char2 : 0),
+       (unicode : 43; char1 : 43; char2 : 0),
+       (unicode : 44; char1 : 44; char2 : 0),
+       (unicode : 45; char1 : 45; char2 : 0),
+       (unicode : 46; char1 : 46; char2 : 0),
+       (unicode : 47; char1 : 47; char2 : 0),
+       (unicode : 48; char1 : 48; char2 : 0),
+       (unicode : 49; char1 : 49; char2 : 0),
+       (unicode : 50; char1 : 50; char2 : 0),
+       (unicode : 51; char1 : 51; char2 : 0),
+       (unicode : 52; char1 : 52; char2 : 0),
+       (unicode : 53; char1 : 53; char2 : 0),
+       (unicode : 54; char1 : 54; char2 : 0),
+       (unicode : 55; char1 : 55; char2 : 0),
+       (unicode : 56; char1 : 56; char2 : 0),
+       (unicode : 57; char1 : 57; char2 : 0),
+       (unicode : 58; char1 : 58; char2 : 0),
+       (unicode : 59; char1 : 59; char2 : 0),
+       (unicode : 60; char1 : 60; char2 : 0),
+       (unicode : 61; char1 : 61; char2 : 0),
+       (unicode : 62; char1 : 62; char2 : 0),
+       (unicode : 63; char1 : 63; char2 : 0),
+       (unicode : 64; char1 : 64; char2 : 0),
+       (unicode : 65; char1 : 65; char2 : 0),
+       (unicode : 66; char1 : 66; char2 : 0),
+       (unicode : 67; char1 : 67; char2 : 0),
+       (unicode : 68; char1 : 68; char2 : 0),
+       (unicode : 69; char1 : 69; char2 : 0),
+       (unicode : 70; char1 : 70; char2 : 0),
+       (unicode : 71; char1 : 71; char2 : 0),
+       (unicode : 72; char1 : 72; char2 : 0),
+       (unicode : 73; char1 : 73; char2 : 0),
+       (unicode : 74; char1 : 74; char2 : 0),
+       (unicode : 75; char1 : 75; char2 : 0),
+       (unicode : 76; char1 : 76; char2 : 0),
+       (unicode : 77; char1 : 77; char2 : 0),
+       (unicode : 78; char1 : 78; char2 : 0),
+       (unicode : 79; char1 : 79; char2 : 0),
+       (unicode : 80; char1 : 80; char2 : 0),
+       (unicode : 81; char1 : 81; char2 : 0),
+       (unicode : 82; char1 : 82; char2 : 0),
+       (unicode : 83; char1 : 83; char2 : 0),
+       (unicode : 84; char1 : 84; char2 : 0),
+       (unicode : 85; char1 : 85; char2 : 0),
+       (unicode : 86; char1 : 86; char2 : 0),
+       (unicode : 87; char1 : 87; char2 : 0),
+       (unicode : 88; char1 : 88; char2 : 0),
+       (unicode : 89; char1 : 89; char2 : 0),
+       (unicode : 90; char1 : 90; char2 : 0),
+       (unicode : 91; char1 : 91; char2 : 0),
+       (unicode : 92; char1 : 92; char2 : 0),
+       (unicode : 93; char1 : 93; char2 : 0),
+       (unicode : 94; char1 : 94; char2 : 0),
+       (unicode : 95; char1 : 95; char2 : 0),
+       (unicode : 96; char1 : 96; char2 : 0),
+       (unicode : 97; char1 : 97; char2 : 0),
+       (unicode : 98; char1 : 98; char2 : 0),
+       (unicode : 99; char1 : 99; char2 : 0),
+       (unicode : 100; char1 : 100; char2 : 0),
+       (unicode : 101; char1 : 101; char2 : 0),
+       (unicode : 102; char1 : 102; char2 : 0),
+       (unicode : 103; char1 : 103; char2 : 0),
+       (unicode : 104; char1 : 104; char2 : 0),
+       (unicode : 105; char1 : 105; char2 : 0),
+       (unicode : 106; char1 : 106; char2 : 0),
+       (unicode : 107; char1 : 107; char2 : 0),
+       (unicode : 108; char1 : 108; char2 : 0),
+       (unicode : 109; char1 : 109; char2 : 0),
+       (unicode : 110; char1 : 110; char2 : 0),
+       (unicode : 111; char1 : 111; char2 : 0),
+       (unicode : 112; char1 : 112; char2 : 0),
+       (unicode : 113; char1 : 113; char2 : 0),
+       (unicode : 114; char1 : 114; char2 : 0),
+       (unicode : 115; char1 : 115; char2 : 0),
+       (unicode : 116; char1 : 116; char2 : 0),
+       (unicode : 117; char1 : 117; char2 : 0),
+       (unicode : 118; char1 : 118; char2 : 0),
+       (unicode : 119; char1 : 119; char2 : 0),
+       (unicode : 120; char1 : 120; char2 : 0),
+       (unicode : 121; char1 : 121; char2 : 0),
+       (unicode : 122; char1 : 122; char2 : 0),
+       (unicode : 123; char1 : 123; char2 : 0),
+       (unicode : 124; char1 : 124; char2 : 0),
+       (unicode : 125; char1 : 125; char2 : 0),
+       (unicode : 126; char1 : 126; char2 : 0),
+       (unicode : 127; char1 : 127; char2 : 0),
+       (unicode : 160; char1 : 255; char2 : 0),
+       (unicode : 167; char1 : 173; char2 : 0),
+       (unicode : 171; char1 : 174; char2 : 0),
+       (unicode : 176; char1 : 248; char2 : 0),
+       (unicode : 177; char1 : 241; char2 : 0),
+       (unicode : 178; char1 : 253; char2 : 0),
+       (unicode : 181; char1 : 230; char2 : 0),
+       (unicode : 183; char1 : 250; char2 : 0),
+       (unicode : 187; char1 : 175; char2 : 0),
+       (unicode : 188; char1 : 172; char2 : 0),
+       (unicode : 193; char1 : 143; char2 : 0),
+       (unicode : 196; char1 : 142; char2 : 0),
+       (unicode : 201; char1 : 144; char2 : 0),
+       (unicode : 205; char1 : 139; char2 : 0),
+       (unicode : 211; char1 : 149; char2 : 0),
+       (unicode : 212; char1 : 167; char2 : 0),
+       (unicode : 214; char1 : 153; char2 : 0),
+       (unicode : 218; char1 : 151; char2 : 0),
+       (unicode : 220; char1 : 154; char2 : 0),
+       (unicode : 221; char1 : 157; char2 : 0),
+       (unicode : 223; char1 : 225; char2 : 0),
+       (unicode : 225; char1 : 160; char2 : 0),
+       (unicode : 228; char1 : 132; char2 : 0),
+       (unicode : 233; char1 : 130; char2 : 0),
+       (unicode : 237; char1 : 161; char2 : 0),
+       (unicode : 243; char1 : 162; char2 : 0),
+       (unicode : 244; char1 : 147; char2 : 0),
+       (unicode : 246; char1 : 148; char2 : 0),
+       (unicode : 247; char1 : 246; char2 : 0),
+       (unicode : 250; char1 : 163; char2 : 0),
+       (unicode : 252; char1 : 129; char2 : 0),
+       (unicode : 253; char1 : 152; char2 : 0),
+       (unicode : 268; char1 : 128; char2 : 0),
+       (unicode : 269; char1 : 135; char2 : 0),
+       (unicode : 270; char1 : 133; char2 : 0),
+       (unicode : 271; char1 : 131; char2 : 0),
+       (unicode : 282; char1 : 137; char2 : 0),
+       (unicode : 283; char1 : 136; char2 : 0),
+       (unicode : 313; char1 : 138; char2 : 0),
+       (unicode : 314; char1 : 141; char2 : 0),
+       (unicode : 317; char1 : 156; char2 : 0),
+       (unicode : 318; char1 : 140; char2 : 0),
+       (unicode : 327; char1 : 165; char2 : 0),
+       (unicode : 328; char1 : 164; char2 : 0),
+       (unicode : 340; char1 : 171; char2 : 0),
+       (unicode : 341; char1 : 170; char2 : 0),
+       (unicode : 344; char1 : 158; char2 : 0),
+       (unicode : 345; char1 : 169; char2 : 0),
+       (unicode : 352; char1 : 155; char2 : 0),
+       (unicode : 353; char1 : 168; char2 : 0),
+       (unicode : 356; char1 : 134; char2 : 0),
+       (unicode : 357; char1 : 159; char2 : 0),
+       (unicode : 366; char1 : 166; char2 : 0),
+       (unicode : 367; char1 : 150; char2 : 0),
+       (unicode : 381; char1 : 146; char2 : 0),
+       (unicode : 382; char1 : 145; char2 : 0),
+       (unicode : 915; char1 : 226; char2 : 0),
+       (unicode : 920; char1 : 233; char2 : 0),
+       (unicode : 931; char1 : 228; char2 : 0),
+       (unicode : 934; char1 : 232; char2 : 0),
+       (unicode : 937; char1 : 234; char2 : 0),
+       (unicode : 945; char1 : 224; char2 : 0),
+       (unicode : 948; char1 : 235; char2 : 0),
+       (unicode : 949; char1 : 238; char2 : 0),
+       (unicode : 960; char1 : 227; char2 : 0),
+       (unicode : 963; char1 : 229; char2 : 0),
+       (unicode : 964; char1 : 231; char2 : 0),
+       (unicode : 966; char1 : 237; char2 : 0),
+       (unicode : 8319; char1 : 252; char2 : 0),
+       (unicode : 8729; char1 : 249; char2 : 0),
+       (unicode : 8730; char1 : 251; char2 : 0),
+       (unicode : 8734; char1 : 236; char2 : 0),
+       (unicode : 8745; char1 : 239; char2 : 0),
+       (unicode : 8776; char1 : 247; char2 : 0),
+       (unicode : 8801; char1 : 240; char2 : 0),
+       (unicode : 8804; char1 : 243; char2 : 0),
+       (unicode : 8805; char1 : 242; char2 : 0),
+       (unicode : 8992; char1 : 244; char2 : 0),
+       (unicode : 8993; char1 : 245; char2 : 0),
+       (unicode : 9472; char1 : 196; char2 : 0),
+       (unicode : 9474; char1 : 179; char2 : 0),
+       (unicode : 9484; char1 : 218; char2 : 0),
+       (unicode : 9488; char1 : 191; char2 : 0),
+       (unicode : 9492; char1 : 192; char2 : 0),
+       (unicode : 9496; char1 : 217; char2 : 0),
+       (unicode : 9500; char1 : 195; char2 : 0),
+       (unicode : 9508; char1 : 180; char2 : 0),
+       (unicode : 9516; char1 : 194; char2 : 0),
+       (unicode : 9524; char1 : 193; char2 : 0),
+       (unicode : 9532; char1 : 197; char2 : 0),
+       (unicode : 9552; char1 : 205; char2 : 0),
+       (unicode : 9553; char1 : 186; char2 : 0),
+       (unicode : 9554; char1 : 213; char2 : 0),
+       (unicode : 9555; char1 : 214; char2 : 0),
+       (unicode : 9556; char1 : 201; char2 : 0),
+       (unicode : 9557; char1 : 184; char2 : 0),
+       (unicode : 9558; char1 : 183; char2 : 0),
+       (unicode : 9559; char1 : 187; char2 : 0),
+       (unicode : 9560; char1 : 212; char2 : 0),
+       (unicode : 9561; char1 : 211; char2 : 0),
+       (unicode : 9562; char1 : 200; char2 : 0),
+       (unicode : 9563; char1 : 190; char2 : 0),
+       (unicode : 9564; char1 : 189; char2 : 0),
+       (unicode : 9565; char1 : 188; char2 : 0),
+       (unicode : 9566; char1 : 198; char2 : 0),
+       (unicode : 9567; char1 : 199; char2 : 0),
+       (unicode : 9568; char1 : 204; char2 : 0),
+       (unicode : 9569; char1 : 181; char2 : 0),
+       (unicode : 9570; char1 : 182; char2 : 0),
+       (unicode : 9571; char1 : 185; char2 : 0),
+       (unicode : 9572; char1 : 209; char2 : 0),
+       (unicode : 9573; char1 : 210; char2 : 0),
+       (unicode : 9574; char1 : 203; char2 : 0),
+       (unicode : 9575; char1 : 207; char2 : 0),
+       (unicode : 9576; char1 : 208; char2 : 0),
+       (unicode : 9577; char1 : 202; char2 : 0),
+       (unicode : 9578; char1 : 216; char2 : 0),
+       (unicode : 9579; char1 : 215; char2 : 0),
+       (unicode : 9580; char1 : 206; char2 : 0),
+       (unicode : 9600; char1 : 223; char2 : 0),
+       (unicode : 9604; char1 : 220; char2 : 0),
+       (unicode : 9608; char1 : 219; char2 : 0),
+       (unicode : 9612; char1 : 221; char2 : 0),
+       (unicode : 9616; char1 : 222; char2 : 0),
+       (unicode : 9617; char1 : 176; char2 : 0),
+       (unicode : 9618; char1 : 177; char2 : 0),
+       (unicode : 9619; char1 : 178; char2 : 0),
+       (unicode : 9632; char1 : 254; char2 : 0)
+     );
+
+     unicodemap : tunicodemap = (
+       cpname : 'cp895';
+       cp : 895;
+       map : @map;
+       lastchar : 255;
+       reversemap : @reversemap;
+       reversemaplength : 256;
+       next : nil;
+       internalmap : true
+     );
+
+  begin
+     registermapping(@unicodemap)
+  end.

+ 1 - 1
packages/rtl-unicode/src/inc/cpbuildu.pp

@@ -1,7 +1,7 @@
 unit cpbuildu;
 // buildunit for cp*
 interface
-uses cp932,cp936,cp949,cp950;
+uses cp895,cp932,cp936,cp949,cp950;
 
 implementation
 

+ 275 - 0
rtl/ucmaps/cp895.txt

@@ -0,0 +1,275 @@
+#
+#    Name:     cp895_KamenickyBrothers to Unicode table
+#    Unicode version: 1.1
+#    Table version: 1.1
+#    Table format:  Format A
+#    Date:          03/31/95
+#    Authors:       Tomas Hajny based on public domain description of Kamenicky
+#                   brothers encoding found on Internet and cp437 created by:
+#                   Michel Suignard <[email protected]>
+#                   Lori Hoerth <[email protected]>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp895_KamenickyBrothers code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp895_KamenickyBrothers order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0a	0x000a	#LINE FEED
+0x0b	0x000b	#VERTICAL TABULATION
+0x0c	0x000c	#FORM FEED
+0x0d	0x000d	#CARRIAGE RETURN
+0x0e	0x000e	#SHIFT OUT
+0x0f	0x000f	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1a	0x001a	#SUBSTITUTE
+0x1b	0x001b	#ESCAPE
+0x1c	0x001c	#FILE SEPARATOR
+0x1d	0x001d	#GROUP SEPARATOR
+0x1e	0x001e	#RECORD SEPARATOR
+0x1f	0x001f	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2a	0x002a	#ASTERISK
+0x2b	0x002b	#PLUS SIGN
+0x2c	0x002c	#COMMA
+0x2d	0x002d	#HYPHEN-MINUS
+0x2e	0x002e	#FULL STOP
+0x2f	0x002f	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3a	0x003a	#COLON
+0x3b	0x003b	#SEMICOLON
+0x3c	0x003c	#LESS-THAN SIGN
+0x3d	0x003d	#EQUALS SIGN
+0x3e	0x003e	#GREATER-THAN SIGN
+0x3f	0x003f	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4a	0x004a	#LATIN CAPITAL LETTER J
+0x4b	0x004b	#LATIN CAPITAL LETTER K
+0x4c	0x004c	#LATIN CAPITAL LETTER L
+0x4d	0x004d	#LATIN CAPITAL LETTER M
+0x4e	0x004e	#LATIN CAPITAL LETTER N
+0x4f	0x004f	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5a	0x005a	#LATIN CAPITAL LETTER Z
+0x5b	0x005b	#LEFT SQUARE BRACKET
+0x5c	0x005c	#REVERSE SOLIDUS
+0x5d	0x005d	#RIGHT SQUARE BRACKET
+0x5e	0x005e	#CIRCUMFLEX ACCENT
+0x5f	0x005f	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6a	0x006a	#LATIN SMALL LETTER J
+0x6b	0x006b	#LATIN SMALL LETTER K
+0x6c	0x006c	#LATIN SMALL LETTER L
+0x6d	0x006d	#LATIN SMALL LETTER M
+0x6e	0x006e	#LATIN SMALL LETTER N
+0x6f	0x006f	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7a	0x007a	#LATIN SMALL LETTER Z
+0x7b	0x007b	#LEFT CURLY BRACKET
+0x7c	0x007c	#VERTICAL LINE
+0x7d	0x007d	#RIGHT CURLY BRACKET
+0x7e	0x007e	#TILDE
+0x7f	0x007f	#DELETE
+0x80	0x010c	#LATIN CAPITAL LETTER C WITH CARON
+0x81	0x00fc	#LATIN SMALL LETTER U WITH DIAERESIS
+0x82	0x00e9	#LATIN SMALL LETTER E WITH ACUTE
+0x83	0x010f	#LATIN SMALL LETTER D WITH CARON
+0x84	0x00e4	#LATIN SMALL LETTER A WITH DIAERESIS
+0x85	0x010e	#LATIN CAPITAL LETTER D WITH CARON
+0x86	0x0164	#LATIN CAPITAL LETTER T WITH CARON
+0x87	0x010d	#LATIN SMALL LETTER C WITH CARON
+0x88	0x011b	#LATIN SMALL LETTER E WITH CARON
+0x89	0x011a	#LATIN CAPITAL LETTER E WITH CARON
+0x8a	0x0139	#LATIN CAPITAL LETTER L WITH ACUTE
+0x8b	0x00cd	#LATIN CAPITAL LETTER I WITH ACUTE
+0x8c	0x013e	#LATIN SMALL LETTER L WITH CARON
+0x8d	0x013a	#LATIN SMALL LETTER L WITH ACUTE
+0x8e	0x00c4	#LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f	0x00c1	#LATIN CAPITAL LETTER A WITH ACUTE
+0x90	0x00c9	#LATIN CAPITAL LETTER E WITH ACUTE
+0x91	0x017e	#LATIN SMALL LETTER Z WITH CARON
+0x92	0x017d	#LATIN CAPITAL LETTER Z WITH CARON
+0x93	0x00f4	#LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x94	0x00f6	#LATIN SMALL LETTER O WITH DIAERESIS
+0x95	0x00d3	#LATIN CAPITAL LETTER O WITH ACUTE
+0x96	0x016f	#LATIN SMALL LETTER U WITH RING ABOVE
+0x97	0x00da	#LATIN CAPITAL LETTER U WITH ACUTE
+0x98	0x00fd	#LATIN SMALL LETTER Y WITH ACUTE
+0x99	0x00d6	#LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a	0x00dc	#LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b	0x0160	#LATIN CAPITAL LETTER S WITH CARON
+0x9c	0x013d	#LATIN CAPITAL LETTER L WITH CARON
+0x9d	0x00dd	#LATIN CAPITAL LETTER Y WITH ACUTE
+0x9e	0x0158	#LATIN CAPITAL LETTER R WITH CARON
+0x9f	0x0165	#LATIN SMALL LETTER T WITH CARON
+0xa0	0x00e1	#LATIN SMALL LETTER A WITH ACUTE
+0xa1	0x00ed	#LATIN SMALL LETTER I WITH ACUTE
+0xa2	0x00f3	#LATIN SMALL LETTER O WITH ACUTE
+0xa3	0x00fa	#LATIN SMALL LETTER U WITH ACUTE
+0xa4	0x0148	#LATIN SMALL LETTER N WITH CARON
+0xa5	0x0147	#LATIN CAPITAL LETTER N WITH CARON
+0xa6	0x016e	#LATIN CAPITAL LETTER U WITH RING ABOVE
+0xa7	0x00d4	#LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xa8	0x0161	#LATIN SMALL LETTER S WITH CARON
+0xa9	0x0159	#LATIN SMALL LETTER R WITH CARON
+0xaa	0x0155	#LATIN SMALL LETTER R WITH ACUTE
+0xab	0x0154	#LATIN CAPITAL LETTER R WITH ACUTE
+0xac	0x00bc	#VULGAR FRACTION ONE QUARTER
+0xad	0x00a7	#SECTION SIGN
+0xae	0x00ab	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf	0x00bb	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0	0x2591	#LIGHT SHADE
+0xb1	0x2592	#MEDIUM SHADE
+0xb2	0x2593	#DARK SHADE
+0xb3	0x2502	#BOX DRAWINGS LIGHT VERTICAL
+0xb4	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5	0x2561	#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6	0x2562	#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7	0x2556	#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8	0x2555	#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9	0x2563	#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba	0x2551	#BOX DRAWINGS DOUBLE VERTICAL
+0xbb	0x2557	#BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc	0x255d	#BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd	0x255c	#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe	0x255b	#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2	0x252c	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3	0x251c	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL
+0xc5	0x253c	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6	0x255e	#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7	0x255f	#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8	0x255a	#BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9	0x2554	#BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca	0x2569	#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb	0x2566	#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc	0x2560	#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd	0x2550	#BOX DRAWINGS DOUBLE HORIZONTAL
+0xce	0x256c	#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf	0x2567	#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0	0x2568	#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1	0x2564	#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2	0x2565	#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3	0x2559	#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4	0x2558	#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5	0x2552	#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6	0x2553	#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7	0x256b	#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8	0x256a	#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT
+0xda	0x250c	#BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb	0x2588	#FULL BLOCK
+0xdc	0x2584	#LOWER HALF BLOCK
+0xdd	0x258c	#LEFT HALF BLOCK
+0xde	0x2590	#RIGHT HALF BLOCK
+0xdf	0x2580	#UPPER HALF BLOCK
+0xe0	0x03b1	#GREEK SMALL LETTER ALPHA
+0xe1	0x00df	#LATIN SMALL LETTER SHARP S
+0xe2	0x0393	#GREEK CAPITAL LETTER GAMMA
+0xe3	0x03c0	#GREEK SMALL LETTER PI
+0xe4	0x03a3	#GREEK CAPITAL LETTER SIGMA
+0xe5	0x03c3	#GREEK SMALL LETTER SIGMA
+0xe6	0x00b5	#MICRO SIGN
+0xe7	0x03c4	#GREEK SMALL LETTER TAU
+0xe8	0x03a6	#GREEK CAPITAL LETTER PHI
+0xe9	0x0398	#GREEK CAPITAL LETTER THETA
+0xea	0x03a9	#GREEK CAPITAL LETTER OMEGA
+0xeb	0x03b4	#GREEK SMALL LETTER DELTA
+0xec	0x221e	#INFINITY
+0xed	0x03c6	#GREEK SMALL LETTER PHI
+0xee	0x03b5	#GREEK SMALL LETTER EPSILON
+0xef	0x2229	#INTERSECTION
+0xf0	0x2261	#IDENTICAL TO
+0xf1	0x00b1	#PLUS-MINUS SIGN
+0xf2	0x2265	#GREATER-THAN OR EQUAL TO
+0xf3	0x2264	#LESS-THAN OR EQUAL TO
+0xf4	0x2320	#TOP HALF INTEGRAL
+0xf5	0x2321	#BOTTOM HALF INTEGRAL
+0xf6	0x00f7	#DIVISION SIGN
+0xf7	0x2248	#ALMOST EQUAL TO
+0xf8	0x00b0	#DEGREE SIGN
+0xf9	0x2219	#BULLET OPERATOR
+0xfa	0x00b7	#MIDDLE DOT
+0xfb	0x221a	#SQUARE ROOT
+0xfc	0x207f	#SUPERSCRIPT LATIN SMALL LETTER N
+0xfd	0x00b2	#SUPERSCRIPT TWO
+0xfe	0x25a0	#BLACK SQUARE
+0xff	0x00a0	#NO-BREAK SPACE