unit LevelDB; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, StrUtils; type TForm_LevelDB = class(TForm) group_progress: TGroupBox; progress: TProgressBar; lbl_progress: TLabel; btn_abortok: TButton; lbl_estimation: TLabel; procedure btn_abortokClick(Sender: TObject); public procedure CreateDatabase(Source, Target: String); procedure CreateLevel(Source, Target: String); end; var Form_LevelDB: TForm_LevelDB; implementation {$R *.dfm} uses ABSMain, ABSDecUtil, Main, ConnectionManager, TypeDefs, DataAccess, OniImgClass, Data, RawList; var Converting: Boolean = False; Abort: Boolean = False; function GetOpenMsg(msg: TStatusMessages): String; begin case msg of SM_AlreadyOpened: Result := 'File already opened.'; SM_FileNotFound: Result := 'File not found.'; SM_UnknownExtension: Result := 'Unknown extension.'; SM_IncompatibleFile: Result := 'Incompatible file format.'; SM_UnknownError: Result := 'Unknown error.'; end; end; procedure TForm_LevelDB.CreateLevel(Source, Target: String); var DatHeader: THeader; FilesHeader: TFilesMap; NamedFilesHeader: TNamedFilesMap; ExtensionsHeader: TExtensionsMap; Stream_Body, Stream_Names: TMemoryStream; Stream_Dat, Stream_Raw, Stream_Sep: TFileStream; BeginTime, FileTime: Double; Step: Integer; LevelID: Integer; TimeFormat: TFormatSettings; ConID: Integer; Connection: TDataAccess; ConRepMsg: TStatusMessages; FileID: Integer; Strings: TStrings; i, j: Integer; temps: String; tempi: Integer; tempb: Byte; FileInfo: TFileInfo; DatLinks: TDatLinkList; RawLinks: TRawDataList; DatFileStream, RawFileStream: TMemoryStream; // ########################### datsum, linksum, rawsum: Int64; freq: Int64; tempticks1, tempticks2: Int64; // ########################### const Steps: Byte = 3; procedure DoStep(StepName: String); begin Inc(Step); if StepName <> 'FIN' then group_progress.Caption := 'Creating Dat (Step ' + IntToStr(Step) + '/' + IntToStr(Steps) + ': ' + StepName + ')' else group_progress.Caption := 'Creating Dat (FINISHED)'; end; procedure StopConvert; begin btn_abortok.Caption := '&Close'; btn_abortok.Default := True; converting := False; lbl_estimation.Caption := 'ABORTED'; group_progress.Caption := 'Creating Level (ABORTED)'; Stream_Body.Free; Stream_Names.Free; DatFileStream.Free; RawFileStream.Free; Stream_Dat.Free; Stream_Raw.Free; if Connection.DataOS in [DOS_WINDEMO, DOS_MAC, DOS_MACBETA] then Stream_Sep.Free; if MessageBox(Self.Handle, PChar('Delete the unfinished level-files?'), PChar('Delete files?'), MB_YESNO) = idYes then begin DeleteFile(target); DeleteFile(AnsiReplaceStr(Target, '.dat', '.raw')); if Connection.DataOS in [DOS_WINDEMO, DOS_MAC, DOS_MACBETA] then DeleteFile(AnsiReplaceStr(Target, '.dat', '.sep')); end; end; begin // // FILE EXISTS CHECK FÜR DAT/RAW/SEP!!! // TimeFormat.ShortTimeFormat := 'hh:nn:ss'; TimeFormat.LongTimeFormat := 'hh:nn:ss'; TimeFormat.TimeSeparator := ':'; ConID := ConManager.OpenConnection(Source, ConRepMsg); if not (ConRepMsg in [SM_OK, SM_AlreadyOpened]) then begin ShowMessage('Source-file couldn''t be opened! Aborting' + CrLf + GetOpenMsg(ConRepMsg)); Exit; end else Connection := ConManager.Connection[ConID]; ConID := ConManager.FileOpened(Target); if ConID >= 0 then begin if MessageBox(Self.Handle, PChar('Destination-file is opened, close it in ' + 'order to proceed conversion?'), PChar('Destination-file opened'), MB_YESNO + MB_ICONQUESTION) = ID_YES then begin if Form_Main.CheckConnectionCloseable(ConID) then if not ConManager.CloseConnection(ConID, ConRepMsg) then begin ShowMessage('Couldn''t close destination-file. Aborting'); Exit; end; end else begin ShowMessage('Aborting'); Exit; end; end; if FileExists(Target) then begin if MessageBox(Self.Handle, PChar('Destination-file exists. ' + 'Overwrite it?'), PChar('Destination-file exists'), MB_YESNO + MB_ICONWARNING) = ID_YES then begin if not DeleteFile(Target) then begin ShowMessage('Couldn''t delete file. Aborting'); Exit; end; if FileExists(AnsiReplaceStr(Target, '.dat', '.raw')) then if not DeleteFile(AnsiReplaceStr(Target, '.dat', '.raw')) then begin ShowMessage('Couldn''t delete file. Aborting'); Exit; end; if FileExists(AnsiReplaceStr(Target, '.dat', '.sep')) then if Connection.DataOS in [DOS_WINDEMO, DOS_MAC, DOS_MACBETA] then if not DeleteFile(AnsiReplaceStr(Target, '.dat', '.sep')) then begin ShowMessage('Couldn''t delete file. Aborting'); Exit; end; end else begin ShowMessage('Aborting'); Exit; end; end; LevelID := Connection.LevelNumber; LevelID := (LevelID * 2) * 256 * 256 * 256 + $01; Self.Visible := True; Form_Main.Visible := False; Step := 0; Converting := True; Abort := False; btn_abortok.Caption := '&Abort...'; btn_abortok.Default := False; BeginTime := Time; Stream_Body := TMemoryStream.Create; Stream_Names := TMemoryStream.Create; Stream_Dat := TFileStream.Create(Target, fmCreate); Stream_Raw := TFileStream.Create(AnsiReplaceStr(Target, '.dat', '.raw'), fmCreate); if Connection.DataOS in [DOS_WINDEMO, DOS_MAC, DOS_MACBETA] then Stream_Sep := TFileStream.Create(AnsiReplaceStr(Target, '.dat', '.sep'), fmCreate); DoStep('Creating header'); progress.Position := 0; lbl_progress.Caption := ''; lbl_estimation.Caption := 'Estimated finishing time: unknown'; Application.ProcessMessages; SetLength(NamedFilesHeader, 0); Strings := TStringList.Create; Strings := Connection.GetFilesList('', '', False, ST_ExtNameAsc); for i := 0 to Strings.Count - 1 do begin if MidStr(Strings.Strings[i], Pos('-', Strings.Strings[i]) + 1, Length(Strings.Strings[i]) - Pos('.', ReverseString(Strings.Strings[i])) - Pos('-', Strings.Strings[i]) ) <> '' then begin SetLength(NamedFilesHeader, Length(NamedFilesHeader) + 1); NamedFilesHeader[High(NamedFilesHeader)].FileNumber := StrToInt(MidStr(Strings.Strings[i], 1, 5)); NamedFilesHeader[High(NamedFilesHeader)].blubb := 0; end; end; for i := 0 to High(DatHeader.OSIdent) do case Connection.DataOS of DOS_WIN: DatHeader.OSIdent[i] := HeaderOSIdentWin[i]; DOS_MAC: DatHeader.OSIdent[i] := HeaderOSIdentMac[i]; DOS_MACBETA: DatHeader.OSIdent[i] := HeaderOSIdentMacBeta[i]; end; for i := 0 to High(DatHeader.GlobalIdent) do DatHeader.GlobalIdent[i] := HeaderGlobalIdent[i]; DatHeader.Files := Connection.GetFileCount; DatHeader.NamedFiles := Length(NamedFilesHeader); Strings := Connection.GetExtensionsList(EF_ExtCount); DatHeader.Extensions := Strings.Count; DatHeader.DataAddr := 0; DatHeader.DataSize := 0; DatHeader.NamesAddr := 0; DatHeader.NamesSize := 0; for i := 0 to High(DatHeader.Ident2) do DatHeader.Ident2[i] := 0; SetLength(FilesHeader, DatHeader.Files); SetLength(ExtensionsHeader, DatHeader.Extensions); DoStep('Writing extensions-header'); progress.Max := Strings.Count; Application.ProcessMessages; for i := 0 to Strings.Count - 1 do begin temps := Strings.Strings[i]; ExtensionsHeader[i].ExtCount := StrToInt( MidStr( temps, Pos('(', temps) + 1, Pos(')', temps) - Pos('(', temps) - 1 ) ); temps := MidStr(temps, 1, 4); for j := 0 to 3 do ExtensionsHeader[i].Extension[j] := temps[4-j]; for j := 0 to High(FileTypes) do if FileTypes[j].Extension = temps then Break; if j < Length(FileTypes) then begin case Connection.DataOS of DOS_WIN: ExtensionsHeader[i].Ident := FileTypes[j].IdentWin; DOS_WINDEMO: ExtensionsHeader[i].Ident := FileTypes[j].IdentMac; DOS_MAC: ExtensionsHeader[i].Ident := FileTypes[j].IdentMac; DOS_MACBETA: ExtensionsHeader[i].Ident := FileTypes[j].IdentMac; end; end else begin ShowMessage('Unknown Extension: ' + Strings.Strings[i]); Exit; end; progress.Position := i + 1; lbl_progress.Caption := 'Extensions done: ' + IntToStr(i + 1) + '/' + IntToStr(Strings.Count); Application.ProcessMessages; end; DoStep('Storing files-data'); progress.Position := 0; progress.Max := DatHeader.Files; lbl_progress.Caption := ''; lbl_estimation.Caption := 'Estimated finishing time: unknown'; Application.ProcessMessages; QueryPerformanceFrequency(freq); datsum := 0; linksum := 0; rawsum := 0; FileTime := Time; for FileID := 0 to DatHeader.Files - 1 do begin FileInfo := Connection.GetFileInfo(FileID); for j := 0 to 3 do FilesHeader[FileID].Extension[j] := FileInfo.Extension[4 - j]; if FileInfo.Size > 0 then begin QueryPerformanceCounter(tempticks1); FilesHeader[FileID].DataAddr := Stream_Body.Size + 8; DatFileStream := TMemoryStream.Create; Connection.LoadDatFile(FileID, TStream(DatFileStream)); DatFileStream.Seek(0, soFromBeginning); tempi := FileID * 256 + 1; DatFileStream.Write(tempi, 4); DatFileStream.Write(LevelID, 4); QueryPerformanceCounter(tempticks2); datsum := datsum + (tempticks2 - tempticks1); DatLinks := Connection.GetDatLinks(FileID); if Length(DatLinks) > 0 then begin for i := 0 to High(DatLinks) do begin DatFileStream.Seek(DatLinks[i].SrcOffset, soFromBeginning); if DatLinks[i].DestID < 0 then tempi := 0 else tempi := DatLinks[i].DestID * 256 + 1; DatFileStream.Write(tempi, 4); end; end; QueryPerformanceCounter(tempticks1); linksum := linksum + (tempticks1 - tempticks2); RawLinks := Connection.GetRawList(FileID); if Length(RawLinks) > 0 then begin for i := 0 to High(RawLinks) do begin if RawLinks[i].RawSize > 0 then begin RawFileStream := TMemoryStream.Create; Connection.LoadRawFile(FileID, RawLinks[i].SrcOffset, TStream(RawFileStream)); RawFileStream.Seek(0, soFromBeginning); if RawLinks[i].LocSep then begin RawLinks[i].RawAddr := Stream_Sep.Size; Stream_sep.CopyFrom(RawFileStream, RawFileStream.Size); end else begin RawLinks[i].RawAddr := Stream_Raw.Size; Stream_Raw.CopyFrom(RawFileStream, RawFileStream.Size); end; end else RawLinks[i].RawAddr := 0; DatFileStream.Seek(RawLinks[i].SrcOffset, soFromBeginning); DatFileStream.Write(RawLinks[i].RawAddr, 4); end; end; DatFileStream.Seek(0, soFromBeginning); Stream_Body.CopyFrom(DatFileStream, DatFileStream.Size); QueryPerformanceCounter(tempticks2); rawsum := rawsum + (tempticks2 - tempticks1); end else FilesHeader[FileID].DataAddr := 0; if Length(fileinfo.Name) > 0 then begin FilesHeader[FileID].NameAddr := Stream_Names.Size; temps := fileinfo.Extension + fileinfo.Name + Chr(0); Stream_Names.Write(temps[1], Length(temps)); end else FilesHeader[FileID].NameAddr := 0; FilesHeader[FileID].FileSize := fileinfo.Size; FilesHeader[FileID].FileType := fileinfo.FileType; if ((FileID mod 10) = 0) and (FileID >= 100) then lbl_estimation.Caption := 'Estimated time left: ' + TimeToStr( (Time - FileTime) / FileID * (progress.Max - FileID + 1) * 1.1, TimeFormat ); progress.Position := FileID + 1; lbl_progress.Caption := 'Files done: ' + IntToStr(FileID + 1) + '/' + IntToStr(progress.Max); Application.ProcessMessages; end; ShowMessage('AvgDats: ' + FloatToStr((datsum / progress.Max) / freq) + #13#10 + 'AvgLinks: ' + FloatToStr((linksum / progress.Max) / freq) + #13#10 + 'AvgRaws: ' + FloatToStr((rawsum / progress.Max) / freq) ); Stream_Dat.Write(DatHeader, SizeOf(DatHeader)); for i := 0 to High(FilesHeader) do Stream_Dat.Write(FilesHeader[i], SizeOf(FilesHeader[i])); for i := 0 to High(NamedFilesHeader) do Stream_Dat.Write(NamedFilesHeader[i], SizeOf(NamedFilesHeader[i])); for i := 0 to High(ExtensionsHeader) do Stream_Dat.Write(ExtensionsHeader[i], SizeOf(ExtensionsHeader[i])); DatHeader.DataSize := Stream_Body.Size; DatHeader.NamesSize := Stream_Names.Size; DatHeader.DataAddr := Stream_Dat.Size; Stream_Body.Seek(0, soFromBeginning); Stream_Dat.CopyFrom(Stream_Body, Stream_Body.Size); DatHeader.NamesAddr := Stream_Dat.Size; Stream_Names.Seek(0, soFromBeginning); Stream_Dat.CopyFrom(Stream_Names, Stream_Names.Size); Stream_Dat.Seek(0, soFromBeginning); Stream_Dat.Write(DatHeader, SizeOf(DatHeader)); Stream_Dat.Free; Stream_Body.Free; Stream_Names.Free; Stream_Raw.Free; if Connection.DataOS in [DOS_WINDEMO, DOS_MAC, DOS_MACBETA] then Stream_Sep.Free; progress.Position := progress.Max; lbl_progress.Caption := 'Files done: ' + IntToStr(progress.Max) + '/' + IntToStr(progress.Max); lbl_estimation.Caption := 'FINISHED (duration: ' + TimeToStr(Time - Begintime, TimeFormat) + ')'; DoStep('FIN'); btn_abortok.Caption := '&OK'; btn_abortok.Default := True; converting := False; // CloseDataConnection(DataConnections[conIndex]); end; procedure TForm_LevelDB.CreateDatabase(Source, target: String); var DataBase: TABSDatabase; Query: TABSQuery; MimeCoder: TStringFormat_MIME64; BeginTime, FileTime: Double; Step: Integer; LevelID: Integer; TimeFormat: TFormatSettings; ConID: Integer; Connection: TDataAccess; ConRepMsg: TStatusMessages; FileID: Integer; Strings: TStrings; i: Integer; temps: String; tempi: Integer; tempb: Byte; tempdata: TByteData; FileInfo: TFileInfo; DatLinks: TDatLinkList; RawLinks: TRawDataList; const steps: Byte = 2; procedure DoStep(stepname: String); begin Inc(step); if stepname <> 'FIN' then group_progress.Caption := 'Creating DB (Step ' + IntToStr(step) + '/' + IntToStr(steps) + ': ' + stepname + ')' else group_progress.Caption := 'Creating DB (FINISHED)'; end; procedure StopConvert; begin btn_abortok.Caption := '&Close'; btn_abortok.Default := True; converting := False; lbl_estimation.Caption := 'ABORTED'; group_progress.Caption := 'Creating DB (ABORTED)'; DataBase.Close; if MessageBox(Self.Handle, PChar('Delete the unfinished DB-file?'), PChar('Delete file?'), MB_YESNO) = idYes then begin DeleteFile(target); end; end; begin // // FILE EXISTS CHECK FÜR DAT/RAW/SEP!!! // TimeFormat.ShortTimeFormat := 'hh:nn:ss'; TimeFormat.LongTimeFormat := 'hh:nn:ss'; TimeFormat.TimeSeparator := ':'; ConID := ConManager.OpenConnection(Source, ConRepMsg); if not (ConRepMsg in [SM_OK, SM_AlreadyOpened]) then begin ShowMessage('Source-file couldn''t be opened! Aborting' + CrLf + GetOpenMsg(ConRepMsg)); Exit; end else Connection := ConManager.Connection[ConID]; ConID := ConManager.FileOpened(Target); if ConID >= 0 then begin if MessageBox(Self.Handle, PChar('Destination-file is opened, close it in ' + 'order to proceed conversion?'), PChar('Destination-file opened'), MB_YESNO + MB_ICONQUESTION) = ID_YES then begin if Form_Main.CheckConnectionCloseable(ConID) then if not ConManager.CloseConnection(ConID, ConRepMsg) then begin ShowMessage('Couldn''t close destination-file. Aborting'); Exit; end; end else begin ShowMessage('Aborting'); Exit; end; end; if FileExists(Target) then begin if MessageBox(Self.Handle, PChar('Destination-file exists. ' + 'Overwrite it?'), PChar('Destination-file exists'), MB_YESNO + MB_ICONWARNING) = ID_YES then begin if not DeleteFile(Target) then begin ShowMessage('Couldn''t delete file. Aborting'); Exit; end; end else begin ShowMessage('Aborting'); Exit; end; end; Self.Visible := True; Form_Main.Visible := False; step := 0; converting := True; abort := False; btn_abortok.Caption := '&Abort...'; btn_abortok.Default := False; BeginTime := Time; DataBase := TABSDatabase.Create(Self); DataBase.MaxConnections := 1; DataBase.PageSize := 8112; DataBase.PageCountInExtent := 8; DataBase.DatabaseName := 'OLDB'; DataBase.DatabaseFileName := target; DataBase.CreateDatabase; DoStep('Creating tables'); progress.Position := 0; lbl_progress.Caption := ''; lbl_estimation.Caption := 'Estimated finishing time: unknown'; Application.ProcessMessages; Query := TABSQuery.Create(Self); Query.DatabaseName := 'OLDB'; Query.SQL.Text := 'CREATE TABLE globals ( id AUTOINC PRIMARY KEY, name STRING(128), ' + 'value STRING(128) );'; Query.ExecSQL; Query.SQL.Text := 'CREATE TABLE linkmap ( id AUTOINC PRIMARY KEY, src_id INTEGER, ' + 'src_link_offset INTEGER, target_id INTEGER, INDEX idsrcid src_id, ' + 'INDEX iddestid target_id);'; Query.ExecSQL; Query.SQL.Text := 'CREATE TABLE rawmap ( id AUTOINC PRIMARY KEY, src_id INTEGER, ' + 'src_link_offset INTEGER, sep BOOLEAN, size INTEGER, ' + 'data BLOB BlobCompressionMode 9 BlobBlockSize 1024 BlobCompressionAlgorithm ZLib, ' + 'INDEX idsrcid src_id);'; // Query.SQL.Text:='CREATE TABLE rawmap ( id AUTOINC PRIMARY KEY, src_id INTEGER, src_link_offset INTEGER, size INTEGER, data BLOB BlobCompressionAlgorithm None );'; Query.ExecSQL; Query.SQL.Text := 'CREATE TABLE datfiles ( id INTEGER PRIMARY KEY, extension CHAR(4), ' + 'name STRING(128), contenttype INTEGER, size INTEGER, ' + 'data BLOB BlobCompressionMode 9 BlobBlockSize 1024 BlobCompressionAlgorithm ZLib );'; // Query.SQL.Text:='CREATE TABLE datfiles ( id INTEGER PRIMARY KEY, extension CHAR(4), name STRING(128), contenttype INTEGER, size INTEGER, data BLOB BlobCompressionAlgorithm None );'; Query.ExecSQL; // Query.SQL.Text := // 'CREATE TABLE extlist ( id AUTOINC PRIMARY KEY, ext CHAR(4), ident CHAR(16) );'; // Query.ExecSQL; Query.SQL.Text := 'INSERT INTO globals (name,value) VALUES ("dbversion","' + dbversion + '");'; Query.ExecSQL; Query.SQL.Text := 'INSERT INTO globals (name,value) VALUES ("lvl","' + IntToStr(Connection.LevelNumber) + '");'; Query.ExecSQL; case Connection.DataOS of DOS_WIN: temps := 'WIN'; DOS_WINDEMO: temps := 'WINDEMO'; DOS_MAC: temps := 'MAC'; DOS_MACBETA: temps := 'MACBETA'; end; Query.SQL.Text := 'INSERT INTO globals (name,value) VALUES ("os","' + temps + '");'; Query.ExecSQL; progress.Position := 0; lbl_progress.Caption := 'Files done: ' + IntToStr(0) + '/' + IntToStr( Connection.GetFileCount); lbl_estimation.Caption := 'Estimated finishing time: unknown'; progress.Max := Connection.GetFileCount; begintime := Time; DoStep('Writing .dat-fileslist'); Application.ProcessMessages; Database.StartTransaction; for FileID := 0 to Connection.GetFileCount - 1 do begin fileinfo := Connection.GetFileInfo(FileID); if (fileinfo.FileType and $02) = 0 then begin mimecoder := TStringFormat_MIME64.Create; Connection.LoadDatFile(FileID, tempdata); Query.SQL.Text := 'INSERT INTO datfiles (id,extension,name,contenttype,size,data) VALUES (' + IntToStr(FileID) + ',"' + fileinfo.Extension + '","' + fileinfo.Name + '","' + IntToHex( fileinfo.FileType, 8) + '",' + IntToStr(fileinfo.Size) + ',MimeToBin("' + MimeCoder.StrTo(@tempdata[0], Length(tempdata)) + '") );'; Query.ExecSQL; mimecoder.Free; RawLinks := Connection.GetRawList(FileID); if Length(RawLinks) > 0 then begin for i := 0 to High(RawLinks) do begin if RawLinks[i].RawSize > 0 then begin SetLength(tempdata, RawLinks[i].RawSize); Connection.LoadRawFile(FileID, RawLinks[i].SrcOffset, tempdata); mimecoder := TStringFormat_MIME64.Create; Query.SQL.Text := 'INSERT INTO rawmap (src_id,src_link_offset,sep,size,data) VALUES (' + IntToStr(FileID) + ', ' + IntToStr(RawLinks[i].SrcOffset) + ',' + BoolToStr(RawLinks[i].LocSep) + ', ' + IntToStr(RawLinks[i].RawSize) + ', ' + 'MimeToBin("' + MimeCoder.StrTo(@tempdata[0], RawLinks[i].RawSize) + '") );'; Query.ExecSQL; mimecoder.Free; end else begin Query.SQL.Text := 'INSERT INTO rawmap (src_id,src_link_offset,sep,size) VALUES (' + IntToStr(FileID) + ', ' + IntToStr(RawLinks[i].SrcOffset) + ', ' + BoolToStr(RawLinks[i].LocSep) + ', 0);'; Query.ExecSQL; end; end; end; DatLinks := Connection.GetDatLinks(FileID); if Length(DatLinks) > 0 then begin for i := 0 to High(DatLinks) do begin Query.SQL.Text := 'INSERT INTO linkmap (src_id, src_link_offset, target_id) VALUES (' + IntToStr(FileID) + ', ' + IntToStr(DatLinks[i].SrcOffset) + ', ' + IntToStr(DatLinks[i].DestID) + ');'; Query.ExecSQL; end; end; end else begin Query.SQL.Text := 'INSERT INTO datfiles (id,extension,name,contenttype,size) VALUES (' + IntToStr(FileID) + ', "' + fileinfo.Extension + '", ' + '"' + fileinfo.Name + '", "' + IntToHex(fileinfo.FileType, 8) + '", 0);'; Query.ExecSQL; end; if ((FileID mod 100) = 0) and (FileID > 0) then begin Database.Commit(False); Database.StartTransaction; end; if ((FileID mod 10) = 0) and (FileID >= 100) then lbl_estimation.Caption := 'Estimated time left: ' + TimeToStr( (Time - BeginTime) / FileID * (progress.Max - FileID + 1) * 1.1, timeformat ); progress.Position := FileID; lbl_progress.Caption := 'Files done: ' + IntToStr(FileID) + '/' + IntToStr(progress.Max); Application.ProcessMessages; if abort then begin StopConvert; Exit; end; end; Database.Commit(False); progress.Position := progress.Max; lbl_progress.Caption := 'Files done: ' + IntToStr(progress.Max) + '/' + IntToStr(progress.Max); lbl_estimation.Caption := 'FINISHED (duration: ' + TimeToStr(Time - BeginTime, timeformat) + ')'; DoStep('FIN'); btn_abortok.Caption := '&OK'; btn_abortok.Default := True; converting := False; Query.Close; Query.Free; DataBase.Close; DataBase.Free; end; procedure TForm_LevelDB.btn_abortokClick(Sender: TObject); begin if converting then begin if MessageBox(Self.Handle, PChar('Do you really want to cancel the convert-progress?'), PChar('Warning: Converting'), MB_YESNO) = idYes then abort := True; end else begin Self.Visible := False; Form_Main.Visible := True; end; end; end.