/***************************************************************************
                          bibentrytable.cpp  -  description
                             -------------------
    begin                : Sun May 25 2003
    copyright            : (C) 2003 by Thach Nguyen
    email                : thach.nguyen@rmit.edu.au
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <iostream>
#include <algorithm>
#include <stdlib.h>
using namespace std;


#include "config.h"
#include "bibentrytable.h"

#include <ctime>

#include <qstylesheet.h>

//BibEntryDefTable* BibEntryDefTable::s_self = 0;

bool use_braces = true;


int caseless_find ( const char *haystack,char *needle, bool caseless );

void print_entry ( FILE *fp, BibEntry *e, char ld, char rd )
{
	int i;
	fprintf ( fp, "@%s{%s,\n", ( e->getEntryType() ).ascii(), ( e->getKey() ).ascii() );

	for ( i=0; i < e-> getNoFields(); i++ )
	{
		if ( !(e->getField(i)).isEmpty())
		{


			if ( e->stringMacroIndicator ( e->getFieldName ( i ) ) )
			{
				fprintf ( fp, "\t%s = %s", ( e->getFieldName ( i ) ).ascii(), ( e->getField ( i ) ).ascii() );
			}
			else
				fprintf ( fp, "\t%s = %c%s%c", ( e->getFieldName ( i ) ).ascii(), ld, ( e->getField ( i ) ).ascii(), rd );
			if ( i < e->getNoFields()-1 )
				fprintf ( fp, ",\n" );
		}
	}
	fprintf ( fp, "\n}\n\n" );
}



BibentryTable::BibentryTable()
{
	dbname = "none";
}

BibentryTable::~BibentryTable()
{
	clear();
}

void BibentryTable::clear()
{
	for ( int i=0; i < ( signed int ) entryTab.size(); i++ )
	{
		delete entryTab[i];
	}
	entryTab.erase ( entryTab.begin(), entryTab.end() );
	preamble=QString::fromLatin1 ( "" );
	stringMacros.clear();
	//selected_entry = -1;
	//  commands.clear();
}


BibEntry *BibentryTable::get_entry ( int i )
{
	if ( 0 <= i && i < ( signed int ) entryTab.size() )
	{
		return entryTab[i];
	}
	return 0;
}


QPair<QString, QString> BibentryTable::getStringMacro ( int index )
{
	if ( index < 0 || index >= ( int ) stringMacros.count() )
		return QPair<QString, QString> ( 0,0 );

	int i = 0;
	QMap<QString, QString>::Iterator it;
	for ( it = stringMacros.begin(); it != stringMacros.end(); ++it )
	{
		if ( i == index )
			return QPair<QString, QString> ( it.key(), it.data() );
	}
}


QString BibentryTable::getStringMacroValue ( QString key )
{
	if	( stringMacros.contains ( key ) )
		return stringMacros[key];
	else
		return 0;
}

int BibentryTable::readBibfile ( char *name, bool import )
{
	FILE *inf = fopen ( name, "r" );

	if ( !inf )
		return -1;

	if ( inf )
	{
		while ( !feof ( inf ) )
		{
			bool dumm;
			readEntry ( inf, import, dumm, dumm );
		}
		fclose ( inf );
	}


	string aux = name;
	dbname = "";
	for ( unsigned int i = aux.rfind ( '/' ) +1; i < aux.rfind ( '.' ) && i < strlen ( name ); i++ )
	{
		dbname += name[i];
	}
	return 0;
}


void BibentryTable::readEntry ( FILE *inf, bool import, bool &ref, bool &macro,  bool ignoreUndefinedType, bool ignoredUndefinedField, bool notInsertExisting )
{
	ref = false;
	macro = false;

	bool undefinedType = false;
	unsigned int i;
	char c, name[256], key[256], fieldname[256];
	BibEntry *entry = 0;
	Delimiter delim=BRACE;
	char ld='{',rd='}';
	bool stringMacro = false;
	bool existing = false;
	bool inserting = false;

	// Eat space
	do c = getc ( inf ); while ( lt_space ( c ) && !feof ( inf ) );

	// Eat everything before the @
	while ( c!='@' && !feof ( inf ) )
	{
		// skip comments
		if ( c=='%' ) while ( !feof ( inf ) && getc ( inf ) !='\n' );

		c = getc ( inf );
	}

	// This is not a BibTeX entry!
	if ( c != '@' ) return;

	// Eat everything before the name
	do c = getc ( inf ); while ( !ispseudoalpha ( c ) && !feof ( inf ) );

	// read the entry type name
	for ( i=0; ispseudoalpha ( c ) && !feof ( inf ) && i < 255; i++ )
	{
		name[i] = c;
		c = getc ( inf );
	}
	name[i] = 0;

	char lName[255];

	// Non-case sensitive
	for ( i=0; name[i] > ' '; i++ )
		lName[i] = tolower ( name[i] );
	lName[i] = '\0';
	// Check that the name exist, otherwise it's a special case
	if ( !BibEntryDefTable::self()->getBibEntryDef ( QString::fromLatin1 ( lName ) ) )
	{
		/*       if (isCommand(name)) {
			  entry = new BibEntry(name, 0);
		*/
		//	char *s = read_field(inf, c);
		//	cerr << "Field = " << s << "\n";
		if ( strcmp ( lName, "preamble" ) ==0 )
		{
			bool dump;
			char *s = read_field ( inf, c, dump );
			if ( s )
				preamble = QString ( s );
			return;
		}

		if ( strcmp ( lName, "comment" ) == 0 )
		{
			return;
		}

		if ( strcmp ( lName, "string" ) == 0 )
		{
			stringMacro = true;
		}

		else
		{

			cerr << "Entry type: " << name << " is not found\n";
			undefinedType = true;
			if ( !ignoreUndefinedType )
			{
				cerr << "Using other type\n";
			}

			else
				return;
		}


	}



	if ( strcmp ( lName, "string" ) == 0 )
	{
		stringMacro = true;
	}
//	delim=BRACE;
	delim=UNKNOWN;
	if ( import || stringMacro )
	{
		while (  c!='{' && c!='(' && !feof ( inf ) )
		{
			c=getc ( inf );
		}
		if ( c=='{' )
		{
			delim=BRACE;
			rd='}';
		}
		if ( c=='(' )
		{
			delim=PAREN;
			rd=')';
		}
		key[0] = 0;
	}
	else
	{
		// Eat everything before the key
		while ( ( c==' ' || c=='{' || c=='(' || c=='\n' || c=='\t' || c=='\r' ) && !feof ( inf ) )
		{
			
			if ( c=='{' ) delim=BRACE;
//			if ( c=='"' ) delim=QUOTE;
			if ( c=='(' ) delim=PAREN;
			c=getc ( inf );
		}

		switch ( delim )
		{
			case BRACE: ld='{'; rd='}'; break;
//			case QUOTE: ld='"'; rd='"'; break;
			case PAREN: ld='('; rd=')'; break;
			case UNKNOWN:
				return;	
		}


		for ( i=0; ( c!=',' && !feof ( inf ) && i < 255 ); i++ )
		{
			key[i] = c;
			c = getc ( inf );
		}
		key[i] = 0;
		if ( feof ( inf ) ) return;
		if ( c!=',' ) return;
	}

	//Eat right white space
	while ( lt_space ( key[i] ) && i > 0 ) i--;
	key[i+1] = 0;


	if ( !undefinedType&&!stringMacro )
	{
		entry = new BibEntry ( lName, key );
	}
	if ( undefinedType && !ignoreUndefinedType )
	{
		entry = new BibEntry ( QString::fromLatin1 ( "other" ), key );
		undefinedType = false;
	}
	// Read fields
	do
	{
		// Eat any non-alpha, all field names start with alpha
		do c = getc ( inf ); while ( !isalpha ( c ) && c!=rd && !feof ( inf ) );
		//while (!ispseudoalpha(c) && c!=rd && !feof(inf));
		for ( i=0; ispseudoalpha ( c ) && !feof ( inf ) && i < 255; i++ )
		{
			//fieldname[i] = tolower(c);
			fieldname[i] = c;
			c = getc ( inf );
		}
		fieldname[i] = 0;

		while ( lt_space ( c ) && !feof ( inf ) ) c = getc ( inf );
		if ( c=='=' )
		{
			c=getc ( inf );
			bool asStringMacro;
			char *s = read_field ( inf, c, asStringMacro );
			if ( s )
			{
				//Remove left and right white space
				i = 0;
				while ( lt_space ( s[i] ) && i < strlen ( s ) ) i++;
				s = &s[i];
				i = strlen ( s );
				while ( lt_space ( s[i] ) && i > 0 ) i--;
				s[i+1] = 0;
				//if (stringMacro)
				//	cerr << "\n" << fieldname << " " << s << "\n";
				if ( strlen ( s ) > 0 )
				{
					if ( stringMacro )
					{
						if ( !notInsertExisting )
						{
							inserting = true;
						}

						else
						{
							inserting = true;
							if ( stringMacros.contains ( fieldname ) )	//Macro with same key exist
								inserting = false;
						}

						if ( inserting )
						{
							stringMacros.insert ( fieldname, s );

							macro = true;
						}
					}
					else
					{
						if ( !undefinedType )
						{
							if ( strcmp ( fieldname, "kbibnote" ) ==0 )
							{
								entry->setField ( QString::fromLatin1 ( "comment" ), s );
								entry->setStringMacroIndicator ( QString::fromLatin1 ( "comment" ), asStringMacro );
							}
							else
							{
								entry->setField ( fieldname, s );
								entry->setStringMacroIndicator ( fieldname, asStringMacro );
							}
						}
					}
				}
			}
		}

	}
	while ( c != rd && !feof ( inf ) );

	if ( entry )
	{
		//check for existing entry
		if ( !notInsertExisting )
		{
			inserting = true;
		}
		else
		{
			inserting = true;
			for ( int i =0; i < size(); i++ )
			{
				BibEntry* thisEntry = get_entry ( i );
				existing = false;

				if ( compareBibEntry ( thisEntry, entry ) == 0 )
				{
					existing = true;
				}
				else
					existing = false;


				if ( existing )
				{
					inserting = false;
					break;
				}
			}

		}

		if ( inserting )
		{
			entry->setIndex ( entryTab.size() );
			new_entry ( entry );
			ref = true;
		}
	}



}


void BibentryTable::new_entry ( BibEntry &bib )
{
	entryTab.push_back ( new BibEntry ( bib ) );
}

void BibentryTable::new_entry ( BibEntry* bib )
{
	entryTab.push_back ( bib );
}

void BibentryTable::new_stringMacro ( QString key, QString value )
{
	stringMacros.insert ( key, value );
}



int BibentryTable::writeBibfile ( const char *name, int fieldDelimiter )
{
	int i = 0;
	BibEntry *bib;
	FILE *outf = fopen ( name, "w" );

	if ( !outf )
	{
		cerr << "Cannot open file for saving " << name<<"\n";
		return -1;
	}
	//  print_commands(outf, this);
	fprintf ( outf, "#Created by Kbib version %s\n", VERSION );
	time_t curr = time ( 0 );
	fprintf ( outf, "#Last modified: %s\n\n", ctime ( &curr ) );

	if ( !preamble.isEmpty() )
	{
		fprintf ( outf, "@preamble{%s}\n\n", preamble.ascii() );
	}

	char ld, rd;
	switch ( fieldDelimiter )
	{
		case 1:
			rd = ld='\"';
			break;
		case 2:
			ld = '(';
			rd = ')';
			break;
		default:
			ld = '{';
			rd = '}';
			break;
	}


	QMap<QString, QString>::Iterator it;
	for ( it = stringMacros.begin(); it != stringMacros.end(); ++it )
	{
		QString key, data;
		key = it.key();
		data = it.data();
		fprintf ( outf, "@string{%s=%c", key.ascii(),ld );
		fprintf ( outf, "%s%c}\n\n", data.ascii(), rd );
	}

	i = 0;
	while ( ( bib=get_entry ( i++ ) ) )
	{
		print_entry ( outf, bib, ld, rd );
	}
	fclose ( outf );
	return 0;
}
QPair<QString, QString> getStringMacro ( int i );

/** Only remove the table vector, don't delete the entry contents */
void BibentryTable::removeEntryTab()
{
	entryTab.erase ( entryTab.begin(), entryTab.end() );
}


void BibentryTable::createKeys ( const QString connectingString )
{
	QString fkey,tmp_fkey;
	char dletter='a';
	int oopscount=0;
	int idx;
	QString fn;
	QString fm;
	bool fix_key = false;
	for ( int i = 0; i< ( signed int ) entryTab.size(); i++ )
	{
		BibEntry *entry = entryTab[i];
		fn = entry->getField ( "lockkey" );
		if ( fn!=QString::fromLatin1 ( "Y" ) )
		{
			entry->createKey ( connectingString );
			dletter='a';
			fkey= entry->getKey();
			tmp_fkey = fkey;
			entry->setKey ( "" );

			while ( 1 )
			{
				idx = searchKey ( tmp_fkey );

				if ( idx < 0 )
					fix_key = false;

				else if ( idx < i )
					fix_key = true;

				else
				{

					while ( 1 )
					{

						fm = entryTab[idx]->getField ( "lockkey" );
						if ( fm == QString::fromLatin1 ( "Y" ) )
						{
							fix_key = true;
							break;
						}
						if ( fm != QString::fromLatin1 ( "Y" ) && idx == ( ( int ) ( entryTab.size() )-1 ) )
						{
							fix_key = false;
							break;
						}

						if ( fm != QString::fromLatin1 ( "Y" ) && idx < ( ( int ) ( entryTab.size() )-1 ) )
						{
							int tmp_idx = searchKey ( tmp_fkey, idx+1 );
							idx = tmp_idx;
						}
						if ( idx < 0 )
						{
							fix_key = false;
							break;
						}
					}
				}

				if ( !fix_key )
				{
					entry->setKey ( tmp_fkey );
					break;
				}
				else
				{
					tmp_fkey = fkey;
					for ( int j=0;j<oopscount;j++ )
						tmp_fkey+='x';
					tmp_fkey+=dletter;
					dletter++;
					if ( dletter=='z' )
					{
						oopscount++;
						dletter='a';
					}
				}
			}
		}
	}
}


int BibentryTable::searchKey ( const QString s, int start )
{
	int found = -1;
	//string skey = s;
	QString skey = s.lower();
	for ( int fn=start; fn < ( signed int ) entryTab.size(); fn++ )
	{
		BibEntry *entry = entryTab[fn];
		//string key = entry->getKey();
		QString key = entry->getKey().lower();
		if ( key == skey )
		{
			found = fn;
			break;
		}
	}
	return found;
}



//Do I need this function???????
void BibentryTable::createKey ( int i, const QString connectingString )
{
	QString fkey,tmp_fkey;
	char dletter='a';
	int oopscount=0;
	int idx;
	QString fn;
	QString fm;
	bool fix_key = false;

	if ( i < 0 || i >= ( signed int ) entryTab.size() )
	{
		return;
	}

	BibEntry *entry = entryTab[i];
	fn = entry->getField ( "lockkey" );
	if ( fn!=QString::fromLatin1 ( "Y" ) )
	{
		entry->createKey ( connectingString );
		dletter='a';
		fkey= entry->getKey();
		tmp_fkey = fkey;
		entry->setKey ( "" );

		while ( 1 )
		{
			idx = searchKey ( tmp_fkey );

			if ( idx < 0 )
				fix_key = false;

			else if ( idx < i )
				fix_key = true;

			else
			{

				while ( 1 )
				{


					fm = entryTab[idx]->getField ( "lockkey" );
					if ( fm==QString::fromLatin1 ( "Y" ) )
					{
						fix_key = true;
						break;
					}
					if ( fm==QString::fromLatin1 ( "N" ) && idx == ( ( int ) ( entryTab.size() )-1 ) )
					{
						fix_key = false;
						break;
					}

					if ( fm==QString::fromLatin1 ( "N" ) && idx < ( ( int ) ( entryTab.size() )-1 ) )
					{
						idx = searchKey ( tmp_fkey, idx+1 );

					}
					if ( idx < 0 )
					{
						fix_key = false;
						break;
					}
				}
			}

			if ( !fix_key )
			{
				entry->setKey ( tmp_fkey );
				break;
			}
			else
			{
				tmp_fkey = fkey;
				for ( int j=0;j<oopscount;j++ )
					tmp_fkey+='x';
				tmp_fkey+=dletter;
				dletter++;
				if ( dletter=='z' )
				{
					oopscount++;
					dletter='a';
				}
			}
		}
	}
}


/*
void BibentryTable::createKey(int i)
{
        string fkey;
        char dletter='a';
        int oopscount=0;
        int idx;
        if (i < 0 || i >= (signed int) entryTab.size() ) {
                return;
        }

        BibEntry *entry = entryTab[i];
        entry->createKey();
        dletter='a';
        fkey= entry->getKey();
        idx = searchKey(const_cast<char*>(fkey.c_str()));
        if (idx!=i) {
                while(1) {
                        fkey= entry->getKey();
                        for(int j=0;j<oopscount;j++)
                                fkey+='x';
                        fkey+=dletter;
                        idx = searchKey(const_cast<char*>(fkey.c_str()));
                        if (idx<0) {
                                entry->setKey(const_cast<char*>(fkey.c_str()));
                                break;
                        } else {
                                dletter++;
                                if (dletter=='z') {
                                        oopscount++;
                                        dletter='a';
                                }
                        }

                }
        }

}
*/

int caseless_find ( const char *haystack,char *needle, bool caseless )
{
	int i,j,flaws;
	int lh,ln;
	int skip_braces=1,dyn_alloc=0;
	char *aux,*p;
	char prebuf[256];
	if (haystack!=0)
		lh=strlen ( haystack );
	else
		lh = 0;
	if (needle!=0)
		ln=strlen ( needle );
	else
		ln = 0;
	if ( ( lh==0 ) && ( ln==0 ) )
		return 1;
	if ( lh==0 )
		return 0;

	if ( strchr ( needle,'{' ) )
		skip_braces=0;
	if ( strchr ( needle,'}' ) )
		skip_braces=0;

	if ( lh>255 )
	{
		aux= ( char * ) malloc ( lh+1 );
		dyn_alloc=1;
	}
	else
		aux=prebuf;

	if ( skip_braces )
	{
		memset ( aux,0,lh+1 );
		p=aux;
		for ( i=0;i<lh;i++ )
		{
			if ( ( haystack[i]=='{' ) || ( haystack[i]=='}' ) )
				continue;
			* ( p++ ) =haystack[i];
		}
		lh=strlen ( aux );
	}
	else
	{
		strcpy ( aux,haystack );
	}

	lh=strlen ( aux );

	if ( ln>lh )
	{
		if ( dyn_alloc )
			free ( aux );
		return 0;
	}

	for ( i=0;i< ( lh-ln+1 );i++ )
	{
		flaws=0;
		for ( j=0;j<ln;j++ )
		{
			char x, y;
			if ( caseless )
			{
				x = toupper ( aux[i+j] );
				y = toupper ( needle[j] );
			}
			else
			{
				x = aux[i+j];
				y = needle[j];
			}

			//if (toupper(aux[i+j])!=toupper(needle[j])) {
			if ( x!=y )
			{
				++flaws;
				break;
			}
		}
		if ( !flaws )
		{
			if ( dyn_alloc )
				free ( aux );
			return 1;
		}
	}
	if ( dyn_alloc )
		free ( aux );
	return 0;
}


int BibentryTable::search_string ( char *s, int first, int att, int opt )
{
	int fn, last, found = -1;
	bool caseless = 1;

	if ( ( opt&1 ) )
		caseless = 0;



	if ( first >= 0 )
	{
		last = entryTab.size();
	}
	else
	{
		last = -first;
		first = 0;
	}

	for ( fn=first; fn < last; fn++ )
	{
		BibEntry *entry = entryTab[fn];
		const char * field;

		/*

		if (att == 1){ //search in author
		  field = entry->getField("author");
		  if (caseless_find(const_cast<char*>(field.c_str()),s,caseless)) 
		   found = fn;
		}
		else if (att == 2) { //search in title
		  field = entry->getField("title");
		  if (caseless_find(const_cast<char*>(field.c_str()),s,caseless))
		   found = fn;
		}
		*/

		if ( att == 0 )
		{
			field = const_cast<char *> ( ( entry->getKey() ).ascii() );
			if ( field )
			{
				if ( caseless_find ( field,s,caseless ) )
					found = fn;
			}

		}
		else if ( att>0 )
		{
			const char *field_name = ( BibEntryDefTable::self()->getFieldName ( att-1 ) ).ascii();
			field = ( entry->getField ( field_name ) ).ascii();
			if ( field )
			{
				if ( caseless_find ( field,s,caseless ) )
					found = fn;
			}

		}
		else
		{ //search in all fields

			for ( int i=-1; i < entry->getNoFields(); i++ )
			{
				field = ( i>=0 ) ?
				        ( entry->getField ( i ) ).ascii() :
				        ( entry->getKey() ).ascii();
				if ( caseless_find ( field,s,caseless ) )
				{
					found = fn;
					break;
				}
			}
		}



		if ( found >= 0 )
			break;
	}

	return found;
}

void BibentryTable::delete_entry ( int i )
{
	if ( 0 <= i && i < ( ( signed int ) entryTab.size() ) )
	{
		vector<BibEntry *>::iterator it = entryTab.begin();
		for ( int k=0; k<i; k++ )
			it++;
		delete *it;
		entryTab.erase ( it );
	}
}

static string field_to_sort = "citation key";

static
bool lt_fields ( BibEntry *e1, BibEntry *e2 )
{
	const char *r1,*r2;
	string s1, s2;
	r1 = ( e1->getField ( field_to_sort ) ).ascii();
	r2 = ( e2->getField ( field_to_sort ) ).ascii();

	if ( ( !r1 ) && ( !r2 ) )
		return 0;
	if ( !r1 )
		return 1;
	if ( !r2 )
		return 0;

	s1=r1;
	s2=r2;

	return ( s1 < s2 );
}

static
bool gt_fields ( BibEntry *e1, BibEntry *e2 )
{
	const char *r1,*r2;
	string s1, s2;
	r1 = ( e1->getField ( field_to_sort ) ).ascii();
	r2 = ( e2->getField ( field_to_sort ) ).ascii();

	if ( ( !r1 ) && ( !r2 ) )
		return 0;
	if ( !r1 )
		return 1;
	if ( !r2 )
		return 0;

	s1=r1;
	s2=r2;

	return ( s1 > s2 );
}

void BibentryTable::sort ( int ascending, QString s )
{
	field_to_sort = s.ascii();
	::sort ( entryTab.begin(), entryTab.end(),
	         ascending ? lt_fields : gt_fields );
	updateEntryIndices();
}

int BibentryTable::removeDuplicated ( int compareSetting )
{
	int numRemoved=0;
	BibEntry *thisEntry, *otherEntry;
//    int numField;
	//  bool duplicated = false;
	int listSize = entryTab.size();
	for ( int i =0; i < listSize-1; i++ )
	{
		thisEntry = entryTab[i];

		for ( int j = i+1; j < listSize; j++ )
		{
			otherEntry = entryTab[j];

			if ( compareBibEntry ( thisEntry, otherEntry, compareSetting ) == 0 )
			{
				delete_entry ( j );
				numRemoved++;
				listSize--;
				j--;
			}


		}

	}
	if ( numRemoved )
	{
		updateEntryIndices();
	}
	return  numRemoved;


}

void BibentryTable::updateEntryIndices ( void )
{
	int listSize = entryTab.size();
	for ( int i =0; i <= listSize-1; i++ )
	{
		entryTab[i]->setIndex ( i );
	}

}

void BibentryTable::change_entry ( int index, BibEntry *entry )
{
	if ( index < 0 || index >= ( int ) ( entryTab.size() ) )
		return;

	delete entryTab[index];
	entryTab[index] = entry;
	entryTab[index]->setIndex ( index );
}

QString BibentryTable::getFieldText ( BibEntry *bibItem, QString fieldName )
{
	QString field = bibItem->getField ( fieldName );
	if ( field.isEmpty() )
		return field;

	RefField *fieldDef = BibEntryDefTable::self()->getRefField ( fieldName );
	bool macro = bibItem->stringMacroIndicator ( fieldName );
	if ( fieldDef )
	{
		if ( fieldDef->type == NUMBER )
		{
			macro = false;
		}
	}

	if ( macro )
	{
		if ( stringMacros.contains ( field ) )
		{
			field = stringMacros[field];
			macro = false;
		}
		else
			field = QString ( "#" ) + field + QString ( "#" );

	}


	return field;
}


QString BibentryTable::detailedEntry ( BibEntry *bibItem )
{
	QString st;
	st = QString ( "<font color=\"#004faf\"><B>Reference Type:</B></font><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" );
	st.append ( bibItem->getEntryType() );
	//st.append("<BR></pre>");
	st.append ( "<BR>" );

	QString fieldName;
	QString field;

	for ( int i=0; i < bibItem->getNoFields(); i++ )
	{

		fieldName = bibItem->getFieldName ( i ).lower() ;


		RefField *fieldDef = BibEntryDefTable::self()->getRefField ( fieldName );
		bool url = false;
		bool paragraph = false;
		if ( fieldDef )
		{
			if ( fieldDef->type == URL )
				url = true;
			if (fieldDef->type == PARAGRAPH)
				paragraph = true;
		}

		field = getFieldText ( bibItem, fieldName );

		QChar c = fieldName.at ( 0 );
		fieldName = fieldName.replace ( 0, 1, c.upper() );

		if ( !url )
		{
			//st.append("<pre>");
			st.append ( "<font color=\"#004faf\">" );
			st.append ( "<B>" );
			st.append ( fieldName );
			st.append ( "</B>:" );
			st.append ( "</font><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" );
			if (!paragraph)
				st.append ( QStyleSheet::escape ( field.simplifyWhiteSpace() ) );
			else
				st.append ( QStyleSheet::convertFromPlainText ( field,  QStyleSheetItem::WhiteSpaceNormal ) );
			st.append ( "<BR>" );
			//st.append("</pre>");
		}
		else
		{
			st.append ( "<font color=\"#004faf\">" );
			st.append ( "<B>" );
			st.append ( fieldName );
			st.append ( "</B>:" );
			st.append ( "</font><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" );
			st.append ( "<a href=\"" );
			st.append ( field );
			st.append ( "\">" );
			st.append ( field );
			st.append ( "</a><BR>" );
		}
	}

	return st;


}


QString BibentryTable::formatEntry ( BibEntry *bibItem, bool richText )
{
	QString st;
	QString tmp;
	if ( strcmp ( bibItem->getEntryType(), "article" ) ==0 )
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "author" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "\"" );
			st.append ( tmp );
			st.append ( "\"" );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "journal" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			if ( richText )
				st.append ( "<I>" );
			st.append ( tmp );
			if ( richText ) st.append ( "</I>" );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "volume" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "vol. " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "number" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "no. " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "pages" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "pp. " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "year" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}
		if ( !st.isEmpty() )
			st.append ( "." );

	}

	else if ( strcmp ( bibItem->getEntryType(), "inproceedings" ) ==0 ||strcmp ( bibItem->getEntryType(), "incollection" ) ==0 )
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "author" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "\"" );
			st.append ( tmp );
			st.append ( "\"" );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "booktitle" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "in " );
			if ( richText ) st.append ( "<I>" );
			st.append ( tmp );
			if ( richText ) st.append ( "</I>" );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "volume" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "vol. " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "number" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "no. " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "year" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "pages" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "pp. " );
			st.append ( tmp );
		}

		if ( !st.isEmpty() )
			st.append ( "." );
	}

	else if ( strcmp ( bibItem->getEntryType(), "book" ) ==0 )
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "author" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			if ( richText ) st.append ( "<I>" );
			st.append ( tmp );
			if ( richText ) st.append ( "</I>" );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "edition" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "publisher" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "year" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "chapter" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "ch. " );
			st.append ( tmp );
		}
		if ( !st.isEmpty() )
			st.append ( "." );
	}

	else if ( strcmp ( bibItem->getEntryType(), "proceedings" ) ==0 )
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "editor" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
			st.append ( ", Ed." );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "\"" );
			st.append ( tmp );
			st.append ( "\"" );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "volume" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "vol. " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "number" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "no. " );
			st.append ( tmp );
		}

		QString tmp2 = getFieldText ( bibItem, QString::fromLatin1 ( "address" ) ).simplifyWhiteSpace();
		if ( !tmp2.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp2 );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "publisher" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( tmp2.isEmpty() )
				st.append ( ", " );
			else
				st.append ( ": " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "year" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		if ( !st.isEmpty() )
			st.append ( "." );
	}

	else if ( strcmp ( bibItem->getEntryType(), "phdthesis" ) ==0 )
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "author" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "\"" );
			st.append ( tmp );
			st.append ( ",\"" );
		}
		st.append ( " Ph.D. thesis" );

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "school" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "address" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "year" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}
		st.append ( "." );


	}

	else if ( strcmp ( bibItem->getEntryType(), "masterthesis" ) ==0 )
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "author" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "\"" );
			st.append ( tmp );
			st.append ( ",\"" );
		}
		st.append ( " Master thesis" );

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "school" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "address" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "year" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}
		st.append ( "." );


	}

	else if ( strcmp ( bibItem->getEntryType(), "inbook" ) ==0 )
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "author" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "\"" );
			st.append ( tmp );
			st.append ( "\"" );
		}

	}


	else
	{
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "author" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			tmp = reformatAuthors ( tmp, 0 );
			st.append ( tmp );
		}
		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "title" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( "\"" );
			st.append ( tmp );
			st.append ( "\"" );
		}

		tmp = getFieldText ( bibItem, QString::fromLatin1 ( "year" ) ).simplifyWhiteSpace();
		if ( !tmp.isEmpty() )
		{
			if ( !st.isEmpty() )
				st.append ( ", " );
			st.append ( tmp );
		}

		if ( !st.isEmpty() )
			st.append ( "." );

	}
	return st;

}
