Index: /oup/current/Code/Exporters.pas
===================================================================
--- /oup/current/Code/Exporters.pas	(revision 73)
+++ /oup/current/Code/Exporters.pas	(revision 74)
@@ -6,22 +6,23 @@
 
 procedure ExportDatFile(fileid: LongWord; filename: String);
+procedure ExportRawFiles(fileid: LongWord; filename: String);
 procedure ExportRawFile(fileid: LongWord; dat_offset: LongWord; filename: String);
-
-function ExportSNDD(fileid: LongWord; filename: String; convert: Boolean): Integer;
-function ExportTRAC(fileid: LongWord; filename: String; convert: Boolean): Integer;
-function ExportTXAN(fileid: LongWord; filename: String; convert: Boolean): Integer;
-function ExportTXMB(fileid: LongWord; filename: String; convert: Boolean): Integer;
-function ExportTXMP(fileid: LongWord; filename: String; convert: Boolean): Integer;
-
-var
-  ExportHandlers: array[1..1] of TExportHandlers = (
-    //    (Ext:'ABNA'; needed:False),
-    //(Ext:'AGDB'; needed:False),
-    (Ext: 'SNDD'; needed: True; Handler: ExportSNDD)
-{    (Ext:'TRAC'; needed:True; Handler:ExportTRAC),
-    (Ext:'TXAN'; needed:True; Handler:ExportTXAN),
-    (Ext:'TXMB'; needed:True; Handler:ExportTXMB),
-    (Ext:'TXMP'; needed:True; Handler:ExportTXMP)
-});
+function ExportConverted(fileid: LongWord; filename: String): Integer;
+
+function ExportSNDD(fileid: LongWord; filename: String): Integer;
+function ExportTRAC(fileid: LongWord; filename: String): Integer;
+function ExportTXAN(fileid: LongWord; filename: String): Integer;
+function ExportImage(fileid: LongWord; filename: String): Integer;
+
+var
+  ExportHandlers: array[1..3] of TExportHandlers = (
+//    (Ext:'ABNA'; needed:False),
+//    (Ext:'AGDB'; needed:False),
+    (Ext: 'SNDD'; needed: True; Handler: ExportSNDD),
+//    (Ext:'TRAC'; needed:True; Handler:ExportTRAC),
+//    (Ext:'TXAN'; needed:True; Handler:ExportTXAN),
+    (Ext:'TXMB'; needed:True; Handler:ExportImage),
+    (Ext:'TXMP'; needed:True; Handler:ExportImage)
+);
 
 
@@ -30,5 +31,4 @@
 
 uses Functions, DataStructures, OniDataClass;
-
 
 
@@ -54,5 +54,14 @@
 
 
-
+procedure ExportRawFiles(fileid: LongWord; filename: String);
+var
+  i: Integer;
+  rawlist: TRawList;
+begin
+  rawlist := OniDataConnection.GetRawList(fileid);
+  if Length(rawlist) > 0 then
+    for i := 0 to High(rawlist) do
+      ExportRawFile(fileid, rawlist[i].src_offset, filename);
+end;
 
 procedure ExportRawFile(fileid: LongWord; dat_offset: LongWord; filename: String);
@@ -77,47 +86,58 @@
 end;
 
+function ExportConverted(fileid: LongWord; filename: String): Integer;
+var
+  i: Integer;
+  fileinfo: TFileInfo;
+begin
+  fileinfo := OniDataConnection.GetFileInfo(fileid);
+  if Length(ExportHandlers) > 0 then
+    for i := 0 to High(ExportHandlers) do
+      if ExportHandlers[i].Ext = fileinfo.Extension then
+        ExportHandlers[i].Handler(fileid, filename);
+end;
+
 
 
 
 function ExportSNDD;
-{  CONST
-    WAVheader:Array[0..0] OF Byte=(
-        Ord('R'),Ord('I'),Ord('F'),Ord('F'),0,0,0,0,Ord('W'),Ord('A'),Ord('V'),Ord('E'),
-        Ord('f'),Ord('m'),Ord('t'),Ord(' '),24,0,0,0,
-      );
-}  type
-  TDatData = record
+type
+  TDatData = packed record
     {0x00}
-    _fileid:   LongWord;
-    level:     LongWord;
-    Flag:      LongWord;
-    FormatTag: Word;
-    ChanNo:    Word;
+    _fileid:         LongWord;
+    level:           LongWord;
+    FormatSize:      LongWord;
+    AudioFormat:     Word;
+    NumChannels:     Word;
     {0x10}
-    SampleRate: LongWord;
-    BytesPSec: LongWord;
-    BPSample:  LongWord;
-    BitsPS:    LongWord;
-    {0x20}
-    Unknown:   array[1..7] of LongWord;
-    Unknown2:  Word;
+    SampleRate:      LongWord;
+    ByteRate:        LongWord;
+    BlockAlign:      Word;
+    BitsPerSample:   Word;
+    {0x1C}
+    SizeExtHeader:   Word;
+    SamplesPerBlock: Word;
+    NumCoefficients: Word;
+    Coefficients:    array[0..6] of LongWord;
+    {0x3E}
+    Duration:        Word;
     {0x40}
-    RawSize:   LongWord;
-    RawPos:    LongWord;
-  end;
-var
-  filestream: TFileStream;
-
+    RawSize:         LongWord;
+    RawPos:          LongWord;
+  end;
+var
+  filestream: TFileStream;
   DatData:     TDatData;
+  i: Integer;
+  Data: Tdata;
+
   //Wave Header Stuff
-  ASCII_Group: LongWord; //"RIFF"
-  WAV_Len:     LongWord;
-  ASCII_WAV:   LongWord; //"WAVE"
-  ASCII_FMT:   LongWord; //"fmt "
-  WAV_FMT_Len: LongWord;
-  ASCII_DATA:  LongWord; //"data"
-  WAV_FolLen:  LongWord;
-
-  Data: Tdata;
+  ASCII_RIFF:   LongWord; //"RIFF"
+  WAVE_Len:     LongWord;
+  ASCII_WAVE:   LongWord; //"WAVE"
+  ASCII_FMT:    LongWord; //"fmt "
+  WAVE_FMT_Len: LongWord;
+  ASCII_DATA:   LongWord; //"data"
+  WAVE_DataLen:  LongWord;
 begin
   Result := export_noerror;
@@ -126,39 +146,36 @@
   begin
     //Initializing Header vars
-    ASCII_Group := 1179011410; // 'RIFF'
-    WAV_Len     := RAWSize + 70;
-    ASCII_WAV   := 1163280727;  // 'WAVE'
-    ASCII_FMT   := 544501094;   // 'fmt '
-    WAV_FMT_Len := 50;          // 50 bytes
-    ASCII_DATA  := 1635017060;  // 'data'
-    WAV_FolLen  := RAWSize;
+    ASCII_RIFF   := 1179011410; // 'RIFF'
+    WAVE_Len     := RAWSize + 70;
+    ASCII_WAVE   := 1163280727;  // 'WAVE'
+    ASCII_FMT    := 544501094;   // 'fmt '
+    WAVE_FMT_Len := 50;          // 50 bytes
+    ASCII_DATA   := 1635017060;  // 'data'
+    WAVE_DataLen := RAWSize;
     SetLength(Data, RAWSize);
     OniDataConnection.LoadRawFile(fileid, $44, Data);
 
-    filestream := TFileStream.Create(filename + '.raw', fmCreate);
+    //Now start packing this into a neat wave...
+    filestream := TFileStream.Create(filename + '.wav', fmCreate);
+    filestream.Write(ASCII_RIFF, SizeOf(ASCII_RIFF));
+    filestream.Write(WAVE_Len, SizeOf(WAVE_Len));
+    filestream.Write(ASCII_WAVE, SizeOf(ASCII_WAVE));
+    filestream.Write(ASCII_FMT, SizeOf(ASCII_FMT));
+    filestream.Write(WAVE_FMT_Len, SizeOf(WAVE_FMT_Len));
+    filestream.Write(AudioFormat, SizeOf(AudioFormat));
+    filestream.Write(NumChannels, SizeOf(NumChannels));
+    filestream.Write(Samplerate, SizeOf(Samplerate));
+    filestream.Write(ByteRate, SizeOf(ByteRate));
+    filestream.Write(BlockAlign, SizeOf(BlockAlign));
+    filestream.Write(BitsPerSample, SizeOf(BitsPerSample));
+    filestream.Write(SizeExtHeader, SizeOf(SizeExtHeader));
+    filestream.Write(SamplesPerBlock, SizeOf(SamplesPerBlock));
+    filestream.Write(NumCoefficients, SizeOf(NumCoefficients));
+    for i := 0 to High(Coefficients) do
+      filestream.Write(Coefficients[i], SizeOf(Coefficients[i]));
+    filestream.Write(ASCII_DATA, SizeOf(ASCII_DATA));
+    filestream.Write(WAVE_DataLen, SizeOf(WAVE_DataLen));
     filestream.Write(Data[0], Length(Data));
     filestream.Free;
-
-    if convert then
-    begin
-      //Now start packing this into a neat wave...
-      filestream := TFileStream.Create(filename + '.wav', fmCreate);
-      filestream.Write(ASCII_Group, SizeOf(ASCII_Group));
-      filestream.Write(WAV_Len, SizeOf(WAV_Len));
-      filestream.Write(ASCII_WAV, SizeOf(ASCII_WAV));
-      filestream.Write(ASCII_FMT, SizeOf(ASCII_FMT));
-      filestream.Write(WAV_FMT_Len, SizeOf(WAV_FMT_Len));
-      filestream.Write(ChanNo, SizeOf(ChanNo));
-      filestream.Write(Samplerate, SizeOf(Samplerate));
-      filestream.Write(BytesPSec, SizeOf(BytesPSec));
-      filestream.Write(BPSample, SizeOf(BPSample));
-      filestream.Write(BitsPS, SizeOf(BitsPS));
-      filestream.Write(Unknown[1], SizeOf(Unknown));
-      filestream.Write(Unknown2, SizeOf(Unknown2));
-      filestream.Write(ASCII_DATA, SizeOf(ASCII_DATA));
-      filestream.Write(WAV_FolLen, SizeOf(WAV_FolLen));
-      filestream.Write(Data[0], Length(Data));
-      filestream.Free;
-    end;
   end;
 end;
@@ -214,43 +231,21 @@
 
 
-function ExportTXMB;
-var
-  filestream: TFileStream;
-  //    img:TImgPackage;
-  Data: Tdata;
-begin
-  Result := export_noerror;
-  if convert then
-  begin
-{      img:=LoadTXMBconnected(fileid);
-      data:=ImgdataToBmp(img.imgx,img.imgy,img.imgdepth,img.storetype,img.imgdata);
-      filestream:=TFileStream.Create(filename+'.bmp',fmCreate);
-      filestream.Write(data[0],Length(data));
-      filestream.Free;
-}    end;
-end;
-
-
-
-
-function ExportTXMP;
-var
-  filestream: TFileStream;
-  //    img:TImgPackage;
-begin
-  Result := export_noerror;
-{    img:=LoadImgData(fileid);
-
-    filestream:=TFileStream.Create(filename+'.raw',fmCreate);
-    filestream.Write(img.imgdata[0],Length(img.imgdata));
-    filestream.Free;
-
-    IF convert THEN BEGIN
-      img.imgdata:=ImgdataToBMP(img.imgx,img.imgy,img.imgdepth,img.storetype,img.imgdata);
-      filestream:=TFileStream.Create(filename+'.bmp',fmCreate);
-      filestream.Write(img.imgdata[0],Length(img.imgdata));
-      filestream.Free;
-    END;
-}  end;
+function ExportImage;
+var
+  filestream: TFileStream;
+  img: TOniImage;
+  data: Tdata;
+begin
+  Result := export_noerror;
+
+  img := TOniImage.Create;
+  img.Load(fileid);
+  data := img.GetAsBMP;
+  img.Free;
+
+  filestream:=TFileStream.Create(filename+'.bmp',fmCreate);
+  filestream.Write(data[0],Length(data));
+  filestream.Free;
+end;
 
 end.
Index: /oup/current/Code/FolderBrowser.pas
===================================================================
--- /oup/current/Code/FolderBrowser.pas	(revision 74)
+++ /oup/current/Code/FolderBrowser.pas	(revision 74)
@@ -0,0 +1,549 @@
+// -----------------------------------------------------------------------------
+//
+// TFolderBrowser-Klasse
+// Copyright (c) 2003-2005 Delphi-Forum
+// Tino, Popov, Christian Stelzman (PL), Luckie, Aton, Mathias Simmack (msi)
+//
+// basiert auf den folgenden Beiträgen
+//   - http://www.delphi-forum.de/viewtopic.php?t=11240
+//   - http://www.delphi-forum.de/viewtopic.php?t=21471
+//   * http://www.delphi-forum.de/viewtopic.php?t=25302
+//   - http://www.delphi-forum.de/viewtopic.php?t=27010&start=0
+//
+// -----------------------------------------------------------------------------
+
+// -- Revision history ---------------------------------------------------------
+//
+//   * ursprüngliche Version von PL (s. Link #3)
+//   * Fehlerkorrekturen von Luckie
+//       - Result bei Callback ergänzt
+//       - Properties als private deklariert
+//       - Bugs in "Execute"-Methode behoben
+//   * Dateifilter in Callback-Funktion
+//       - Idee (Aton)
+//       - globale Stringvariable (msi)
+//       - TFolderBrowser-Klasse (PL)
+//   * Unterstützung für mehrere Filter ergänzt (msi)
+//   * Unterstützung für verschiedene Root-Ordner (msi)
+//   * Änderungen bei den Properties (msi)
+//       - "SelFolder" in "SelectedItem" umbenannt
+//       - "FNewFolder" als "NewFolderButton" verfügbar
+//       - "FShowFiles" als "ShowFiles" verfügbar
+//       - "FNoTT" als "NoTargetTranslation" verfügbar (XP-Flag)
+//   * Funktion zum Ermitteln von Verknüpfungszielen ergänzt (msi)
+//       - Ergänzung, um Umgebungsvariablen umzuwandeln
+//   * "InitFolder" (s. Create) umbenannt in "PreSelectedFolder" (PL)
+//   * "FNoTT" (NoTargetTranslation) standardmäßig auf TRUE gesetzt,
+//     damit alle Windows-Versionen, inkl. XP, gleich reagieren (msi)
+//   * "CoInitializeEx" (Execute & TranslateLink) geändert (msi)
+//   * "TranslateMsiLink" (PL, msi)
+//        - ermittelt Pfad/Programm aus MSI-Verknüpfungen (Office, Openoffice)
+//        - benötigt installierten MSI
+//
+// -----------------------------------------------------------------------------
+unit FolderBrowser;
+
+
+interface
+
+uses
+  ShlObj, ActiveX, Windows, Messages;
+
+type
+  TFolderBrowser = class
+  private
+    // alles private gemacht; geht niemanden was an,
+    // da nachträglicher Zugriff sinnlos (Luckie)
+    FHandle      : THandle;
+    FCaption     : string;
+    FShowFiles   : boolean;
+    FNewFolder   : boolean;
+    FStatusText  : boolean;
+    FNoTT        : boolean;
+    FInitFolder  : string;
+    FSelected    : string;
+    FTop,
+    FLeft        : integer;
+    FPosChanged  : boolean;
+
+    // mehrere Filter müssen durch #0 voneinander getrennt
+    // werden, bspw. '*.txt'#0'*.*htm*'#0'*.xml'
+    // der letzte Filter kann mit #0#0 enden, muss er aber
+    // nicht, weil die Funktion "CheckFilter" diese beiden
+    // Zeichen automatisch anhängt (Mathias)
+    FFilter      : string;
+    FRoot        : PItemIdList;
+    procedure FreeItemIDList(var pidl: pItemIDList);
+    procedure SetTopPosition(const Value: Integer);
+    procedure SetLeftPosition(const Value: Integer);
+  public
+    constructor Create(Handle: THandle; const Caption: string;
+      const PreSelectedFolder: string = ''; ShowFiles: Boolean = False;
+      NewFolder: Boolean = False);
+    destructor Destroy; override;
+    function SetDefaultRoot: boolean;
+    function SetRoot(const SpecialFolderId: integer): boolean; overload;
+    function SetRoot(const Path: string): boolean; overload;
+    function Execute: Boolean; overload;
+    function TranslateLink(const LnkFile: string): string;
+    function TranslateMsiLink(const LnkFile: string): string;
+    property SelectedItem: string read FSelected;
+    property Filter: string read FFilter write FFilter;
+    property NewFolderButton: boolean read FNewFolder write FNewFolder;
+    property ShowFiles: boolean read FShowFiles write FShowFiles;
+    property StatusText: boolean read FStatusText write FStatusText;
+    property NoTargetTranslation: boolean read FNoTT write FNoTT;
+    property Top: integer read FTop write SetTopPosition;
+    property Left: integer read FLeft write SetLeftPosition;
+  end;
+
+implementation
+
+
+//
+// erweiterte SHBrowseForFolder-Eigenschaften
+// (Deklaration ist notwendig, weil u.U. nicht in jeder Delphi-Version
+// bekannt und verfügbar)
+//
+const
+  BIF_NEWDIALOGSTYLE     = $0040;
+  BIF_USENEWUI           = BIF_NEWDIALOGSTYLE or BIF_EDITBOX;
+  BIF_BROWSEINCLUDEURLS  = $0080;
+  BIF_UAHINT             = $0100;
+  BIF_NONEWFOLDERBUTTON  = $0200;
+  BIF_NOTRANSLATETARGETS = $0400;
+  BIF_SHAREABLE          = $8000;
+
+  BFFM_IUNKNOWN          = 5;
+  BFFM_SETOKTEXT         = WM_USER + 105; // Unicode only
+  BFFM_SETEXPANDED       = WM_USER + 106; // Unicode only
+
+
+// -- helper functions ---------------------------------------------------------
+
+function fileexists(const FileName: string): boolean;
+var
+  Handle   : THandle;
+  FindData : TWin32FindData;
+begin
+  Handle   := FindFirstFile(pchar(FileName),FindData);
+  Result   := (Handle <> INVALID_HANDLE_VALUE);
+
+  if(Result) then FindClose(Handle);
+end;
+
+function CheckFilter(const Path, Filter: string): boolean;
+var
+  p      : pchar;
+begin
+  // Standardergebnis
+  Result := false;
+  if(Path = '') or (Filter = '') then exit;
+
+  // #0#0 an den Filter anhängen, damit später das Ende
+  // korrekt erkannt wird
+  p      := pchar(Filter + #0#0);
+  while(p[0] <> #0) do
+  begin
+    // Datei mit entsprechendem Filter wurde gefunden, ...
+    if(fileexists(Path + '\' + p)) then
+    begin
+    // ... Ergebnis auf TRUE setzen, und Schleife abbrechen
+      Result := true;
+      break;
+    end;
+
+    // ansonsten zum nächsten Filter
+    inc(p,lstrlen(p) + 1);
+  end;
+end;
+
+function SHGetIDListFromPath(const Path: string; out pidl: PItemIDList):
+  boolean;
+var
+  ppshf        : IShellFolder;
+  wpath        : array[0..MAX_PATH]of widechar;
+  pchEaten,
+  dwAttributes : Cardinal;
+begin
+  // Standardergebnis
+  Result       := false;
+
+  // IShellFolder-Handle holen
+  if(SHGetDesktopFolder(ppshf) = S_OK) then
+  try
+    if(StringToWideChar(Path,wpath,sizeof(wpath)) <> nil) then
+    begin
+      // Pfadname in "PItemIdList" umwandeln
+      ppshf.ParseDisplayName(0,nil,wpath,pchEaten,pidl,dwAttributes);
+      Result   := pidl <> nil;
+    end;
+  finally
+    ppshf      := nil;
+  end;
+end;
+
+//
+// "CreateComObject" (modifizierte Version; Mathias)
+//
+function CreateComObject(const ClassID: TGUID;
+  out OleResult : HRESULT): IUnknown;
+begin
+  OleResult := CoCreateInstance(ClassID,nil,CLSCTX_INPROC_SERVER or
+    CLSCTX_LOCAL_SERVER,IUnknown,Result);
+end;
+
+//
+// "ExpandEnvStr"
+//
+function ExpandEnvStr(const szInput: string): string;
+const
+  MAXSIZE = 32768;
+begin
+  SetLength(Result,MAXSIZE);
+  SetLength(Result,ExpandEnvironmentStrings(pchar(szInput),
+    @Result[1],length(Result)));
+end;
+
+
+
+// -----------------------------------------------------------------------------
+//
+// TFolderBrowser-Klasse
+//
+// -----------------------------------------------------------------------------
+
+function FolderCallback(wnd: HWND; uMsg: UINT; lp, lpData: LPARAM): LRESULT;
+  stdcall;
+var
+  path : array[0..MAX_PATH + 1]of char;
+  fb   : TFolderBrowser;
+begin
+  fb   := TFolderBrowser(lpData);
+
+  case uMsg of
+    // Dialog wurde initialisiert
+    BFFM_INITIALIZED:
+      begin
+        // Ordner auswählen, ...
+        if(fb.FInitFolder <> '') then
+          SendMessage(wnd,BFFM_SETSELECTION,WPARAM(true),
+          LPARAM(pchar(fb.FInitFolder)));
+
+        // ... & OK-Button deaktivieren, wenn Filter benutzt werden
+        SendMessage(wnd,BFFM_ENABLEOK,0,LPARAM(fb.FFilter = ''));
+        // oder anders gesagt: OK-Button aktivieren, wenn keine
+        // Filter benutzt werden. ;o)
+        // (Mathias)
+
+        // Dialog neu positionieren
+        if(fb.FPosChanged) then
+          SetWindowPos(wnd,0,fb.Left,fb.Top,0,0,SWP_NOSIZE or SWP_NOZORDER);
+      end;
+    BFFM_SELCHANGED:
+      if(PItemIdList(lp) <> nil) and (fb.FFilter <> '') then
+      begin
+        // den aktuellen Pfadnamen holen, ...
+        ZeroMemory(@path,sizeof(path));
+        if(SHGetPathFromIdList(PItemIdList(lp),path)) then
+        begin
+        // ... & anzeigen
+          SendMessage(wnd,BFFM_SETSTATUSTEXT,0,LPARAM(@path));
+
+        // gibt´s Dateien mit dem Filter?
+        // nur dann wird der OK-Button des Dialogs aktiviert
+          SendMessage(wnd,BFFM_ENABLEOK,0,LPARAM(CheckFilter(path,fb.FFilter)));
+        end;
+      end;
+  end;
+
+  Result := 0; // von Luckie hinzugefügt, hatte ich vergessen (oops)
+end;
+
+
+constructor TFolderBrowser.Create(Handle: THandle; const Caption: string;
+  const PreSelectedFolder: string = ''; ShowFiles: Boolean = False;
+  NewFolder: Boolean = False);
+begin
+  FHandle     := Handle;
+  FCaption    := Caption;
+  FInitFolder := PreSelectedFolder;
+  FShowFiles  := ShowFiles;
+  FNewFolder  := NewFolder;
+  FStatusText := true;
+  FNoTT       := true;
+  FFilter     := '';
+  FRoot       := nil;
+  FTop        := 0;
+  FLeft       := 0;
+  FPosChanged := false;
+end;
+
+destructor TFolderBrowser.Destroy;
+begin
+  // ggf. belegte "PItemIdList" freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIdList(FRoot);
+
+  inherited Destroy;
+end;
+
+procedure TFolderBrowser.SetTopPosition(const Value: integer);
+begin
+  FPosChanged := true;
+  FTop        := Value;
+end;
+
+procedure TFolderBrowser.SetLeftPosition(const Value: integer);
+begin
+  FPosChanged := true;
+  FLeft       := Value;
+end;
+
+function TFolderBrowser.SetDefaultRoot: boolean;
+begin
+  // altes Objekt freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIDList(FRoot);
+
+  // und alles zurücksetzen
+  FRoot  := nil;
+  Result := true;
+end;
+
+function TFolderBrowser.SetRoot(const SpecialFolderId: integer): boolean;
+begin
+  // altes Objekt freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIDList(FRoot);
+
+  // SpecialFolderId kann eine der CSIDL_*-Konstanten sein,
+  //   CSIDL_DESKTOP
+  //   CSIDL_STARTMENU
+  //   CSIDL_PERSONAL
+  //   ...
+  // s. PSDK
+
+  // neuen Root setzen
+  Result := SHGetSpecialFolderLocation(FHandle,SpecialFolderId,FRoot) = S_OK;
+end;
+
+function TFolderBrowser.SetRoot(const Path: string): boolean;
+begin
+  // altes Objekt freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIDList(FRoot);
+
+  // neuen Root setzen
+  Result := SHGetIDListFromPath(Path,FRoot);
+end;
+
+function TFolderBrowser.Execute: Boolean;
+var
+  hr           : HRESULT;
+  BrowseInfo   : TBrowseInfo;
+  pidlResult   : PItemIDList;
+  DisplayName,
+  Path         : array[0..MAX_PATH + 1]of char;
+begin
+  Result       := false;
+
+  hr           := CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
+  // Wenn die COM-Bibliothek noch nicht initialisiert ist,
+  // dann ist das Ergebnis S_OK; ist sie bereits initialisiert
+  // ist sie S_FALSE
+  if(hr = S_OK) or (hr = S_FALSE) then
+  try
+    // "BrowseInfo" mit Werten füllen
+    ZeroMemory(@BrowseInfo,sizeof(BrowseInfo));
+    BrowseInfo.hwndOwner      := FHandle;
+    BrowseInfo.pidlRoot       := FRoot;
+    BrowseInfo.pszDisplayName := @Displayname;
+    BrowseInfo.lpszTitle      := pchar(FCaption);
+    BrowseInfo.lpfn           := @FolderCallBack;
+
+    // TFolderBrowser-Klasse als Referenz für Callback-Funktion
+    // übergeben (PL)
+    BrowseInfo.lParam         := LPARAM(self);
+
+    // Flags
+    if(FStatusText) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_STATUSTEXT;
+
+
+    // BIF_USENEWUI sorgt dafür dass besagter Button immer angezeigt wird,
+    // egal, ob BIF_BROWSEINCLUDEFILES gesetzt wird oder nicht, daher
+    // rausgenommen (Luckie)
+    if(FShowFiles) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_BROWSEINCLUDEFILES;
+
+    // Button zum Erstellen neuer Ordner anzeigen? (Luckie, PL)
+    if(FNewFolder) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_NEWDIALOGSTYLE
+    else
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_NONEWFOLDERBUTTON;
+
+    // Windows XP sucht automatisch die Verknüpfungsziele von
+    // Shortcuts heraus; soll stattdessen aber der Name der
+    // Verknüpfung angezeigt werden, ist das Flag BIF_NOTRANSLATETARGETS
+    // erforderlich; Sinn macht es nur unter Windows XP
+    if(FNoTT) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_NOTRANSLATETARGETS;
+    // für die älteren Windows-Versionen gibt es mit der Funktion
+    // "TranslateLink" (s. weiter unten) eine Entsprechung, um die
+    // Ziele von Shortcuts zu ermitteln (Mathias)
+
+
+    // Dialog aufrufen
+    pidlResult := SHBrowseForFolder(BrowseInfo);
+    if(pidlResult <> nil) then
+    begin
+      if(FSelected = '') then
+        if(SHGetPathFromIdList(pidlResult,Path)) and
+          (Path[0] <> #0) then
+        begin
+          FSelected := Path;
+          Result    := true;
+        end;
+
+      self.FreeItemIdList(pidlResult);
+    end;
+  finally
+    CoUninitialize;
+  end;
+end;
+
+function TFolderBrowser.TranslateLink(const LnkFile: string): string;
+var
+  link       : IShellLink;
+  hr         : HRESULT;
+  afile      : IPersistFile;
+  pwcLnkFile : array[0..MAX_PATH]of widechar;
+  szData     : array[0..MAX_PATH]of char;
+  FindData   : TWin32FindData;
+begin
+  // Standardergebnis
+  Result     := '';
+  link       := nil;
+  afile      := nil;
+
+  hr         := CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
+  if(hr = S_OK) or (hr = S_FALSE) then
+  try
+    // IShellLink-Interface erzeugen, ...
+    link   := CreateComObject(CLSID_ShellLink,hr) as IShellLink;
+    if(hr = S_OK) and (link <> nil) then
+    begin
+    // ... & Verknüpfung laden
+      StringToWideChar(LnkFile,pwcLnkFile,sizeof(pwcLnkFile));
+      afile := link as IPersistFile;
+
+      if(afile <> nil) and
+        (afile.Load(pwcLnkFile,STGM_READ) = S_OK) then
+      begin
+        ZeroMemory(@szData,sizeof(szData));
+
+    // Pfad + Dateiname ermitteln, ...
+        if(link.GetPath(szData,sizeof(szData),FindData,
+          SLGP_RAWPATH) = S_OK) then
+        begin
+          SetString(Result,szData,lstrlen(szData));
+    // ... & evtl. Umgebungsvariablen filtern
+          Result := ExpandEnvStr(Result);
+        end;
+      end;
+    end;
+  finally
+    if(afile <> nil) then afile := nil;
+    if(link <> nil) then link := nil;
+
+    CoUninitialize;
+  end;
+end;
+
+procedure TFolderBrowser.FreeItemIDList(var pidl: pItemIDList);
+var
+  ppMalloc : iMalloc;
+begin
+  if(SHGetMalloc(ppMalloc) = S_OK) then
+  try
+    ppMalloc.Free(pidl);
+    pidl     := nil;
+  finally
+    ppMalloc := nil;
+  end;
+end;
+
+
+const
+  MsiDllName                = 'msi.dll';
+
+  INSTALLSTATE_ABSENT       =  2;    // uninstalled
+  INSTALLSTATE_LOCAL        =  3;    // installed on local drive
+  INSTALLSTATE_SOURCE       =  4;    // run from source, CD or net
+  INSTALLSTATE_SOURCEABSENT = -4;    // run from source, source is unavailable
+  INSTALLSTATE_NOTUSED      = -7;    // component disabled
+  INSTALLSTATE_INVALIDARG   = -2;    // invalid function argument
+  INSTALLSTATE_UNKNOWN      = -1;    // unrecognized product or feature
+
+type
+  INSTALLSTATE              = LongInt;
+
+  TMsiGetShortcutTarget     = function(szShortcutTarget, szProductCode,
+    szFeatureId, szComponentCode: PAnsiChar): uint; stdcall;
+  TMsiGetComponentPath      = function(szProduct, szComponent: PAnsiChar;
+    lpPathBuf: PAnsiChar; pcchBuf: pdword): INSTALLSTATE; stdcall;
+var
+  MsiGetShortcutTarget      : TMsiGetShortcutTarget = nil;
+  MsiGetComponentPath       : TMsiGetComponentPath  = nil;
+  MsiDll                    : dword = 0;
+
+function TFolderBrowser.TranslateMsiLink(const LnkFile: string): string;
+var
+  ProductCode,
+  FeatureId,
+  ComponentCode : array[0..MAX_PATH]of char;
+  Path          : array[0..MAX_PATH]of char;
+  PathLen       : dword;
+begin
+  Result := '';
+  if(@MsiGetShortcutTarget = nil) or (@MsiGetComponentPath = nil) then exit;
+
+  ZeroMemory(@ProductCode, sizeof(ProductCode));
+  ZeroMemory(@FeatureId, sizeof(FeatureId));
+  ZeroMemory(@ComponentCode, sizeof(ComponentCode));
+
+  if(MsiGetShortcutTarget(PAnsiChar(LnkFile), ProductCode, FeatureId,
+    ComponentCode) = ERROR_SUCCESS) then
+  begin
+    ZeroMemory(@Path, sizeof(Path));
+    PathLen := sizeof(Path);
+
+    case MsiGetComponentPath(ProductCode, ComponentCode, Path, @PathLen) of
+      INSTALLSTATE_LOCAL,
+      INSTALLSTATE_SOURCE:
+        SetString(Result, Path, lstrlen(Path));
+    end;
+  end;
+end;
+
+
+initialization
+  MsiDll                     := GetModuleHandle(MsiDllName);
+  if(MsiDll = 0) then MsiDll := LoadLibrary(MsiDllName);
+
+  if(MsiDll <> 0) then
+  begin
+    MsiGetShortcutTarget     := GetProcAddress(MsiDll, 'MsiGetShortcutTargetA');
+    MsiGetComponentPath      := GetProcAddress(MsiDll, 'MsiGetComponentPathA');
+
+    if(@MsiGetShortcutTarget = nil) or
+      (@MsiGetComponentPath  = nil) then
+    begin
+      FreeLibrary(MsiDll);
+      MsiDll := 0;
+    end;
+  end;
+finalization
+  if(MsiDll <> 0) then FreeLibrary(MsiDll);
+end.
Index: /oup/current/Code/Functions.pas
===================================================================
--- /oup/current/Code/Functions.pas	(revision 73)
+++ /oup/current/Code/Functions.pas	(revision 74)
@@ -4,7 +4,4 @@
 
 uses Classes, Dialogs, SysUtils, StrUtils, Math, Data;
-
-type
-  TExportSet = set of (DO_dat, DO_raw, DO_convert, DO_toone);
 
 function BoolToStr(bool: Boolean): String;
@@ -16,7 +13,4 @@
 function DataToBin(Data: Tdata): String;
 function BinToInt(bin: String): Byte;
-
-function ExportFile(fileid: LongWord; filename: String; settings: TExportSet;
-  path: String): Integer;
 
 function StringSmaller(string1, string2: String): Boolean;
@@ -324,40 +318,4 @@
 
 
-
-function ExportFile(fileid: LongWord; filename: String; settings: TExportSet;
-  path: String): Integer;
-var
-  i: Byte;
-  extension: String;
-  rawlist: TRawList;
-begin
-  Result    := export_noerror;
-  extension := RightStr(filename, 4);
-  if DO_toone in settings then
-  begin
-    ExportDatFile(fileid, path + '\' + GetWinFileName(filename));
-  end
-  else
-  begin
-    if DO_dat in settings then
-      ExportDatFile(fileid, path + '\' + GetWinFileName(filename));
-    if DO_raw in settings then
-    begin
-      rawlist := OniDataConnection.GetRawList(fileid);
-      if Length(rawlist) > 0 then
-      begin
-        for i := 0 to High(rawlist) do
-        begin
-          ExportRawFile(fileid, rawlist[i].src_offset, path + '\' +
-            GetWinFileName(filename));
-        end;
-      end;
-    end;
-  end;
-end;
-
-
-
-
 function Explode(_string: String; delimiter: Char): TStringArray;
 var
Index: /oup/current/Data.pas
===================================================================
--- /oup/current/Data.pas	(revision 73)
+++ /oup/current/Data.pas	(revision 74)
@@ -71,5 +71,5 @@
     Ext:     String[4];
     needed:  Boolean;
-    Handler: function(fileid: LongWord; filename: String; convert: Boolean): Integer;
+    Handler: function(fileid: LongWord; filename: String): Integer;
   end;
 
Index: /oup/current/OniUnPacker.dpr
===================================================================
--- /oup/current/OniUnPacker.dpr	(revision 73)
+++ /oup/current/OniUnPacker.dpr	(revision 74)
@@ -19,5 +19,6 @@
   Extractor in 'Tools\Extractor.pas' {Form_ToolTemplate3},
   RawEdit in 'Tools\RawEdit.pas' {Form_ToolTemplate4},
-  TxmpReplace in 'Tools\TxmpReplace.pas' {Form_ToolTemplate5};
+  TxmpReplace in 'Tools\TxmpReplace.pas' {Form_ToolTemplate5},
+  FolderBrowser in 'Code\FolderBrowser.pas';
 
 {$R *.res}
Index: /oup/current/Tools/Extractor.dfm
===================================================================
--- /oup/current/Tools/Extractor.dfm	(revision 73)
+++ /oup/current/Tools/Extractor.dfm	(revision 74)
@@ -1,8 +1,12 @@
 inherited Form_Extractor: TForm_Extractor
   Caption = 'Extractor'
+  ClientHeight = 491
+  ExplicitWidth = 500
+  ExplicitHeight = 518
   PixelsPerInch = 96
   TextHeight = 13
   inherited Splitter1: TSplitter
     Left = 483
+    Height = 491
     Align = alRight
     Visible = False
@@ -12,200 +16,198 @@
   end
   inherited panel_files: TPanel
-    Width = 184
-    Align = alClient
-    ExplicitWidth = 184
+    Width = 333
+    Height = 491
+    ExplicitWidth = 333
+    ExplicitHeight = 491
     inherited filelist: TListBox
-      Width = 184
-      ExplicitWidth = 184
+      Width = 333
+      Height = 362
+      ExplicitWidth = 333
+      ExplicitHeight = 362
     end
     inherited panel_extension: TPanel
-      Width = 184
-      ExplicitWidth = 184
+      Width = 333
+      ExplicitWidth = 333
       inherited combo_extension: TComboBox
-        Width = 176
-        ExplicitWidth = 176
+        Width = 325
+        ExplicitWidth = 325
+      end
+      inherited check_zerobyte: TCheckBox
+        Visible = False
       end
       inherited edit_filtername: TEdit
-        Width = 176
-        ExplicitWidth = 176
+        Width = 325
+        ExplicitWidth = 325
       end
     end
   end
   inherited content: TPanel
-    Left = 184
-    Width = 299
-    Align = alRight
-    ExplicitLeft = 184
-    ExplicitWidth = 299
+    Left = 333
+    Width = 150
+    Height = 491
+    ExplicitLeft = 333
+    ExplicitWidth = 150
+    ExplicitHeight = 491
     object group_extract: TGroupBox
-      Left = 3
-      Top = 0
-      Width = 296
-      Height = 423
-      Align = alRight
+      AlignWithMargins = True
+      Left = 6
+      Top = 3
+      Width = 138
+      Height = 374
+      Margins.Left = 6
+      Margins.Right = 6
+      Align = alClient
       Caption = '2. Select extract-method'
       TabOrder = 0
-      object group_singlefiles: TGroupBox
-        AlignWithMargins = True
+      DesignSize = (
+        138
+        374)
+      object label_export_sel: TLabel
+        Left = 7
+        Top = 18
+        Width = 62
+        Height = 20
+        AutoSize = False
+        Caption = 'Export ...'
+      end
+      object label_path: TLabel
+        Left = 7
+        Top = 136
+        Width = 30
+        Height = 18
+        AutoSize = False
+        Caption = 'Path:'
+      end
+      object check_dat: TCheckBox
+        Left = 7
+        Top = 75
+        Width = 121
+        Height = 18
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Export .dat-entries'
+        Checked = True
+        State = cbChecked
+        TabOrder = 0
+      end
+      object check_raw: TCheckBox
+        Left = 7
+        Top = 94
+        Width = 121
+        Height = 18
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Export .raw-entries'
+        TabOrder = 1
+      end
+      object check_convert: TCheckBox
+        Left = 7
+        Top = 112
+        Width = 121
+        Height = 18
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Convert files'
+        TabOrder = 2
+      end
+      object radio_selected: TRadioButton
+        Left = 7
+        Top = 36
+        Width = 113
+        Height = 17
+        Caption = 'selected files'
+        Checked = True
+        TabOrder = 3
+        TabStop = True
+      end
+      object radio_all: TRadioButton
+        Left = 7
+        Top = 52
+        Width = 113
+        Height = 17
+        Caption = 'all files in list'
+        TabOrder = 4
+      end
+      object edit_path: TEdit
+        Left = 36
+        Top = 133
+        Width = 28
+        Height = 21
+        Anchors = [akLeft, akTop, akRight]
+        ReadOnly = True
+        TabOrder = 5
+        Text = 'C:\'
+        OnClick = btn_pathClick
+      end
+      object btn_path: TButton
+        Left = 70
+        Top = 133
+        Width = 62
+        Height = 21
+        Anchors = [akTop, akRight]
+        Caption = 'Select...'
+        TabOrder = 6
+        OnClick = btn_pathClick
+      end
+      object btn_export: TButton
+        Left = 7
+        Top = 180
+        Width = 75
+        Height = 25
+        Caption = 'Export!'
+        TabOrder = 7
+        OnClick = btn_exportClick
+      end
+    end
+    object group_progress: TGroupBox
+      AlignWithMargins = True
+      Left = 6
+      Top = 381
+      Width = 138
+      Height = 104
+      Margins.Left = 6
+      Margins.Top = 1
+      Margins.Right = 6
+      Margins.Bottom = 6
+      Align = alBottom
+      Caption = 'Progress ...'
+      TabOrder = 1
+      Visible = False
+      DesignSize = (
+        138
+        104)
+      object lbl_progress: TLabel
+        Left = 8
+        Top = 40
+        Width = 265
+        Height = 17
+        AutoSize = False
+        Caption = 'Files done: 0/0'
+      end
+      object lbl_estimated: TLabel
+        Left = 8
+        Top = 56
+        Width = 265
+        Height = 17
+        AutoSize = False
+        Caption = 'Estimated finishing time: 00:00:00'
+      end
+      object progress: TProgressBar
         Left = 8
         Top = 16
-        Width = 280
-        Height = 185
-        Margins.Left = 6
-        Margins.Top = 1
-        Margins.Right = 6
-        Align = alTop
-        Caption = 'Write data into single files'
+        Width = 122
+        Height = 17
+        Anchors = [akLeft, akTop, akRight]
+        Smooth = True
         TabOrder = 0
-        object btn_sel_dat: TButton
-          Left = 8
-          Top = 16
-          Width = 129
-          Height = 49
-          Caption = 'Selected files (dat contents only)'
-          TabOrder = 0
-          WordWrap = True
-          OnClick = Extract
-        end
-        object btn_sel_datraw: TButton
-          Left = 8
-          Top = 72
-          Width = 129
-          Height = 49
-          Caption = 'Selected files (dat+raw)'
-          TabOrder = 1
-          WordWrap = True
-          OnClick = Extract
-        end
-        object btn_sel_datraw_convert: TButton
-          Left = 8
-          Top = 128
-          Width = 129
-          Height = 49
-          Caption = 'Selected files (dat+raw) (with convert if possible)'
-          TabOrder = 2
-          WordWrap = True
-          OnClick = Extract
-        end
-        object btn_all_dat: TButton
-          Left = 144
-          Top = 16
-          Width = 129
-          Height = 49
-          Caption = 'All files in list (dat contents only)'
-          TabOrder = 3
-          WordWrap = True
-          OnClick = Extract
-        end
-        object btn_all_datraw: TButton
-          Left = 144
-          Top = 72
-          Width = 129
-          Height = 49
-          Caption = 'All files in list (dat+raw)'
-          TabOrder = 4
-          WordWrap = True
-          OnClick = Extract
-        end
-        object btn_all_datraw_convert: TButton
-          Left = 144
-          Top = 128
-          Width = 129
-          Height = 49
-          BiDiMode = bdLeftToRight
-          Caption = 'All files in list (dat+raw) (with convert if possible)'
-          ParentBiDiMode = False
-          TabOrder = 5
-          WordWrap = True
-          OnClick = Extract
-        end
-      end
-      object group_onefile: TGroupBox
-        AlignWithMargins = True
-        Left = 8
-        Top = 205
-        Width = 280
-        Height = 73
-        Margins.Left = 6
-        Margins.Top = 1
-        Margins.Right = 6
-        Align = alTop
-        Caption = 'Write data into one file'
+      end
+      object btn_abort: TButton
+        Left = 8
+        Top = 72
+        Width = 97
+        Height = 23
+        Caption = 'Abort'
+        Enabled = False
         TabOrder = 1
-        object btn_sel_files_toone: TButton
-          Left = 8
-          Top = 16
-          Width = 129
-          Height = 49
-          Caption = 'Selected files (dat contents only)'
-          TabOrder = 0
-          WordWrap = True
-          OnClick = Extract
-        end
-        object btn_all_files_toone: TButton
-          Left = 144
-          Top = 16
-          Width = 129
-          Height = 49
-          Caption = 'All files in list (dat contents only)'
-          TabOrder = 1
-          WordWrap = True
-          OnClick = Extract
-        end
-      end
-      object group_progress: TGroupBox
-        AlignWithMargins = True
-        Left = 8
-        Top = 282
-        Width = 280
-        Height = 132
-        Margins.Left = 6
-        Margins.Top = 1
-        Margins.Right = 6
-        Margins.Bottom = 7
-        Align = alClient
-        Caption = 'Progress ...'
-        TabOrder = 2
-        Visible = False
-        object lbl_progress: TLabel
-          Left = 8
-          Top = 40
-          Width = 265
-          Height = 17
-          AutoSize = False
-          Caption = 'Files done: 0/0'
-        end
-        object lbl_estimated: TLabel
-          Left = 8
-          Top = 56
-          Width = 265
-          Height = 17
-          AutoSize = False
-          Caption = 'Estimated finishing time: 00:00:00'
-        end
-        object progress: TProgressBar
-          Left = 8
-          Top = 16
-          Width = 265
-          Height = 17
-          Smooth = True
-          TabOrder = 0
-        end
-        object btn_abort: TButton
-          Left = 8
-          Top = 72
-          Width = 97
-          Height = 23
-          Caption = 'Abort'
-          Enabled = False
-          TabOrder = 1
-          OnClick = btn_abortClick
-        end
-      end
-    end
-  end
-  object saved: TSaveDialog [3]
-    Left = 448
-    Top = 328
+        OnClick = btn_abortClick
+      end
+    end
   end
 end
Index: /oup/current/Tools/Extractor.pas
===================================================================
--- /oup/current/Tools/Extractor.pas	(revision 73)
+++ /oup/current/Tools/Extractor.pas	(revision 74)
@@ -3,19 +3,19 @@
 uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
-  Dialogs, Template, StdCtrls, ExtCtrls, ComCtrls, Menus, Buttons;
+  Dialogs, Template, StdCtrls, ExtCtrls, ComCtrls, Menus, Buttons, StrUtils;
 
 type
   TForm_Extractor = class(TForm_ToolTemplate)
     group_extract: TGroupBox;
-    group_singlefiles: TGroupBox;
-    btn_sel_dat: TButton;
-    btn_sel_datraw: TButton;
-    btn_sel_datraw_convert: TButton;
-    btn_all_dat: TButton;
-    btn_all_datraw: TButton;
-    btn_all_datraw_convert: TButton;
-    btn_sel_files_toone: TButton;
-    btn_all_files_toone: TButton;
-    group_onefile: TGroupBox;
+    check_dat: TCheckBox;
+    check_raw: TCheckBox;
+    check_convert: TCheckBox;
+    radio_selected: TRadioButton;
+    label_export_sel: TLabel;
+    radio_all: TRadioButton;
+    label_path: TLabel;
+    edit_path: TEdit;
+    btn_path: TButton;
+    btn_export: TButton;
     group_progress: TGroupBox;
     lbl_progress: TLabel;
@@ -23,8 +23,8 @@
     progress: TProgressBar;
     btn_abort: TButton;
-    saved: TSaveDialog;
     procedure FormCreate(Sender: TObject);
-    procedure Extract(Sender: TObject);
     procedure btn_abortClick(Sender: TObject);
+    procedure btn_pathClick(Sender: TObject);
+    procedure btn_exportClick(Sender: TObject);
   private
   public
@@ -36,5 +36,6 @@
 implementation
 {$R *.dfm}
-uses Main, Functions, Data, OniDataClass;
+uses Main, Functions, Data, OniDataClass, FolderBrowser, Exporters;
+
 
 procedure TForm_Extractor.FormCreate(Sender: TObject);
@@ -42,15 +43,5 @@
   inherited;
   Self.AllowMultiSelect := True;
-
-  btn_sel_dat.Caption    := 'Selected files' + CrLf + '(dat contents only)';
-  btn_sel_datraw.Caption := 'Selected files' + CrLf + '(dat+raw contents)';
-  btn_sel_datraw_convert.Caption :=
-    'Selected files' + CrLf + '(dat+raw contents)' + CrLf + '(with convert if possible)';
-  btn_all_dat.Caption    := 'All files in list' + CrLf + '(dat contents only)';
-  btn_all_datraw.Caption := 'All files in list' + CrLf + '(dat+raw contents)';
-  btn_all_datraw_convert.Caption :=
-    'All files in list' + CrLf + '(dat+raw contents)' + CrLf + '(with convert if possible)';
-  btn_sel_files_toone.Caption := 'Selected files' + CrLf + '(dat contents only)';
-  btn_all_files_toone.Caption := 'All files in list' + CrLf + '(dat contents only)';
+  edit_path.Text := AppSettings.ExtractPath;
 end;
 
@@ -60,129 +51,82 @@
 end;
 
-procedure TForm_Extractor.Extract(Sender: TObject);
+procedure TForm_Extractor.btn_pathClick(Sender: TObject);
 var
-  sel_only:  Boolean;
-  dat_only:  Boolean;
-  convert:   Boolean;
-  one_file:  Boolean;
-  settings:  TExportSet;
+  fb: TFolderBrowser;
+begin
+  inherited;
+
+  fb := TFolderBrowser.Create(Handle, 'Please select a folder where you want ' +
+        'the files to be stored...', edit_path.Text, False, True);
+  if fb.Execute then
+  begin
+    edit_path.Text := fb.SelectedItem;
+    AppSettings.ExtractPath := edit_path.Text;
+  end;
+  fb.Free;
+end;
+
+procedure TForm_Extractor.btn_exportClick(Sender: TObject);
+var
+  begintime: Double;
   files:     LongWord;
   i, done:   LongWord;
-  begintime: Double;
+  selonly:   Boolean;
+  fileid:    LongWord;
+  filename:  String;
+  path:      String;
 begin
-  sel_only := Pos('sel', TButton(Sender).Name) > 0;
-  dat_only := not (Pos('datraw', TButton(Sender).Name) > 0);
-  convert  := Pos('convert', TButton(Sender).Name) > 0;
-  one_file := Pos('toone', TButton(Sender).Name) > 0;
-  if dat_only then
-    settings := [DO_dat]
-  else
-    settings := [DO_dat, DO_raw];
-  if convert then
-    settings := settings + [DO_convert];
-  if one_file then
-    settings := settings + [DO_toone];
+  inherited;
+  panel_files.Enabled := False;
+  group_extract.Enabled := False;
+  group_progress.Visible := True;
+
+  path := edit_path.Text;
+  if not EndsText('\', path) then
+    path := path + '\';
+
+  begintime := Time;
+  lbl_estimated.Caption := 'Estimated finishing time: unknown';
   progress.Position := 0;
 
-  if saved.Execute then
+  selonly := radio_selected.Checked;
+
+  if selonly then
+    files := filelist.SelCount
+  else
+    files := filelist.Count;
+
+  lbl_progress.Caption := 'Files done: 0/' + IntToStr(files);
+  progress.Max := files;
+  done  := 0;
+
+  for i := 0 to filelist.Count - 1 do
   begin
-    begintime := Time;
-    group_progress.Visible := True;
-    panel_files.Enabled := False;
-    group_singlefiles.Enabled := False;
-    group_onefile.Enabled := False;
-    lbl_estimated.Caption := 'Estimated finishing time: unknown';
-    if one_file then
+    if (selonly and filelist.Selected[i]) or not selonly then
     begin
-      if FileExists(saved.FileName) then
-      begin
-        if MessageBox(Self.Handle, PChar(
-          'File already exists. Do you want to overwrite it?'), PChar('Warning!'), MB_YESNO) =
-          ID_YES then
-        begin
-          DeleteFile(saved.FileName);
-        end
-        else
-        begin
-          group_progress.Visible    := False;
-          panel_files.Enabled      := True;
-          group_singlefiles.Enabled := True;
-          group_onefile.Enabled     := True;
-          Exit;
-        end;
-      end;
-      i := FileCreate(saved.FileName);
-      FileClose(i);
-      i := 0;
+      fileid := OniDataConnection.ExtractFileID(filelist.Items.Strings[i]);
+      filename := GetWinFilename(filelist.Items.Strings[i]);
+      if check_dat.Checked then
+        ExportDatFile(fileid, path + filename);
+      if check_raw.Checked then
+        ExportRawFiles(fileid, path + filename);
+      if check_convert.Checked then
+        ExportConverted(fileid, path + filename);
+      Inc(done);
     end;
-    if sel_only then
-    begin
-      files := filelist.SelCount;
-      lbl_progress.Caption := 'Files done: 0/' + IntToStr(files);
-      progress.Max := files;
-      done  := 0;
-      for i := 0 to filelist.Count - 1 do
-      begin
-        if filelist.Selected[i] then
-        begin
-          if one_file then
-          begin
-            ExportFile(OniDataConnection.ExtractFileID(
-              filelist.Items.Strings[filelist.ItemIndex]), ExtractFileName(saved.FileName),
-              settings, ExtractFileDir(saved.FileName));
-          end
-          else
-          begin
-            ExportFile(OniDataConnection.ExtractFileID(
-              filelist.Items.Strings[filelist.ItemIndex]), filelist.Items.Strings[i], settings, 'D:');
-          end;
-          Inc(done);
-        end;
-        if ((done mod 10) = 0) and (done >= 50) then
-          lbl_estimated.Caption := 'Estimated finishing time: ' + TimeToStr(
+    if ((done mod 10) = 0) and (done >= 50) then
+      lbl_estimated.Caption := 'Estimated finishing time: ' + TimeToStr(
             (Time - begintime) / done * files + begintime);
-        if (i mod 10) = 0 then
-        begin
-          progress.Position    := done;
-          lbl_progress.Caption := 'Files done: ' + IntToStr(done) + '/' + IntToStr(files);
-          Application.ProcessMessages;
-        end;
-      end;
-    end
-    else
-    begin
-      files := filelist.Count;
-      lbl_progress.Caption := 'Files done: 0/' + IntToStr(files);
-      progress.Max := files;
-      for i := 0 to filelist.Count - 1 do
-      begin
-        if one_file then
-        begin
-          ExportFile(OniDataConnection.ExtractFileID(
-            filelist.Items.Strings[filelist.ItemIndex]), ExtractFileName(saved.FileName),
-            settings, ExtractFileDir(saved.FileName));
-        end
-        else
-        begin
-          ExportFile(OniDataConnection.ExtractFileID(
-            filelist.Items.Strings[filelist.ItemIndex]), filelist.Items.Strings[i], settings, 'D:');
-        end;
-        if ((i mod 10) = 0) and (i >= 50) then
-          lbl_estimated.Caption := 'Estimated finishing time: ' + TimeToStr(
-            (Time - begintime) / i * files + begintime);
-        if (i mod 5) = 0 then
-        begin
-          progress.Position    := i;
-          lbl_progress.Caption := 'Files done: ' + IntToStr(i) + '/' + IntToStr(files);
-          Application.ProcessMessages;
-        end;
-      end;
-    end;
-    group_progress.Visible    := False;
-    panel_files.Enabled      := True;
-    group_singlefiles.Enabled := True;
-    group_onefile.Enabled     := True;
+
+    progress.Position    := done;
+    lbl_progress.Caption := 'Files done: ' + IntToStr(done) + '/' + IntToStr(files);
+    Application.ProcessMessages;
   end;
+
+  panel_files.Enabled := True;
+  group_extract.Enabled := True;
+  group_progress.Visible := False;
 end;
+
 
 begin
