//	****************************************************************************
//	*	$VER: Datenbank.c 1.08 25.02.2000													*
//	****************************************************************************
//	*	Datenbankfunktionen																		*
//	****************************************************************************
//	*	Programmiersprache:	C++																*
//	*	Compiler:				Maxon C++ (Version 3.00)									*
//	*	Portierung:				keine AMIGA-spezifischen Teile							*
//	*	Programmierer:			Manfred Tremmel												*
//	****************************************************************************
//    Copyright (C) 1997-2001 Manfred Tremmel
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA

#include <string.h>
#include <stdio.h>
#include <new.h>
#include "MTVersion.h"
#include "MTList.h"
#include "MTLocale.h"
#include "Datenbank.h"
#include "LocaleStrings.h"
#include "Einstellungen.h"

extern Prefs				*MyPrefsPTR;
extern OpenLocaleClass	*MyLocalePTR;

DataBase::DataBase( STRPTR Dateiname, STRPTR Datenbankbez, UWORD GetUser, LONG Laenge, LONG LaengeAlt )
{
	strcpy((char *)DataName, (const char *)Dateiname);
	strcat((char *)DataName, (const char *)Datenbankbez);
	strcat((char *)DataName, ".dat");
	sprintf( DRU_TAB_TEXT, "/%sTabelle [\n", Datenbankbez );
	AktElementNr	= 0;
	UnDoUsed			= 0;
	ReDoUsed			= 0;
	ElementLength	= Laenge;
	User				= GetUser;
	DruckWert		= NULL;
	DruckWertLaenge= 0;
	DruckWertAnzahl= 0;
	Such_DB_Anzahl	= 0;
	Such_DB_Feld	= NULL;
	Such_DB_Typ		= NULL;
	Such_DB_CS		= NULL;
	Such_DB_Felder_Laenge	= 0;
	Such_DB_Felder_String	= NULL;
	Such_DB_Nr		= 0;

	if( f.open( DataName, ios::in|ios::out ) == NULL )
	{
		if( f.open( DataName, ios::out ) == NULL )
		{
			sprintf( Fehler, AppStrings[MSG_ReQuest_DB_Open], DataName );
			throw (STRPTR)Fehler;
		}
		f.close();
		f.open( DataName, ios::in|ios::out );
	}

	if( !ReadHeader() )
	{
		f.close();
		f.open( DataName, ios::out );
		InitHeader( Datenbankbez );
		f.write( (const char *)&AktHeader, (int)sizeof(AktHeader) );
		f.close();
		f.open( DataName, ios::in|ios::out );
	}

	if( (AktHeader.Version[2] == '.') &&
		 (AktHeader.Satzlaenge > ElementLength) )
		ElementLength = AktHeader.Satzlaenge;

	ElementLengthPlus = ((ElementLength >> 2) + 1) << 2;
	UserData				= new TEXT[(ElementLengthPlus*22)];
	for(ULONG i = 0; i < 21; i++)
	{
		UnDoBuffer[i] = &UserData[((1+i) * ElementLengthPlus)];
	}
	Status			= (UWORD *)UserData;

	if( AktHeader.Version[1] == '.' )
		VersionsUpdate( Dateiname, Datenbankbez, (sizeof(AktHeader) - sizeof(LONG)), LaengeAlt );
	else if( AktHeader.Satzlaenge < ElementLength )
		VersionsUpdate( Dateiname, Datenbankbez, sizeof(AktHeader), AktHeader.Satzlaenge );
};

DataBase::~DataBase()
{
	FreeStatus();

	f.close();

	delete [(ElementLengthPlus*22)] UserData;

	if( Such_DB_Anzahl > 0 )
	{
		delete [Such_DB_Anzahl] Such_DB_CS;
		delete [Such_DB_Anzahl] Such_DB_Typ;
		delete [Such_DB_Anzahl] Such_DB_Feld;
	}

	if( Such_DB_Felder_Laenge > 0 )
		delete [Such_DB_Felder_Laenge] Such_DB_Felder_String;

	if( DruckWertAnzahl > 0 )
	{
		if( DruckWertLaenge > 0 )
			delete [DruckWertLaenge] (TEXT *)DruckWert->Wert;
		delete [DruckWertAnzahl] (DruWert *)DruckWert;
	}
};

void DataBase::VersionsUpdate( STRPTR Verzeichnis, STRPTR Datenbankbez, LONG HaederLaengeAlt, LONG SatzLaengeAlt )
{
	TEXT NameAlt[32];
	TEXT NameNeu[32];
	struct DBHeader	AltHeader;

	strcpy( NameNeu, Datenbankbez );
	strcat( NameNeu, ".dat" );
	strcpy( NameAlt, NameNeu );
	strcat( NameAlt, ".alt" );

	f.close();

	BPTR lock = Lock( Verzeichnis, SHARED_LOCK );
	CurrentDir( lock );

	if( Rename( NameNeu, NameAlt ) == DOSFALSE )
	{
		sprintf( Fehler, AppStrings[MSG_ReQuest_UpDate], DataName, NameAlt );
		if( DeleteFile( NameAlt ) == DOSTRUE )
		{
			if( Rename( NameNeu, NameAlt ) == DOSFALSE )
				throw (STRPTR)Fehler;
		}
		else
			throw (STRPTR)Fehler;
	}

	{
		fstream neu( NameNeu, ios::out );
		if( neu )
		{
			neu.buffer( (ElementLength * 5) );

			fstream alt( NameAlt, ios::in );
			if( alt )
			{
				alt.buffer( (ElementLength * 6) );
				alt.read( (char *)&AltHeader, HaederLaengeAlt );

				InitHeader( Datenbankbez );
				AktHeader.AnzahlSaetze	= AltHeader.AnzahlSaetze;
				neu.write( (const char *)&AktHeader, (int)sizeof(AktHeader) );

				Initialisiere(UserData);

				for( AktElementNr = 0; AktElementNr < AktHeader.AnzahlSaetze; AktElementNr++ )
				{
					alt.read( (char *)UserData, SatzLaengeAlt );
					UpdateSatz( AltHeader.Version );
					neu.write( UserData, ElementLength );
				}
				alt.close();
			}
		}
		else
		{
			sprintf( NameAlt, AppStrings[MSG_ReQuest_DB_Open], DataName );
			throw (STRPTR)NameAlt;
		}
	}

	DeleteFile( NameAlt );

	UnLock( lock );

	f.open( DataName, ios::in|ios::out );
	GetFirstElement();
};

void DataBase::InitHeader( STRPTR Datenbankbez )
{
	TEXT ZW_Version[] = _Version_;

	BOOL	JahrMerker = MyLocalePTR->Jahr_vier;
	MyLocalePTR->Jahr_vier = FALSE;

	AktHeader.Versionstring[0] = '$';
	AktHeader.Versionstring[1] = 'V';
	AktHeader.Versionstring[2] = 'E';
	AktHeader.Versionstring[3] = 'R';
	AktHeader.Versionstring[4] = ':';
	AktHeader.Versionstring[5] = ' ';

	int i = 0;
	int j = 0;
	STRPTR ZW_String = AktHeader.Bezeichnung;
	for(; i < 20; i++ )
	{
		if( *Datenbankbez )
			*ZW_String++ = *Datenbankbez++;
		else
			*ZW_String++ = ' ';
	}

	strncpy( (char *)AktHeader.Version, (const char *)ZW_Version, 5);
	AktHeader.KlammerAuf[0]		= ' ';
	AktHeader.KlammerAuf[1]    = '(';
	MyLocalePTR->FormatDateC( AktHeader.UpdDatum, "%d.%m.%y" );
	AktHeader.KlammerZu[0]		= ')';
	AktHeader.KlammerZu[1]		= ' ';
	AktHeader.KlammerZu[2]		= 0;
	AktHeader.AnzahlSaetze		= 0;
	AktHeader.Satzlaenge			= ElementLength;

	MyLocalePTR->Jahr_vier = JahrMerker;
};

BOOL DataBase::ReadHeader()
{
	BOOL Zugriff = FALSE;

	if( f.seekg( 0L, ios::beg) == NULL )
	{
		if( f.read( (char *)&AktHeader, (int)sizeof(AktHeader) ) )
			Zugriff = TRUE;
	}

	return Zugriff;
};

void DataBase::DruckWertInit( struct DruWert* ThisDruck )
{
	if( ThisDruck )
	{
		struct DruWert *ZWDruckWert;
		ULONG i;

		DruckWertLaenge = 0;
		DruckWertAnzahl = 1;

		for( ZWDruckWert = ThisDruck; *ZWDruckWert->VText || ZWDruckWert->Klein; ZWDruckWert++ )
		{
			DruckWertLaenge += ZWDruckWert->WertLaenge;
			DruckWertAnzahl++;
		}

		DruckWert = new DruWert[DruckWertAnzahl];

 		memcpy( (void *)DruckWert, (const void *)ThisDruck, (DruckWertAnzahl * sizeof(DruWert)) );

		if( DruckWertLaenge )
		{
			DruckWert->Wert = new TEXT[DruckWertLaenge];
	
			if( DruckWertAnzahl > 2 )
			{
				i = DruckWert->WertLaenge;

				for( ZWDruckWert = &DruckWert[1]; *ZWDruckWert->VText || ZWDruckWert->Klein; ZWDruckWert++ )
				{
					ZWDruckWert->Wert = &DruckWert->Wert[i];
					i += ZWDruckWert->WertLaenge;
				}
			}
		}
	}
};

void DataBase::UserWechsel( UWORD NeuerUser )
{
	FreeStatus();
	User = NeuerUser;
};

void DataBase::FreeStatus()
{
	if( AktElementNr > 0 &&
		 *Status == User )
	{
		*Status = 0;
		f.seekg( (long)(0 - ElementLength), ios::cur );
		if(f.write( (const char *)UserData, 2 ) == NULL)
			throw (ULONG)MSG_ReQuest_Schreibfehler;
		f.seekg( (long)(ElementLength - 2), ios::cur );
	}
};

UWORD DataBase::LesenDB()
{
	UnDoUsed			= 0;
	ReDoUsed			= 0;

	if( AktHeader.AnzahlSaetze == 0 )
		return 0xffff;
	else
	{
		f.read( UnDoBuffer[UnDoUsed], (int)ElementLength );
		memcpy( (void *)UserData, (const void *)UnDoBuffer[UnDoUsed], (size_t)ElementLength );

		if( *Status == User )
			return 0;
		else
			return *Status;
	}
};

void DataBase::Initialisiere( STRPTR PTRBeginn )
{
	for( STRPTR PTREnde = &PTRBeginn[ElementLength]; PTRBeginn < PTREnde; *PTRBeginn++ = 0);
};

UWORD DataBase::GetElementNr( ULONG Element_Nr )
{
	if( Element_Nr > 0 && Element_Nr <= AktHeader.AnzahlSaetze )
	{
		FreeStatus();

		if( Element_Nr == (AktElementNr + 1) );
		else if( Element_Nr == AktElementNr )
		{
			return *Status;
		}
		else if( Element_Nr == (AktElementNr - 1) )
		{
			f.seekg( (long)((-2) * ElementLength), ios::cur);
		}
		else if( Element_Nr == AktHeader.AnzahlSaetze )
		{
			f.seekg( (long)( 0 - ElementLength), ios::end);
		}
		else
		{
			size_t Seekpos = (((size_t)(Element_Nr - 1)	*
									 (size_t)ElementLength	)	+
									sizeof(AktHeader) );
			f.seekg( Seekpos, ios::beg);
		}
		AktElementNr	= Element_Nr;

		return LesenDB();
	}
	else
		return 0xffff;
};

UWORD DataBase::GetFirstElement( )
{
	FreeStatus();
	ReadHeader();
	AktElementNr = 1;
	return LesenDB();
};

UWORD DataBase::GetLastElement( )
{
	FreeStatus();
	ReadHeader();
	f.seekg( (long)(0 - ElementLength), ios::end);
	AktElementNr = AktHeader.AnzahlSaetze;
	return LesenDB();
};

UWORD DataBase::GetPrevElement( )
{
	if( AktElementNr > 1 )
	{		
		FreeStatus();
		f.seekg( (long)((-2) * ElementLength), ios::cur);
		AktElementNr--;
		return LesenDB();
	}
	else
		return GetFirstElement();
};

UWORD DataBase::Get10PrevElement( )
{
	if( AktElementNr > 10 )
	{		
		FreeStatus();
		f.seekg( (long)((-11) * ElementLength), ios::cur);
		AktElementNr -= 10;
		return LesenDB();
	}
	else
		return GetFirstElement();
};

UWORD DataBase::GetNextElement( )
{
	if( AktElementNr < AktHeader.AnzahlSaetze )
	{
		FreeStatus();
		AktElementNr++;
		return LesenDB();
	}
	else
		return GetLastElement();
};

UWORD DataBase::Get10NextElement( )
{
	if( (AktElementNr + 10) < AktHeader.AnzahlSaetze  )
	{		
		FreeStatus();
		f.seekg( (long)(9 * ElementLength), ios::cur);
		AktElementNr += 10;
		return LesenDB();
	}
	else
		return GetLastElement();
};

ULONG DataBase::ElementeVorhanden()
{
	return AktHeader.AnzahlSaetze;
};

void DataBase::UpDateElement( )
{
	if( AktElementNr )
	{
		if( *Status == 0 )
			*Status = User;
		ReDoUsed	= 0;
		if( UnDoUsed < 20)
			UnDoUsed++;
		else
		{
			UnDoUsed = 20;
			ULONG *UNDOziel	= (ULONG *)UnDoBuffer[0];
			ULONG *UNDOvon		= (ULONG *)UnDoBuffer[1];
			ULONG *UNDOende	= (ULONG *)UnDoBuffer[20];
			for( ; UNDOziel < UNDOende; *UNDOziel++ = *UNDOvon++ );
		}
		f.seekg( (long)(0 - ElementLength), ios::cur );
		f.read( UnDoBuffer[UnDoUsed], (int)ElementLength );
		STRPTR von	= UserData;
		STRPTR bis	= von + ElementLength;
		STRPTR Ziel	= UnDoBuffer[UnDoUsed];
		STRPTR vgl	= UnDoBuffer[(UnDoUsed-1)];
		while( von < bis )
		{
			if( *von != *vgl )
				*Ziel = *von;
			von++;
			Ziel++;
			vgl++;
		};
		memcpy( (void *)UserData, (const void *)UnDoBuffer[UnDoUsed], (size_t)ElementLength );
		WriteElement();
	}
};

void DataBase::WriteElement( )
{
	f.seekg( (long)(0 - ElementLength), ios::cur );
	if(f.write( (const char *)UserData, (int)ElementLength ) == NULL)
		throw (ULONG)MSG_ReQuest_Schreibfehler;
};

void DataBase::UnDo( )
{
	if( UnDoUsed > 0 )
	{
		if( ReDoUsed < 20)
			ReDoUsed++;
		else
			ReDoUsed = 20;
		UnDoUsed--;
		memcpy( (void *)UserData, (const void *)UnDoBuffer[UnDoUsed], (size_t)ElementLength );
		WriteElement();
	}
};

void DataBase::ReDo( )
{
	if( ReDoUsed > 0 )
	{
		UnDoUsed++;
		memcpy( (void *)UserData, (const void *)UnDoBuffer[UnDoUsed], (size_t)ElementLength );
		ReDoUsed--;
		WriteElement();
	}
};

void DataBase::LoeschenAkt( )
{
	if( *Status == 0xffff )
		*Status = 0;
	else
		*Status = 0xffff;
	WriteElement();
};

void DataBase::NeuerDatensatz( )
{
	if( AktElementNr &&
		 *Status == User )
	{
		*Status = 0;
		WriteElement();
	}

	Initialisiere(UserData);

	BOOL	JahrMerker = MyLocalePTR->Jahr_vier;
	MyLocalePTR->Jahr_vier = FALSE;

	UnDoUsed = 0;
	ReDoUsed = 0;
	AktHeader.AnzahlSaetze++;
	AktElementNr = AktHeader.AnzahlSaetze;
	strncpy( (char *)AktHeader.Version, _Version_, (size_t)5);
	MyLocalePTR->FormatDateC( AktHeader.UpdDatum, "%d.%m.%y" );
	AktHeader.KlammerZu[0]		= ')';
	f.seekg( (long)0, ios::beg );
	f.write( (const char *)&AktHeader, (int)sizeof(AktHeader) );
	memcpy( (void *)UnDoBuffer[UnDoUsed], (const void *)UserData, (size_t)ElementLength );
	f.seekg( (long)0, ios::end );
	if(f.write( (const char *)UnDoBuffer[UnDoUsed], (int)ElementLength ) == NULL)
		throw (ULONG)MSG_ReQuest_Schreibfehler;

	MyLocalePTR->Jahr_vier = JahrMerker;
};

void DataBase::SuchInit( DataBaseSearch* Vergleichsfunktion, ULONG SuchFeld, STRPTR SuchText, LONG SuchWert, UBYTE VGLFeld )
{
	Vergleichsfunktion->DatenbankfeldNr	= SuchFeld;
	Vergleichsfunktion->VergleichsKZ		= VGLFeld;
	if( SuchFeld >= Such_DB_Anzahl )
		SuchFeld = 0;
	Vergleichsfunktion->Datenbankfeld	= Such_DB_Feld[SuchFeld];
	Vergleichsfunktion->Vergleichstypus	= Such_DB_Typ[SuchFeld];
	
	if( Such_DB_CS[SuchFeld] )
	{
		Vergleichsfunktion->ZW_UBYTE		= SuchWert;
		Vergleichsfunktion->ZW_UWORD		= SuchWert;
		Vergleichsfunktion->ZW_ULONG		= SuchWert;
		Vergleichsfunktion->ZW_BYTE		= SuchWert;
		Vergleichsfunktion->ZW_WORD		= SuchWert;
		Vergleichsfunktion->ZW_LONG		= SuchWert;
		if( SuchWert == 0) 
			Vergleichsfunktion->ZW_BOOL	= FALSE;
		else
			Vergleichsfunktion->ZW_BOOL	= TRUE;
	}
	else
	{
		Vergleichsfunktion->Vergleichswert	= SuchText;
		Vergleichsfunktion->VGL_Vorbereiten();
	}
};

void DataBase::Suchen( ListenClass* SuchList,	ULONG SuchFeld1, STRPTR SuchText1, LONG SuchWert1, UBYTE VGLFeld1,
										UWORD Verknuepf1,	ULONG SuchFeld2, STRPTR SuchText2, LONG SuchWert2, UBYTE VGLFeld2,
										UWORD Verknuepf2,	ULONG SuchFeld3, STRPTR SuchText3, LONG SuchWert3, UBYTE VGLFeld3)
{
	UWORD Verknuepf[2] = { Verknuepf1, Verknuepf2 };

	if( (SuchFeld1 + SuchFeld2 + SuchFeld3) > 0 )
	{
		DataBaseSearch *Vergleichsfunktion = new DataBaseSearch[3];

		SuchInit( Vergleichsfunktion, SuchFeld1, SuchText1, SuchWert1, VGLFeld1 );
		SuchInit( &Vergleichsfunktion[1], SuchFeld2, SuchText2, SuchWert2, VGLFeld2 );
		SuchInit( &Vergleichsfunktion[2], SuchFeld3, SuchText3, SuchWert3, VGLFeld3 );

		ReadHeader();

		for( AktElementNr = 1; AktElementNr <= AktHeader.AnzahlSaetze; AktElementNr++ )
		{
			f.read( UserData, (int)ElementLength );
			if( Vergleich( Vergleichsfunktion, Verknuepf ) )
				SuchListeAnhaengen( SuchList );
		}

		AktElementNr--;
		memcpy( (void *)UnDoBuffer[UnDoUsed], (const void *)UserData, (size_t)ElementLength );

		delete [3] Vergleichsfunktion;
	}

};

BOOL DataBase::Vergleich( DataBaseSearch* Vergleichsfunktion, UWORD* Verknuepf )
{
	BOOL Gefunden = FALSE;
	if( *Status != 0xffff )
	{
		if( Vergleichsfunktion )
		{
			if( Vergleichsfunktion->DatenbankfeldNr )
				Gefunden = SuchVergleich( Vergleichsfunktion );
			if( Vergleichsfunktion[1].DatenbankfeldNr )
			{
				if( Verknuepf[0] )
				{
					if( !Gefunden )
						Gefunden  |= SuchVergleich( &Vergleichsfunktion[1]  );
				}
				else
				{
					if( Gefunden )
						Gefunden  &= SuchVergleich( &Vergleichsfunktion[1] );
				}
			}
			if( Vergleichsfunktion[2].DatenbankfeldNr )
			{
				if( Verknuepf[1] )
				{
					if( !Gefunden )
						Gefunden  |= SuchVergleich( &Vergleichsfunktion[2] );
				}
				else
				{
					if( Gefunden )
						Gefunden  &= SuchVergleich( &Vergleichsfunktion[2] );
				}
			}
		}
		else
			Gefunden = TRUE;
	}
	return Gefunden;
};

BOOL DataBase::SuchVergleich( DataBaseSearch* SuchKlasse )
{
	return FALSE;
};

void DataBase::SuchListeAnhaengen(ListenClass* SuchListe)
{
};

void DataBase::PrintVorbereiten( ofstream* os, UBYTE Art )
{
};

void DataBase::UpdateSatz( STRPTR )
{
};

ULONG DataBase::GetRexx( struct RexxMsg *rxmsg, ULONG Position )
{
	return 0;
};

ULONG DataBase::SetRexx( struct RexxMsg *rxmsg, ULONG Position )
{
	return 0;
};

STRPTR DataBase::PSAufbereit(STRPTR in, STRPTR out)
{
	while( *in )
	{
		if( *in == '(' ||
			 *in == ')' ||
			 *in == '\\' )
			*out++ = '\\';
		*out++ = *in++;
	}
	*out = 0;
	return out;
};

STRPTR DataBase::PSAufbereitMZ(STRPTR in, STRPTR out)
{
	if( in && *in)
	{
		*out++ = '(';
		while( *in )
		{
			switch( *in )
			{
				case '(':
				case ')':
				case '\\':
					*out++ = '\\';
					*out++ = *in++;
					break;
				case '\n':
					*out++ = ')';
					*out++ = *in++;
					*out++ = '(';
					break;
				default:
					*out++ = *in++;
					break;
			}
		}
		*out++ = ')';
	}
	*out = 0;
	return out;
};

STRPTR DataBase::PSDruckDatum( STRPTR DruckString, struct DateStamp* DruckDateTime )
{
	TEXT Zwischenstring[80];
	STRPTR ZWString = &DruckString[1];

	DruckString[0] = '(';

	MyLocalePTR->FormatDateC( Zwischenstring, DruckDateTime, MyLocalePTR->Thislocale->loc_DateFormat );
	ZWString = PSAufbereit(Zwischenstring, ZWString );

	*ZWString++ = ')';
	*ZWString++ = '(';

	MyLocalePTR->FormatDateC( Zwischenstring, DruckDateTime, MyLocalePTR->Thislocale->loc_ShortDateFormat );
	ZWString = PSAufbereit(Zwischenstring, ZWString );

	*ZWString++ = ')';
	*ZWString = 0;

	return ZWString;
};

STRPTR DataBase::PSDruckZeit( STRPTR DruckString, struct DateStamp* DruckDateTime )
{
	TEXT Zwischenstring[80];
	STRPTR ZWString = DruckString;

	*ZWString++ = '(';

	MyLocalePTR->FormatDateC( Zwischenstring, DruckDateTime, MyLocalePTR->Thislocale->loc_TimeFormat );
	ZWString = PSAufbereit(Zwischenstring, ZWString );

	*ZWString++ = ')';
	*ZWString++ = '(';

	MyLocalePTR->FormatDateC( Zwischenstring, DruckDateTime, MyLocalePTR->Thislocale->loc_ShortTimeFormat );
	ZWString = PSAufbereit(Zwischenstring, ZWString );

	*ZWString++ = ')';
	*ZWString = 0;

	return ZWString;
};

STRPTR DataBase::PSDruckBetrag( STRPTR DruckString, STRPTR* Waehrung, DOUBLE Betrag_W1, DOUBLE Betrag_W2 )
{
	TEXT Zwischenstring[80];
	STRPTR ZWString = DruckString;

	*ZWString++ = '(';

	MyLocalePTR->FormatMoney(	Zwischenstring, Betrag_W1, Waehrung[1] );
	ZWString = PSAufbereit(Zwischenstring, ZWString);

	*ZWString++ = ')';
	*ZWString++ = '(';

	MyLocalePTR->FormatMoney(	Zwischenstring, Betrag_W2, Waehrung[3] );
	ZWString = PSAufbereit(Zwischenstring, ZWString);

	*ZWString++ = ')';
	*ZWString = 0;

	return ZWString;
};

STRPTR DataBase::PSDruckBetrag( STRPTR DruckString, STRPTR* Waehrung,
										DOUBLE Betrag_NW1, DOUBLE Betrag_BW1, DOUBLE Betrag_NW2, DOUBLE Betrag_BW2 )
{
	DOUBLE Betrag[] = {	Betrag_NW1,
								Betrag_BW1,
								Betrag_NW2,
								Betrag_BW2 };

	TEXT Zwischenstring[80];
	STRPTR ZWString = DruckString;
	ULONG i;

	for( i = 0; i < 4; i++ )
	{
		*ZWString++ = '(';

		// Betrag
		MyLocalePTR->FormatMoney( Zwischenstring, Betrag[i], Waehrung[i] );
		ZWString = PSAufbereit(Zwischenstring, ZWString);

		*ZWString++ = ')';
	}

	*ZWString = 0;

	return ZWString;
};

void DataBase::PrintString( ofstream* os, STRPTR start )
{
	if( DruckWert )
	{
		if( start )
			strcpy( Startstring, start )
		else
		{
			Startstring[0] = '/';
			Startstring[1] = 0;
		}

		PrintVorbereiten( os, '1' );

		for( struct DruWert *ZWDruckWert = DruckWert; *ZWDruckWert->VText; ZWDruckWert++ )
		{
			(*os) << (STRPTR)Startstring << (STRPTR)ZWDruckWert->VText << " " << (STRPTR)ZWDruckWert->VSymbol;
			(*os)	<< (STRPTR)ZWDruckWert->Wert << (STRPTR)ZWDruckWert->NSymbol << " def\n";
		}
	}
};

void DataBase::PrintTabelle( ofstream* os, UBYTE Typ, ULONG von, ULONG bis, DataBaseSearch* Vergleichsfunktion, UWORD* Verknuepf, ULONG Anz )
{
	if( DruckWert )
	{
		BOOL Lesen = TRUE, Gefunden;
		struct DruWert *ZWDruckWert;

		if( bis == 0 )
		{
			Lesen = FALSE;
			bis = von;
		}

		for( ULONG j = von; j <= bis; j++ )
		{
			if( Lesen )
			{
				GetElementNr(j);
				Gefunden = Vergleich( Vergleichsfunktion, Verknuepf );
			}
			else
				Gefunden = TRUE;

			if( Gefunden )
			{
				for( ULONG az = 0; az < Anz; az++ )
				{
					// Datensatznummer
					if( MyPrefsPTR->Daten->Nr_Laenge )
					{
						sprintf( Fehler, "%0*lu", MyPrefsPTR->Daten->Nr_Laenge, j );
						(*os) << "[\n(" << (STRPTR)Fehler << ")\n";
					}
					else
						(*os) << "[\n(" << j << ")\n";

					PrintVorbereiten( os, Typ );

					for( ZWDruckWert = DruckWert; *ZWDruckWert->VText; ZWDruckWert++ )
					{
						if( Typ == '2' || ZWDruckWert->Klein )
						(*os) << (STRPTR)ZWDruckWert->VSymbol << (STRPTR)ZWDruckWert->Wert << (STRPTR)ZWDruckWert->NSymbol << "\n";
					}

					(*os) << "]\n";
				}
			}
		}
	}
};

void DataBaseSearch::VGL_Vorbereiten()
{
	switch( Vergleichstypus)
	{
		case 0:
		case 1:
			if( ParsePatternNoCase( Vergleichswert, Zwischenstring, 512l ) == 1 )
				Vergleichstypus = 1;
			else
			{
				strcpy( Zwischenstring, Vergleichswert );
				Vergleichstypus = 0;
			}
			break;
		case 2:
		case 3:
			if( ParsePatternNoCase( Vergleichswert, Zwischenstring, 512l ) == 1 )
				Vergleichstypus = 3;
			else
			{
				ZW_DATUM = MyLocalePTR->ParseDateC( Vergleichswert );
				Vergleichstypus = 2;
			}
			break;
		case 4:
			if( *Vergleichswert == '0' )
				ZW_BOOL = FALSE;
			else if( *Vergleichswert == '1' )
				ZW_BOOL = TRUE;
			else
			{
				if( stricmp( Vergleichswert, "true" ) == 0 )
					ZW_BOOL = TRUE;
				else
					ZW_BOOL = FALSE;
			}
			break;
		case 11:
			ZW_DOUBLE = MyLocalePTR->ParseNumber( (STRPTR)Vergleichswert );
			break;
		default:
			ZW_LONG = atol( Vergleichswert );
			switch( Vergleichstypus)
			{
				case 5:
					ZW_UBYTE = ZW_LONG;
					break;
				case 6:
					ZW_UWORD = ZW_LONG;
					break;
				case 7:
					ZW_ULONG = ZW_LONG;
					break;
				case 8:
					ZW_BYTE	= ZW_LONG;
					break;
				case 9:
					ZW_WORD	= ZW_LONG;
					break;
			}
			break;
	}
};

BOOL DataBaseSearch::Vergleich( void* DBFeldNeu )
{
	BOOL		Gefunden = FALSE;
	int		StrcmpResult;

	if( DBFeldNeu )
		Datenbankfeld = DBFeldNeu;

	if( Datenbankfeld )
	{
		switch( Vergleichstypus)
		{
			case 0:
				StrcmpResult = stricmp( Zwischenstring, (STRPTR)Datenbankfeld );
				if( StrcmpResult == 0 )			// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( StrcmpResult < 0 )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 1:
				if( MatchPatternNoCase( Zwischenstring, (STRPTR)Datenbankfeld ) )
					Gefunden = TRUE;
				break;
			case 2:
				if( ZW_DATUM.ds_Days		== ((DateStamp *)Datenbankfeld)->ds_Days )
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if(	ZW_DATUM.ds_Days	< 	((DateStamp *)Datenbankfeld)->ds_Days )
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 3:
				TEXT Buffer[80];
				MyLocalePTR->FormatDateC( Buffer, (DateStamp *)Datenbankfeld );
				if( MatchPatternNoCase( Zwischenstring, Buffer ) )
					Gefunden = TRUE;
				break;
			case 4:
				if( ZW_BOOL == (*(BOOL *)Datenbankfeld) )
					Gefunden = TRUE;
				break;
			case 5:
				if( ZW_UBYTE == (*(UBYTE *)Datenbankfeld) )	// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( ZW_UBYTE < (*(UBYTE *)Datenbankfeld) )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 6:
				if( ZW_UWORD == (*(UWORD *)Datenbankfeld) )	// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( ZW_UWORD < (*(UWORD *)Datenbankfeld) )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 7:
				if( ZW_ULONG == (*(ULONG *)Datenbankfeld) )	// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( ZW_ULONG < (*(ULONG *)Datenbankfeld) )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 8:
				if( ZW_BYTE == (*(BYTE *)Datenbankfeld) )	// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( ZW_BYTE < (*(BYTE *)Datenbankfeld) )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 9:
				if( ZW_WORD == (*(WORD *)Datenbankfeld) )	// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( ZW_WORD < (*(WORD *)Datenbankfeld) )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 10:
				if( ZW_LONG == (*(LONG *)Datenbankfeld) )	// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( ZW_LONG < (*(LONG *)Datenbankfeld) )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
			case 11:
				if( ZW_DOUBLE == (*(DOUBLE *)Datenbankfeld) )	// Identisch
				{
					if( VergleichsKZ < 2 ||		// bei =, <= und >=
						 VergleichsKZ == 4 )
						Gefunden = TRUE;
				}
				else if( ZW_DOUBLE < (*(DOUBLE *)Datenbankfeld) )	// Grösser
				{
					if( VergleichsKZ > 2 )		// bei >= und >
						Gefunden = TRUE;
				}
				else									// Kleiner
				{
					if( VergleichsKZ == 1 ||	// bei <= und <
						 VergleichsKZ == 2 )
						Gefunden = TRUE;
				}
				break;
		}
	}
	return Gefunden;
};

